Pipelines

Table of Contents

  1. Introduction
  2. Using Closures
  3. Using Objects
    1. Using Classes
  4. Specifying a Callback

Introduction

In computer science, a pipeline refers to a series of stages where each stage's input is the previous one's output. It can be used to implement a decorator, which adds functionality to an object from an outside object. In Opulence, this is especially useful for HTTP middleware. Pipelines can accept a list of:

... to act as pipeline stages. You can even mix and match various types of stages.

Note: If a stage does not specifically call the $next closure, no stages after it in the pipeline will be run.

Using Closures

Closure stages must accept the input as their first parameter and the next pipe in the pipeline as the second parameter. Let's take a look at a simple example:

use Opulence\Pipelines\Pipeline;

$stages = [
    function ($input, $next) {
        $input++;

        return $next($input);
    },
    function ($input, $next) {
        $input += 2;

        return $next($input);
    }
];
echo (new Pipeline)
    ->send(0)
    ->through($stages)
    ->execute();

This will output:

3

Using Objects

Pipeline can also accept an array of objects and a method to call on those objects.

Note: The method MUST accept two parameters - the output from the previous stage and the next pipe in the pipeline.

use Closure;
use Opulence\Pipelines\Pipeline;

interface IMyPipe
{
    public function filter($input, Closure $next);
}

class PipeA implements IMyPipe
{
    public function filter($input, Closure $next)
    {
        $input++;

        return $next($input);
    }
}

class PipeB implements IMyPipe
{
    public function filter($input, Closure $next)
    {
        $input += 2;

        return $next($input);
    }
}

$stages = [new PipeA(), new PipeB()];
// We must pass in the name of the method to call ("filter")
echo (new Pipeline)
    ->send(1)
    ->through($stages, 'filter')
    ->execute();

This will output:

3

Using Classes

If you use the dependency injection container, you can also use class names as stages:

$classes = ['PipeA', 'PipeB'];
$stages = [];

foreach ($classes as $class) {
    $stages[] = $container->resolve($class);
}

echo (new Pipeline)
    ->send(1)
    ->through($stages, 'filter')
    ->execute();

This will output:

3

Specifying a Callback

To run a callback at the very end of the pipeline, pass in a Closure that accepts the pipeline's output as a parameter:

use Opulence\Pipelines\Pipeline;

$stages = [
    function ($input, $next) {
        $input++;

        return $next($input);
    },
    function ($input, $next) {
        $input += 2;

        return $next($input);
    }
];
echo (new Pipeline)
    ->send(1)
    ->through($stages)
    ->then(function ($output) {
        return $output + 3;
    })
    ->execute();

This will output:

5