A set of functional primitives for PHP, heavily inspired by Scala’s traversable collection, Dojo’s array functions and Underscore.js
- Works with arrays and everything implementing interface
Traversable - Consistent interface: for functions taking collections and callbacks, first parameter is always the collection, than the callback.
Callbacks are always passed
$value,$index,$collection. Strict comparison is the default but can be changed - Calls 5.3 closures as well as usual callbacks
- All functions reside in namespace
Functionalto not raise conflicts with any other extension or library
Put the require statement for functional-php in your composer.json file and run php composer.phar install:
{
"require": {
"lstrojny/functional-php": "~1.2"
}
}Checkout functional-php and include the _import.php
<?php
include 'path/to/functional-php/src/Functional/_import.php';<<<<<<< HEAD
Everytime you want to work with Functional PHP and not reference the fully qualified name, add use Functional as F; on top of
your PHP file.
Functional\every(array|Traversable $collection, callable $callback)
array Functional\invoke(array|Traversable $collection, string $methodName[, array $methodArguments])
mixed Functional\invoke_first(array|Traversable $collection, string $methodName[, array $methodArguments])
mixed Functional\invoke_last(array|Traversable $collection, string $methodName[, array $methodArguments])
<?php
use Functional as F;
// If all users are active, set them all inactive
if (F\every($users, function($user, $collectionKey, $collection) {return $user->isActive();})) {
F\invoke($users, 'setActive', array(false));
}mixed Functional\invoke_if(mixed $object, string $methodName[, array $methodArguments, mixed $defaultValue])
<?php
use Functional as F;
// if $user is an object and has a public method getId() it is returned,
// otherwise default value 0 (4th argument) is used
$userId = F\invoke_if($user, 'getId', array(), 0);bool Functional\some(array|Traversable $collection, callable $callback)
<?php
use Functional as F;
if (F\some($users, function($user, $collectionKey, $collection) use($me) {return $user->isFriendOf($me);})) {
// One of those users is a friend of me
}bool Functional\none(array|Traversable $collection, callable $callback)
<?php
use Functional as F;
if (F\none($users, function($user, $collectionKey, $collection) {return $user->isActive();})) {
// Do something with a whole list of inactive users
}array Functional\select(array|Traversable $collection, callable $callback)
array Functional\reject(array|Traversable $collection, callable $callback)
<?php
use Functional as F;
$fn = function($user, $collectionKey, $collection) {
return $user->isActive();
};
$activeUsers = F\select($users, $fn);
$inactiveUsers = F\reject($users, $fn);Alias for Functional\select() is Functional\filter()
array Functional\drop_first(array|Traversable $collection, callable $callback)
array Functional\drop_last(array|Traversable $collection, callable $callback)
<?php
use Functional as F;
$fn = function($user, $index, $collection) {
return $index === 3;
};
// All users except the first three
F\drop_first($users, $fn);
// First three users
F\drop_last($users, $fn);Pick a single element from a collection of objects or an array by index. If no such index exists, return the default value.
array Functional\pick(array|Traversable $collection, mixed $propertyName, mixed $default, callable $callback)
<?php
use Functional as F;
$array = array('one' => 1, 'two' => 2, 'three' => 3);
F\pick($array, 'one'); //return 1;
F\pick($array, 'ten'); //return null;
F\pick($array, 'ten', 10); //return 10;Fetch a single property from a collection of objects or arrays.
array Functional\pluck(array|Traversable $collection, string|integer|float|null $propertyName)
<?php
use Functional as F;
$names = F\pluck($users, 'name');Splits a collection into two by callback. Truthy values come first
array Functional\partition(array|Traversable $collection, callable $callback)
<?php
use Functional as F;
list($admins, $users) = F\partition($collection, function($user) {
return $user->isAdmin();
});###Functional\group() Splits a collection into groups by the index returned by the callback
array Functional\group(array|Traversable $collection, callable $callback)
<?php
use Functional as F;
$groupedUser = F\group($collection, function($user) {
return $user->getGroup()->getName();
});Applies a callback to each element in the collection and reduces the collection to a single scalar value.
Functional\reduce_left() starts with the first element in the collection, while Functional\reduce_right() starts
with the last element.
mixed Functional\reduce_left(array|Traversable $collection, callable $callback[, $initial = null])
mixed Functional\reduce_right(array|Traversable $collection, callable $callback[, $initial = null])
<?php
use Functional as F;
// $str will be "223"
$str = F\reduce_left(array(2, 3), function($value, $index, $collection, $reduction) {
return $reduction . $value;
}, 2);
// $str will be "232"
$str = F\reduce_right(array(2, 3), function($value, $index, $collection, $reduction) {
return $reduction . $value;
}, 2);Takes a nested combination of collections and returns their contents as a single, flat array. Does not preserve indexes.
array Functional\flatten(array|Traversable $collection)
<?php
use Functional as F;
$flattened = F\flatten(array(1, 2, 3, array(1, 2, 3, 4), 5));
// array(1, 2, 3, 1, 2, 3, 4, 5);Returns the first index holding specified value in the collection. Returns false if value was not found
int|string Functional\first_index_of(array|Traversable $collection, mixed $value)
<?php
use Functional as F;
// $index will be 0
$index = F\first_index_of(array('value', 'value'), 'value');Returns the last index holding specified value in the collection. Returns false if value was not found
int|string Functional\last_index_of(array|Traversable $collection, mixed $value)
<?php
use Functional as F;
// $index will be 1
$index = F\last_index_of(array('value', 'value'), 'value');Returns true or false if all elements in the collection are strictly true or false
bool Functional\true(array|Traversable $collection)
bool Functional\false(array|Traversable $collection)
<?php
use Functional as F;
// Returns true
F\true(array(true, true));
// Returns false
F\true(array(true, 1));
// Returns true
F\false(array(false, false, false));
// Returns false
F\false(array(false, 0, null, false));Returns true or false if all elements in the collection evaluate to true or false
bool Functional\truthy(array|Traversable $collection)
bool Functional\falsy(array|Traversable $collection)
<?php
use Functional as F;
// Returns true
F\truthy(array(true, true, 1, 'foo'));
// Returns false
F\truthy(array(true, 0, false));
// Returns true
F\falsy(array(false, false, 0, null));
// Returns false
F\falsy(array(false, 'str', null, false));Returns true if given collection contains given element. If third parameter is true, the comparison will be strict
bool Functional\contains(array|Traversable $collection, mixed $value[, bool $strict = false])
<?php
use Functional as F;
// Returns true
F\contains(array('el1', 'el2'), 'el1');
// Returns false
F\contains(array('0', '1', '2'), 2);
// Returns true
F\contains(array('0', '1', '2'), 2, false);Recombines arrays by index and applies a callback optionally
array Functional\zip(array|Traversable $collection1[, array|Traversable ...[, callable $callback]])
<?php
use Functional as F;
// Returns array(array('one', 1), array('two', 2), array('three', 3))
F\zip(array('one', 'two', 'three'), array(1, 2, 3));
// Returns array('one|1', 'two|2', 'three|3')
F\zip(
array('one', 'two', 'three'),
array(1, 2, 3),
function($one, $two) {
return $one . '|' . $two;
}
);Invoke a callback on a value if the value is not null
<?php
use Functional as F;
F\with($value, function($value) {
$this->doSomethingWithValue($value);
});void Functional\each(array|Traversable $collection, callable $callback)
Applies a callback to each element
array Functional\map(array|Traversable $collection, callable $callback)
Applies a callback to each element in the collection and collects the return value
mixed Functional\first(array|Traversable $collection[, callable $callback])
mixed Functional\head(array|Traversable $collection[, callable $callback])
Returns the first element of the collection where the callback returned true. If no callback is given, the first element
is returned
mixed Functional\last(array|Traversable $collection[, callable $callback])
Returns the last element of the collection where the callback returned true. If no callback is given, the last element
is returned
mixed Functional\tail(array|Traversable $collection[, callable $callback])
Returns every element of the collection except the first one. Elements are optionally filtered by callback.
integer|float Functional\product(array|Traversable $collection, $initial = 1)
Calculates the product of all numeric elements, starting with $initial
integer|float Functional\ratio(array|Traversable $collection, $initial = 1)
Calculates the ratio of all numeric elements, starting with $initial
integer|float Functional\sum(array|Traversable $collection, $initial = 0)
Calculates the sum of all numeric elements, starting with $initial
integer|float Functional\difference(array|Traversable $collection, $initial = 0)
Calculates the difference of all elements, starting with $initial
integer|float|null Functional\average(array|Traversable $collection)
Calculates the average of all numeric elements
array Functional\unique(array|Traversable $collection[, callback $indexer[, bool $strict = true]])
Returns a unified array based on the index value returned by the callback, use $strict to change comparison mode
mixed Functional\maximum(array|Traversable $collection)
Returns the highest element in the array or collection
mixed Functional\minimum(array|Traversable $collection)
Returns the lowest element in the array or collection
mixed Functional\memoize(callable $callback[, array $arguments = array()], [mixed $key = null]])
Returns and stores the result of the function call. Second call to the same function will return the same result without calling the function again
=======
To run the test suite use vendor/bin/phpunit tests/
- General help and development list: http://groups.google.com/group/functional-php
- Commit list: http://groups.google.com/group/functional-php-commits
- Richard Quadling and Pierre Joye for Windows build help
- David Soria Parra for various ideas and the userland version of
Functional\flatten() - Max Beutel for
Functional\unique(),Functional\invoke_first(),Functional\invoke_last()and all the discussions - The people behind Travis CI for continuous integration



