Skip to content

bdelespierre/php-underscore

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status

» Table of contents

Underscore.php

PHP lacks consistency, that's a fact. Many functions within a similar field — for instance array functions — may have inconsistent names and prototypes. Underscore.php aims to correct that by providing simple, consistent and data-type tolerant 80-odd functions that support both the usual functional suspects: map, select, invoke — as well as more specialized helpers: function binding, php templating, deep equality testing, and so on.

Underscore.php is strongly inspired by Underscore.js and try to be consistent with it as much as possible (PHP language limitation doesn't allow full coverage — especialy for Functions functions...) Don't hesitate to report any discrepancy with Underscore.js.

Features

  • Made with ♥ for PHP 5.4+
  • Type tolerant
  • Triggers exceptions instead of errors
  • Consistent function names / arguments
  • Hassle-free chaining
  • ERB-style templating
  • Extensible

Heads up!

This library is in beta phase: you are strongly encouraged to try it and to contribute.Feel free to file an issue if you encounter a bug or an unexpected result.

About data-type tolerance

Juggling with types in PHP can be tedious. Not only types are sometimes ambiguous, they don't fit in every API function/method. For instance, if you want to map every item from an iterator using array_map, you have to translate it into an array first or write the mapping yourself using a loop. Same goes for sort, diff or filter...

PHP is loosely typed, which means that the data you're manipulating are more important than their structure. Underscore.php understands that by providing a comprehensive interface that works with almost every data-type so you don't have to worry about whether you can or cannot use a function/method.

Basically, Underscore.php uses 3 main data-types:

  • Scalar (integer, float, boolean, or string)
  • Traversable (array, object, or iterator)
  • Callable (closure, function, method, or runtime-created function)

When a fuction requires a Traversable as argument, you can provide either an array, an instance of stdClass — the default (object) casting — an Iterator or anything that implements the Traversable interface, such as a PDOStatement object. With certain functions like #extend, you can even extend an array with an object instance and everything will be fine.

<?php
// let's merge our configuration object with data from $_SESSION and MySQL
$userConfig = _::extend([],
	include "global.conf.php",              // is an array
	$pdo->query($groupConfigurationQuery)   // is a PDOStatement
	$_SESSION['user']->configuration,       // is an object
);
?>

Table of contents

  1. Installation
  2. Usage
  3. Collection Functions
  4. Uncategorized
  5. Array Functions
  6. Function (uh, ahem) Functions
  7. Object Functions
  8. Utility Functions
  9. Chaining
  10. Class Forgery

Installation

Composer

Add the following require rule to composer.json and run composer update. See the Packagist repository for more details.

require: { "bdelespierre/underscore": "dev-master" }
With Git
git clone https://github.com/bdelespierre/underscore.php ./underscore.php
Manual
curl -sS https://github.com/bdelespierre/underscore.php/archive/master.zip > underscore.php.zip
unzip underscore.php.zip && rm underscore.zip

Or simply download the zip and extract it where you want.

Usage

Composer
<?php
require_once "vendor/autoload.php";

use Underscore\Underscore as _;

_::each([1,2,3], function ($i) { echo "{$i}\n"; });
?>
Manual
<?php
require_once "path/to/underscore/src/Underscore/Underscore.php";
require_once "path/to/underscore/src/Underscore/Bridge.php";

use Underscore\Underscore as _;

_::each([1,2,3], function ($i) { echo "{$i}\n"; });
?>
Functions

Underscore functions can also be used as procedural functions. To do so, include the functions.php library. The only limitation is that you cannot dynamically add new functions with _::mixin.

<?php
require_once "path/to/underscore/src/functions.php";

_each([1,2,3], function ($i) { echo "{$i}\n"; });
?>

Collection Functions

each


Description: Iterates over a list of elements, yielding each in turn to an iterator function. The iterator is bound to the context object, if one is passed. Each invocation of iterator is called with three arguments: (element, index, list). If list is an object, iterator's arguments will be (value, key, list).

Parameters
  • list: traversable, the list to iterate over
  • iterator: callable, the iteration function
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::each(list,iterator,context)
Examples
<?php
_::each([1,2,3], function ($i) { echo $i; });
// => 123

_::each((object)['a'=>1,'b'=>2,'c'=>3], function ($value, $key) { echo "$key => $value\n"; });
// => displays each pair in turn
?>

Table of contents » Collection Functions

eachReference


Alias: walk

Description: Does the very same job as each but provide a reference of every list item to the iterator function.

Parameters
  • list: traversable, the list to iterate over
  • iterator: callable, the iteration function
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::eachReference(list,iterator,context)
Examples
<?php
$numbers = [1,2,3];
_::eachReference($numbers, function (& $value) { $value *= $value; });
// => [1,4,9]
?>

Table of contents » Collection Functions

map


Alias: collect

Description: Produces a new array of values by mapping each value in list through a transformation function (iterator). The iterator is bound to the context object, if one is passed. Each invocation of iterator is called with three arguments: (element, index, list). If list is an object, iterator's arguments will be (value, key, list).

Parameters
  • list: traversable, the list of items to map
  • iterator: callable, the transformation function
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::map(list,iterator,context)
Examples
<?php
_::map([1,2,3], function ($value) { return $value -1; });
// => [0,1,2]
?>

Table of contents » Collection Functions

reduce


Alias: inject, foldl

Description: Also known as inject and foldl, reduce boils down a list of values into a single value. Memo is the initial state of the reduction, and each successive step of it should be returned by iterator. The iterator is passed four arguments: the memo, then the value and index (or key) of the iteration, and finally a reference to the entire list.

Parameters
  • list: traversable, the list of items to reduce
  • iterator: callable, the reduction function
  • memo: mixed, The initial reduction state
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::reduce(list,iterator,memo,context)
Examples
<?php
$sum = _::reduce([1,2,3], function ($memo, $num) { return $memo + $num; }, 0);
// => 6
?>

Table of contents » Collection Functions

reduceRight


Alias: foldr

Description: The right-associative version of reduce.

Parameters
  • list: traversable, the list of items to reduce
  • iterator: callable, the reduction function
  • memo: mixed, The initial reduction state
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::reduceRight(list,iterator,memo,context)
Examples
<?php
$list = [[0, 1], [2, 3], [4, 5]];
$flat = _::reduceRight($list, function ($a, $b) { return array_merge($a, $b); }, []);
// => [4,5,2,3,0,1]
?>

Table of contents » Collection Functions

find


Alias: detect

Description: Looks through each value in the list, returning the first one that passes a truth test (iterator), or null if no value passes the test. The function returns as soon as it finds an acceptable element, and doesn't traverse the entire list.

Parameters
  • list: traversable, the list of items to iterate over
  • iterator: callable, the truth-test function
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::find(list,iterator,context)
Examples
<?php
$even = _::find([1,2,3,4,5,6], function ($num) { return $num % 2 == 0; });
// => 2
?>

Table of contents » Collection Functions

filter


Alias: select

Description: Looks through each value in the list, returning an array of all the values that pass a truth test (iterator). If iterator isn't provided, each value will be evaluated as a boolean.

Parameters
  • list: traversable, the list of items to filter
  • iterator: callable, the filtering function
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::filter(list,iterator,context)
Examples
<?php
$evens = _::filter([1,2,3,4,5,6], function ($num) { return $num % 2 == 0; });
// => [2,4,6]
?>

Table of contents » Collection Functions

where


Description: Looks through each value in the list, returning an array of all the values that contain all of the key-value pairs listed in properties.

Parameters
  • list: traversable, the list of items to filter
  • properties: traversable, the key-values pairs each filtered item must match
Prototype
_::where(list,properties)
Examples
<?php
$people = [
    ['name' => 'Jack Nicholson',    'born' => 1937, 'profession' => 'actor'],
    ['name' => 'Morgan Freeman',    'born' => 1937, 'profession' => 'actor'],
    ['name' => 'Leonardo Dicaprio', 'born' => 1974, 'profession' => 'actor'],
    ['name' => 'Nathalie Portman',  'born' => 1981, 'profession' => 'actor'],
    ['name' => 'Ridley Scott',      'born' => 1937, 'profession' => 'producer'],
];

$actorsBornIn1937 = _::where($people, ['born' => 1937, 'profession' => 'actor']);
// => Jack Nicholson & Morgan Freeman
?>

Table of contents » Collection Functions

findWhere


Description: Looks through the list and returns the first value that matches all of the key-value pairs listed in properties.

Parameters
  • list: traversable, the list of items to filter
  • properties: traversable, the key-values pairs each filtered item must match
Prototype
_::findWhere(list,properties)
Examples
<?php
$people = [
    ['name' => 'Jack Nicholson',    'born' => 1937, 'profession' => 'actor'],
    ['name' => 'Morgan Freeman',    'born' => 1937, 'profession' => 'actor'],
    ['name' => 'Leonardo Dicaprio', 'born' => 1974, 'profession' => 'actor'],
    ['name' => 'Nathalie Portman',  'born' => 1981, 'profession' => 'actor'],
    ['name' => 'Ridley Scott',      'born' => 1937, 'profession' => 'producer'],
];

$actor = _::findWhere($people, ['born' => 1937, 'profession' => 'actor']);
// => Jack Nicholsonn
?>

Table of contents » Collection Functions

reject


Description: Returns the values in list without the elements that the truth test (iterator) passes. The opposite of filter.

Parameters
  • list: traversable, the list of items to filter
  • iterator: callable, the truth-test function
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::reject(list,iterator,context)
Examples
<?php
$odds = _::reject([1,2,3,4,5,6], function ($num) { return $num % 2 == 0; });
// => [1,3,5]
?>

Table of contents » Collection Functions

every


Alias: all

Description: Returns true if all of the values in the list pass the iterator truth test. Short-circuits and stops traversing the list if a false element is found.

Parameters
  • list: traversable, the list of items to filter
  • iterator: callable, the truth-test function
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::every(list,iterator,context)
Examples
<?php
_::every([true, 1, null, 'yes']);
// => false
?>

Table of contents » Collection Functions

some


Alias: any

Description: Returns true if any of the values in the list pass the iterator truth test. Short-circuits and stops traversing the list if a true element is found.

Parameters
  • list: traversable, the list of items to filter
  • iterator: callable, the truth-test function
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::some(list,iterator,context)
Examples
<?php
_::some([null, 0, 'yes', false]);
// => true
?>

Table of contents » Collection Functions

contains


Alias: includes

Description: Returns true if the value is present in the list.

Parameters
  • list: traversable, the list of items
  • value: mixed, the value to look for
  • strict: boolean, type of value is also used in coparision
Prototype
_::contains(list,value,strict)
Examples
<?php
_::contains([1,2,3], 3);
// => true
?>

Table of contents » Collection Functions

invoke


Description: Calls the method named by methodName on each value in the list. Any extra arguments passed to invoke will be forwarded on to the method invocation. If your list items are arrays (instead of objects) methods from ArrayObject can be used (like asort). If the wanted method is not found on the current item during iteration, the item will be left untouched.

Parameters
  • list: traversable, the list of items to invoke method/function onto
  • methodName: callable,string, the name of the method to invoke or a closure
  • arguments: array, the method's arguments
Prototype
_::invoke(list,methodName,arguments)
Examples
<?php
_::invoke([[5, 1, 7], [3, 2, 1]], 'sort');
// => [[1, 5, 7], [1, 2, 3]
?>

Table of contents » Collection Functions

pluck


Description: A convenient version of what is perhaps the most common use-case for map: extracting a list of property values.

Parameters
  • list: traversable, the list of items
  • propertyName: string, the name of the property to extract from each item
Prototype
_::pluck(list,propertyName)
Examples
<?php
$stooges = [
    ['name' => 'moe',   'age' => 40],
    ['name' => 'larry', 'age' => 50],
    ['name' => 'curly', 'age' => 60]
];
_::pluck($stooges, 'name');
// => ['moe','larry','curly']
?>

Table of contents » Collection Functions

max


Description: Returns the maximum value in list. If iterator is passed, it will be used on each value to generate the criterion by which the value is ranked.

Parameters
  • list: traversable, the list of items
  • iterator: callable, optional, the comparision function
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::max(list,iterator,context)
Examples
<?php
$stooges = [
    ['name' => 'moe',   'age' => 40],
    ['name' => 'larry', 'age' => 50],
    ['name' => 'curly', 'age' => 60]
];
_::max($stooges, function($stooge) { return $stooge['age']; });
// => 60
?>

Table of contents » Collection Functions

min


Description: Returns the minimum value in list. If iterator is passed, it will be used on each value to generate the criterion by which the value is ranked.

Parameters
  • list: traversable, the list of items
  • iterator: mixed, no description available...
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::min(list,iterator,context)
Examples
<?php
$numbers = [10, 5, 100, 2, 10000];
_::min($numbers);
// => 2
?>

Table of contents » Collection Functions

sortBy


Description: Returns a (stably) sorted copy of list, ranked in ascending order by the results of running each value through iterator. Returns NULL in case of error.

Parameters
  • list: traversable, the list of items to sort
  • iterator: callable, the function that generates the criteria by which items are sorted
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::sortBy(list,iterator,context)
Examples
<?php
_::sortBy([1, 2, 3, 4, 5, 6], function($num) { return sin($num); });
// => [5, 4, 6, 3, 1, 2]
?>

Table of contents » Collection Functions

indexBy


Description: Given a list, and an iterator function that returns a key for each element in the list (or a property name), returns an object with an index of each item. Just like groupBy, but for when you know your keys are unique.

Parameters
  • list: traversable, the list of items to index
  • iterator: callable,scalar, the function to generate the key or a property name
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::indexBy(list,iterator,context)
Examples
<?php
$stooges = [
    ['name' => 'moe',   'age' => 40],
    ['name' => 'larry', 'age' => 50],
    ['name' => 'curly', 'age' => 60]
];
_::indexBy($stooges, 'age');
// => [
//     "40" => ['name' => 'moe',   'age' => 40],
//     "50" => ['name' => 'larry', 'age' => 50],
//     "60" => ['name' => 'curly', 'age' => 60]
// ]
?>

Table of contents » Collection Functions

groupBy


Description: Splits a collection into sets, grouped by the result of running each value through iterator. If iterator is a string instead of a function, groups by the property named by iterator on each of the values.

Parameters
  • list: traversable, the list of items to group
  • iterator: callable,scalar, the function to generate the key or a property name
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::groupBy(list,iterator,context)
Examples
<?php
_::groupBy([1.3, 2.1, 2.4], function($num) { return floor($num); });
// => [1 => [1.3], 2 => [2.1, 2.4]]

$values = [
    ['val' => 'one',   'length' => 3],
    ['val' => 'two',   'length' => 3],
    ['val' => 'three', 'length' => 5]
];
_::groupBy($values, 'length');
// => [3 => [['val' => 'one', 'lenght' => 3], ['val' => 'two', 'length' => 3], 5 => [['val' => 'three', 'length' => 5]]]
?>

Table of contents » Collection Functions

countBy


Description: Sorts a list into groups and returns a count for the number of objects in each group. Similar to groupBy, but instead of returning a list of values, returns a count for the number of values in that group.

Parameters
  • list: traversable, the list of items to group and count
  • iterator: callable,scalar, the function to generate the key or a property name
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::countBy(list,iterator,context)
Examples
<?php
_::countBY([1, 2, 3, 4, 5], function($num) {
    return $num % 2 == 0 ? 'even' : 'odd';
});
// => ['odd' => 3, 'even' => 2]
?>

Table of contents » Collection Functions

shuffle


Description: Returns a shuffled copy of the list.

Parameters
  • list: traversable, the list of items to shuffle
Prototype
_::shuffle(list)
Examples
<?php
_::shuffle([1, 2, 3, 4, 5, 6]);
// => [4, 1, 6, 3, 5, 2]
?>

Table of contents » Collection Functions

sample


Description: Produce a random sample from the list. Pass a number to return n random elements from the list. Otherwise a single random item will be returned.

Parameters
  • list: traversable, the list of items
  • n: int, optional, the number of items to pick
Prototype
_::sample(list,n)
Examples
<?php
_::sample([1, 2, 3, 4, 5, 6]);
// => 4

_::sample([1, 2, 3, 4, 5, 6], 3);
// => [1, 6, 2]
?>

Table of contents » Collection Functions

toArray


Description: Creates a real Array from the list (anything that can be iterated over). This method will also accept scalars such as string, number and even null and will cast them into arrays, for instance Underscore::toArray(null) is [] altough Underscore::toArray('a') is ['a'].

Parameters
  • list: traversable, the list of items
Prototype
_::toArray(list)
Examples
<?php
$object = new stdClass;
$object->one   = 1;
$object->two   = 2;
$object->three = 3;
_::toArray($object);
// => ['one' => 1, 'two' => 2, 'three' => 3]

_::toArray(null);
// => []

_::toArray("hello");
// => ["hello"]
?>

Table of contents » Collection Functions

size


Description: Return the number of values in the list. This method will also accept scalars such as string, number and even null or resources but will return 1 in that case.

Parameters
  • list: traversable, the list of items
Prototype
_::size(list)
Examples
<?php
$object = new stdClass;
$object->one   = 1;
$object->two   = 2;
$object->three = 3;
_::size($object);
// => 3
?>

Table of contents » Collection Functions

Uncategorized

partition


Description: Split a collection into two arrays: one whose elements all satisfy the given predicate, and one whose elements all do not satisfy the predicate.

Parameters
  • list: traversable, the list of items
  • iterator: callable, the predicate
  • context: object, optional, if provided will become the context of $iterator
Prototype
_::partition(list,iterator,context)
Examples
<?php
_::partition([0, 1, 2, 3, 4, 5], function($num) { return $num % 2 != 0; });
// => [[1, 3, 5], [0, 2, 4]]
?>

Table of contents » Uncategorized

now


Description: Returns an integer timestamp for the current time.

Parameters
Prototype
_::now()

Table of contents » Uncategorized

Array Functions

first


Alias: head, take

Description: Returns the first element of an array. Passing n will return the first n elements of the array. Passing guard will force the returned value to be an array.

Parameters
  • array: traversable, the list of items
  • n: int, optional, the number of items to pick
  • guard: bool, optional, true to always return an array
Prototype
_::first(array,n,guard)

Table of contents » Array Functions

initial


Description: Returns everything but the last entry of the array. Pass n to exclude the last n elements from the result. Passing guard will force the returned value to be an array.

Parameters
  • array: traversable, the list of items
  • n: int, optional, the number of items to exclude
  • guard: bool, optional, true to always return an array
Prototype
_::initial(array,n,guard)

Table of contents » Array Functions

last


Description: Returns the last element of an array. Passing n will return the last n elements of the array. Passing guard will force the returned value to be an array.

Parameters
  • array: traversabel, the list of items
  • n: int, optional, the number of items to pick
  • guard: bool, optional, true to always return an array
Prototype
_::last(array,n,guard)

Table of contents » Array Functions

rest


Alias: tail, drop

Description: Returns the rest of the elements in an array. Pass an index to return the values of the array from that index onward. Passing guard will force the returned value to be an array.

Parameters
  • array: traversable, the list of items
  • index: int, optional, the index from which the items are picked
  • guard: bool, optional, true to always return an array
Prototype
_::rest(array,index,guard)

Table of contents » Array Functions

compact


Description: Returns a copy of the array with all falsy values removed. In PHP, false, null, 0, "", array() and "0" are all falsy.

Parameters
  • array: traversable, the list of items
Prototype
_::compact(array)

Table of contents » Array Functions

flatten


Description: Flattens a nested array (the nesting can be to any depth). If you pass shallow, the array will only be flattened a single level.

Parameters
  • array: traversable, the list of items
  • shallow: bool, optional, if true will only flatten on single level
Prototype
_::flatten(array,shallow)

Table of contents » Array Functions

without


Description: Returns a copy of the array with all instances of the values removed.

Parameters