Underscore.php is a PHP port of the popular Underscore.js library. Underscore.php provides a utility library for PHP that provides a lot of the functional programming support that a programmer would expect in Ruby, but without adding much overhead during execution. The only caveat is that underscore.php requires PHP 5.3 or greater. Although you could accomplish some of the things using PHP’s built in functions, the functional style approach looks intuitive and easy to work with. Note that this not a purely functional programming like Haskell. It would be nice to integrate the library in your CakePHP framework, which will help bring some functional flavor to the framework.
Take a quick example of the ‘pluck’ method.
include_once('underscore.php'); $members= array( array('name'=>'bill', 'age'=>40, 'gender' => 'm'), array('name'=>'john', 'age'=>50, 'gender' => 'm'), array('name'=>'sarah','age'=>60, 'gender' => 'f') ); $ret = __::pluck($members, 'name'); print_r($ret); |
returns…
Array ( [0] => bill [1] => john [2] => sarah ) |
Here is another using the ‘map’ method.
$ret = __::map(array(1, 2, 3), function($num) { return $num * 3; }); print_r($ret); |
returns…
Array ( [0] => 3 [1] => 6 [2] => 9 ) |
Underscore.php works in both object-oriented and static styles. The following lines give the examples of both.
$members= array( array('name'=>'bill', 'age'=>40, 'gender' => 'm'), array('name'=>'john', 'age'=>50, 'gender' => 'm'), array('name'=>'sarah','age'=>60, 'gender' => 'f') ); /* Static style */ $ret = __::max($members, function($member) { return $member['age']; }); /* Object Oriented style */ $ret = __($members)->max(function($member) { return $member['age']; }); print_r($ret); |
returns…
Array ( [name] => sarah [age] => 60 [gender] => f ) |
Another example using the ‘template’ method.
$members = array( array('name'=>'bill', 'age'=>40, 'gender' => 'm'), array('name'=>'john', 'age'=>50, 'gender' => 'm'), array('name'=>'sarah','age'=>60, 'gender' => 'f') ); $template = '<% __::each($members, function($member) { %> <li><%= $member["name"] %></li> <% }); %>'; $ret = __::template($template, array('members'=>$members)); print_r($ret); |
returns…
<li>bill</li> <li>john</li> <li>sarah</li> |
How does it work
The underscore.php files defines a ‘__’ class which encapsulates all the functional methods and uses the functional programming ideas introduced in PHP 5.3.
// Underscore.php class __ { // Return an array of values by mapping each item through the iterator public function map($collection=null, $iterator=null) { ... } . . /* other methods */ } |
Presently the library supports the following methods.
Collections
each, map, reduce, reduceRight, detect, select, reject, all, any, includ, invoke, pluck, max, min, groupBy, sortBy, sortedIndex, toArray, size
Arrays
first, rest, last, compact, flatten, without, uniq, union, intersection, difference, zip, indexOf, lastIndexOf, range
Functions
memoize, throttle, once, after, wrap, compose
Objects
keys, values, functions, extend, defaults, clon, tap, isEqual, isEmpty, isObject, isArray, isFunction, isString, isNumber, isBoolean, isDate, isNaN, isNull
Utility
identity, times, mixin, uniqueId, template
Chaining
chain, value
Another attempt at this is the “Functional primitives for PHP”; which I believe does a better job at porting the Underscore.js functionality to proper PHP idioms. Check it out if you’re interested!
http://vvv.tobiassjosten.net/php/functional-primitives-for-php/