sanmai/pipeline
sanmai/pipeline is a lightweight PHP pipeline library to process data through a chain of stages. Compose reusable, testable transformations with clear input/output flow, and plug in custom middleware-like steps for flexible processing in any app.
You can initialize a pipeline from an array using the Pipeline\Standard constructor or the take() and fromArray() helper functions.
use Pipeline\Standard;
use function Pipeline\take;
use function Pipeline\fromArray;
// Using the constructor
$pipeline = new Standard([1, 2, 3]);
// Using the take() helper
$pipeline = take([1, 2, 3]);
// Using the fromArray() helper
$pipeline = fromArray([1, 2, 3]);
The recommended way to use the library is with iterables, which allows for lazy processing of data.
// From a generator
function generateNumbers() {
for ($i = 1; $i <= 5; $i++) {
yield $i;
}
}
$pipeline = take(generateNumbers());
// From an iterator
$iterator = new ArrayIterator([1, 2, 3]);
$pipeline = take($iterator);
// From a file
$file = new SplFileObject('data.txt');
$pipeline = take($file);
The fromValues() helper function creates a pipeline from a sequence of arguments.
use function Pipeline\fromValues;
$pipeline = fromValues(1, 2, 3, 4, 5);
You can also create an empty pipeline and add data to it later.
$pipeline = new Standard();
$pipeline->append([1, 2, 3]);
map() - Transform Each ElementThe map() method applies a callback to each element in the pipeline.
use function Pipeline\take;
// Double each number
$result = take([1, 2, 3])
->map(fn($x) => $x * 2)
->toList(); // [2, 4, 6]
// Note: With arrays, some operations like filter() execute immediately.
// Use ->stream() first if you need lazy processing throughout.
// Extract a property from an array of objects
$users = [
['name' => 'Alice', 'age' => 30],
['name' => 'Bob', 'age' => 25],
];
$names = take($users)
->map(fn($user) => $user['name'])
->toList(); // ['Alice', 'Bob']
filter() - Remove ElementsThe filter() method removes elements that do not pass a given test.
// Keep only even numbers
$result = take([1, 2, 3, 4, 5, 6])
->filter(fn($x) => $x % 2 === 0)
->toList(); // [2, 4, 6]
// With no arguments, filter() removes falsy values
$result = take([0, 1, false, 2, null, 3, '', 4])
->filter()
->toList(); // [1, 2, 3, 4]
cast() - Type Cast ElementsThe cast() method provides a simple way to change the type of elements.
// Convert strings to integers
$result = take(['1', '2', '3'])
->cast(intval(...))
->toList(); // [1, 2, 3]
// Convert strings to uppercase
$result = take(['hello', 'world'])
->cast(strtoupper(...))
->toList(); // ['HELLO', 'WORLD']
append() and push()Use append() to add the contents of an iterable to the end of the pipeline, or push() to add individual elements.
$result = take([1, 2, 3])
->append([4, 5, 6])
->toList(); // [1, 2, 3, 4, 5, 6]
$result = take([1, 2, 3])
->push(4, 5, 6)
->toList(); // [1, 2, 3, 4, 5, 6]
prepend() and unshift()Use prepend() to add the contents of an iterable to the beginning of the pipeline, or unshift() to add individual elements.
$result = take([4, 5, 6])
->prepend([1, 2, 3])
->toList(); // [1, 2, 3, 4, 5, 6]
$result = take([4, 5, 6])
->unshift(1, 2, 3)
->toList(); // [1, 2, 3, 4, 5, 6]
toList() - Indexed ArrayThe toList() method consumes the pipeline and returns a new array with numeric keys.
$result = take(['a' => 1, 'b' => 2, 'c' => 3])
->map(fn($x) => $x * 2)
->toList(); // [2, 4, 6]
toAssoc() - Associative ArrayThe toAssoc() method preserves the original keys.
$result = take(['a' => 1, 'b' => 2, 'c' => 3])
->map(fn($x) => $x * 2)
->toAssoc(); // ['a' => 2, 'b' => 4, 'c' => 6]
reduce() and fold() - Single ValueUse reduce() or fold() to reduce the pipeline to a single value.
// Sum all values
$sum = take([1, 2, 3, 4, 5])->reduce(fn($a, $b) => $a + $b); // 15
// Calculate a product
$product = take([1, 2, 3, 4, 5])
->fold(1, fn($carry, $item) => $carry * $item); // 120
$orders = [
['id' => 1, 'total' => 100, 'status' => 'paid'],
['id' => 2, 'total' => 200, 'status' => 'pending'],
['id' => 3, 'total' => 150, 'status' => 'paid'],
];
$paidTotal = take($orders)
->filter(fn($order) => $order['status'] === 'paid')
->map(fn($order) => $order['total'])
->reduce(fn($a, $b) => $a + $b);
// Result: 250
// Count error lines in a log file
$errorCount = take(new SplFileObject('app.log'))
->filter(fn($line) => str_contains($line, 'ERROR'))
->count();
// Process a CSV file
$data = take(new SplFileObject('data.csv'))
->map(str_getcsv(...))
->filter(fn($row) => count($row) === 3)
->toList();
function getPage(iterable $data, int $page, int $perPage = 10): array
{
$offset = ($page - 1) * $perPage;
return take($data)
->slice($offset, $perPage)
->toList();
}
$page2 = getPage(range(1, 100), 2, 10);
// [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
How can I help you explore Laravel packages today?