Darren Mothersele

Software Developer

Warning: You are viewing old, legacy content. Kept for posterity. Information is out of date. Code samples probably don't work. My opinions have probably changed. Browse at your own risk.

PHP Processing Pipeline

Feb 11, 2016

web-dev

If you’re faced with refactoring a huge bunch of sequential code then a pipeline may be the answer. With a processing pipeline you create your code in stages. Then you compose the stages into a pipeline, and pass your input for processing.

This is great because each of the stages can be easily tested independently. It also makes the code much easier to read and maintain.

There’s a nice and simple implementation published by the League of Extraordinary Packages. I’ve created a fork (on GitHub here) which offers an even simpler syntax.

Here’s a very basic example to show off this new syntax. You create your stages as simple classes with an invoke method. For example:

class Double {
    public function __invoke($payload)
    {
        return $payload * 2;
    }
}

class Square {
    public function __invoke($payload)
    {
        return $payload * $payload;
    }
}

You could even pass in parameters to the stage constructor:

class Add {
    private $i;
    public function __construct($i)
    {
        $this->i = $i;
    }
    public function __invoke($payload)
    {
        return $payload + $this->i;
    }
}

Then create a Pipeline to chain the stages together:

$pipe = (new Pipeline)->Double()->Square()->Add(10);

And then you can process values using the Pipeline:

echo $pipe->process(10), PHP_EOL;

You can even process a list of values:

var_dump(array_map($pipe, [1, 2, 3]));

Obviously you are not just limited to processing integers as in these examples. XML documents, converting to JSON, filtering, translating and other transformations are great candidates for pipelines stages.

I’ve submitted a pull request for my simple modification. All I did was add an implementation of the __call() method so you can add stages without having to explicitly new-up objects and pass them into the pipe() method.

Hopefully my pull request gets accepted. The only thing to be aware of is that I made use of the variadic operator, so it needs a PHP version of 5.6 or greater.