ksassnowski/pipeline

View on GitHub
README.md

Summary

Maintainability
Test Coverage
# PHP Pipeline

[![Build Status](https://travis-ci.org/ksassnowski/pipeline.svg?branch=master)](https://travis-ci.org/ksassnowski/pipeline)
[![Code Climate](https://codeclimate.com/github/ksassnowski/pipeline/badges/gpa.svg)](https://codeclimate.com/github/ksassnowski/pipeline)
[![Test Coverage](https://codeclimate.com/github/ksassnowski/pipeline/badges/coverage.svg)](https://codeclimate.com/github/ksassnowski/pipeline/coverage)
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/8ae76ac2-6bf7-4723-b2bc-4ad61e0e8381/mini.png)](https://insight.sensiolabs.com/projects/8ae76ac2-6bf7-4723-b2bc-4ad61e0e8381)

A simple Pipeline implementation for PHP.

## Summary

This package enables you to send a value through a sequence of steps. Each step operates on the return
value of the previous step. Without a pipeline you would end up with deeply nested function calls like this.

```php
fn5(fn4(fn3(fn2(fn1($initialValue)))));
```

Using a pipeline you can transform the above example to this:

```php
Pipeline::pipe($initialValue)
    ->through($fn1)
    ->through($fn2)
    ->through($fn3)
    ->through($fn4)
    ->through($fn5)
    ->run();
```

This makes the order of steps executed a lot clearer and gets rid of the annoying and ugly nesting of function calls.

## Usage

```php
use Sassnowski\Pipeline\Pipeline;

Pipeline::pipe(10)
    ->through(function ($i) { return $i + 10; })
    ->run();
// 11
```

## Building reusable pipelines

The `through($fn)` method does not change the existing Pipeline, but instead returns a new Pipeline instance that includes
the next step. This enables you to reuse parts of a pipeline.

Since seeding the pipeline with an initial value goes against the idea of reusability, an additional method `build()` is defined.
The `build` method does not initialize the pipeline with value. In this case the value has to be provided when calling the `run` method.

```php
$pipeline1 = Pipeline::build()->through(function ($i) { return $i + 1 });

// Use the existing pipeline and simply add on additional steps.
$pipeline2 = $pipeline1->through(function ($i) { return $i * 10; });

// The initial pipeline remains unchanged.
$pipeline1->run(10); // 11

$pipeline2->run(10); // 110
```

## Class-based steps

It is possible to use classes as steps instead of function. All the class has to do is implement the magic `__invoke` method.

```php
class Add10
{
    function __invoke($i)
    {
        return $i + 10;
    }
}

// Somewhere else
Pipeline::pipe(10)
    ->through(new Add10)
    ->run();
// 20
```

This is useful if the execution of a step requires a lot of additional business logic that does not belong inside the object
containing the Pipeline.

## Exceptions

If a step is added to the pipeline that fails the `is_callable` check an `InvalidArgumentException` will be thrown.

```php
Pipeline::pipe(10)->through(10); // InvalidArgumentException
```

If the `build` method was used to create a pipeline, the initial value has to be passed to then `run` method. Failing to do so
will result in a `RuntimeException`.

```php
Pipeline::build()->through(function ($i) { return $i + 10; })->run() // RuntimeException
```

## Method aliases

In order to enable a more easily readable syntax when building a pipeline several method aliases for the `through` method exist.

* `firstThrough()`
* `andThen()`

```php
Pipeline::pipe(10)
    ->firstThrough($fn1)
    ->andThen($fn2)
    ->andThen($fn3)
    ->run();
```

## License

MIT