A collection of functions and classes to provide some nice functional tools for your projects, with a simple, consistent and well tested api.
Especially useful to build data processing algorithms in a breeze.
Via Composer
$ composer require ibsciss/php-functionnalImagine you want to compute the total VAT amount for october:
Instead of doing things like this:
function compute_october_vat() {
$total_vat_amount = 0;
foreach ($invoices as $invoice) {
if ($invoice->due_date->format('m') == '10') {
$total_vat_amount += $invoice->amount * 0.2;
}
}
return $total_vat_amount;
}Or, if you want to try with map / reduce functions:
function compute_october_vat() {
return array_reduce(
array_map(
function($invoice) { return $invoice->amount * 0.2; },
array_filter( $invoices, function($invoice) { return $invoice->due_date->format('m') == '10'; } )
),
function($x, $y) { return $x + $y; }, 0);
}You can now use a more fluent api:
function compute_october_vat() {
return Fp\collection($invoices)
->filter( function($invoice) { return $invoice->due_date->format('m') == '10'; }; )
->map( function($invoice) { return $invoice->amount * 0.2; }; )
->add();
}The compose function give you the ability to create a new functions from existing functions:
compose(f,g,h)(x) == f(g(h(x)))
A practical example:
$plus_one = function($x) { return $x + 1; };
$square = function($x) { return pow($x, 2); };
$plus_one_and_square = Fp\compose($plus_one, $square);
$plus_one_and_square(2) //return 9Of course you can compose as much functions as you want.
Pipelines functions are useful to apply transformations to collections, Martin Fowler wrote a very good introduction (based on ruby) about it. On the same blog, you'll find another resource to learn how to refactor your too many loops using pipeline.
The map, filter and reduce functions are wrapper around the native php function, to understand why we have made them please see the FAQ.
Apply a function to each item of a collection to create a new array.
//square each item of the collection
Fp\map(
function($x) {
return pow($x, 2); //square function
}, [1,2,3]
); //return [1,4,9,16]Build an array composed with items that returns true when passed in the given callback.
//return even values from the collection
Fp\filter(
function($x) {
return ($x % 2 == 0);
},
[1,2,3,4]
); //return [2,4]It makes an accumulation by passing each item to the given callback. The callback returning value is returned for the next call (an init value is provided for the first call).
//sum values of the collection
Fp\reduce(
function($carry, $item) {
return $carray + $item
},
[1,2,3,4],
0
); //return 10You can chain operations by using the Fp\collection(collection) function (don't forget to call values() to get the results):
//squared even values from the given collection
Fp\collection([1,2,3,4])
->filter(
function($x) { return ($x % 2 == 0); }
)
->map(
function($x) { return pow($x, 2); }
)
->values(); With classical pipeline functions, you have to iterate the whole collection for each step of the transformation and create an intermediate collection which is a massive waste in memory usage.
Moreover you can't really extract a step to use it in other contexts which is bad for code reuse.
To tackle these downsides of classic pipeline function, the functional world come with a nice solution: tranducers.
like map
like filter
Use with single_result terminal reducer.
return the first element
return the max
Batch result
Create indexed tuples with results
append to an array
immutable appending by merge
to get a scalar result instead of a collection
- To improve api consistency
- To be able to produce transducers if the iterable is omitted
- To be able to consume
Collectionobjects.
Please see CHANGELOG for more information what has changed recently.
$ composer testPlease see CONTRIBUTING for details.
If you discover any security related issues, please email :author_email instead of using the issue tracker.
The MIT License (MIT). Please see License File for more information.


