lstrojny/functional-php
Functional PHP adds a rich set of functional programming helpers for PHP: map/filter/reduce, partial application, currying, composition, and collections utilities. Write cleaner, more declarative code without changing your framework or coding style.
Installation Add via Composer:
composer require lstrojny/functional-php
No Laravel-specific configuration is needed—this is a pure PHP package.
First Use Case: Data Transformation
Replace a foreach loop with map:
use function Functional\map;
$numbers = [1, 2, 3];
$doubled = map($numbers, fn($n) => $n * 2); // [2, 4, 6]
Key Entry Points
Functional\* namespace: Core functions (e.g., map, filter, reduce).Functional\Collection: Immutable collection utilities (e.g., from, pipe).collect()->pipe(fn($c) => Functional\map($c->all(), ...)).Chain operations immutably:
use function Functional\{map, filter, reduce};
$result = reduce(
map(
filter($users, fn($u) => $u['active']),
fn($u) => $u['id']
),
[],
fn($acc, $id) => [...$acc, $id],
[]
);
Combine with Laravel’s Collection for SQL-like operations:
$activeUsers = collect($users)
->filter(fn($u) => $u['active'])
->pipe(fn($c) => Functional\map($c->values(), fn($u) => $u['name']));
Pre-bind arguments to functions:
use function Functional\partial;
$addFive = partial('+', 5);
$result = $addFive(3); // 8
Break multi-argument functions into single-argument steps:
use function Functional\curry;
$add = curry(fn($a, $b) => $a + $b);
$addFive = $add(5);
$result = $addFive(3); // 8
Use try/catch with functional style:
use function Functional\{try, catch};
$safeDivide = try(fn($a, $b) => $a / $b, fn($e) => 0);
$result = $safeDivide(10, 0); // 0
Write declarative tests:
$this->assertEquals(
[1, 2, 3],
Functional\map([1, 2, 3], fn($n) => $n)
);
Immutability Overhead
Functional\Collection::from() for large datasets to optimize memory.Closure Scope Issues
map/filter may not capture expected variables if not declared use.$threshold = 10;
$filtered = filter($items, fn($item) => $item > $threshold);
Laravel Collection Conflicts
Functional\map with Laravel’s Collection::map directly (e.g., map($collection) fails).Functional\map($collection->all(), ...);
Lazy Evaluation Misuse
lazy/flatMap require understanding of lazy sequences.toArray() or reduce when needed.Inspect Intermediate Steps
Use Functional\tap to log/debug:
$result = tap($data, fn($d) => Log::debug('Data:', $d))
->pipe(fn($d) => map($d, ...));
Type Safety
@var hints in IDEs (e.g., PhpStorm) for functional chains.Performance Profiling
memory_get_usage() for large datasets.Custom Combinators Extend with your own higher-order functions:
function customMap($collection, callable $fn) {
return Functional\map($collection, $fn);
}
Laravel Service Providers Bind functional helpers to Laravel’s container:
$this->app->bind('functional', fn() => new Functional\Collection());
DSL for Domain Logic Create domain-specific functions:
function calculateTax($items) {
return reduce($items, 0, fn($acc, $item) => $acc + ($item['price'] * 0.2));
}
Integration with Livewire/Alpine Use functional style in component logic:
public function mount() {
$this->filteredItems = filter($this->items, fn($item) => $item['visible']);
}
How can I help you explore Laravel packages today?