PHPackages                             belt/underscore - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. belt/underscore

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

belt/underscore
===============

Pushing square things down round holes

v1.1(11y ago)220.4k↓50%1BSD-2-ClausePHPPHP &gt;=5.4.0

Since Oct 24Pushed 11y ago1 watchersCompare

[ Source](https://github.com/beltphp/underscore)[ Packagist](https://packagist.org/packages/belt/underscore)[ Docs](https://github.com/beltphp/underscore)[ RSS](/packages/belt-underscore/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (3)Dependencies (2)Versions (4)Used By (0)

Belt.`Underscore`
=================

[](#beltunderscore)

[![Latest Version](https://camo.githubusercontent.com/67253840dca226901eaa4e8de97c5a7975cb09e0781d9ad08e0bd92b163ecfae/687474703a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f62656c742f756e64657273636f72652e7376673f7374796c653d666c61742d737175617265)](https://github.com/beltphp/underscore/releases)[![Software License](https://camo.githubusercontent.com/d1e56ba6bff874ba0866962af6324190e62fc789a46ed4e026dcbbb36f18fc5d/687474703a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f62656c742f756e64657273636f72652e7376673f7374796c653d666c61742d737175617265)](LICENSE)[![Build Status](https://camo.githubusercontent.com/a86af19a98cbbe5b2235060e11b6b7f9435b3bd5aaad4e0e981dc7367ea41eb2/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f62656c747068702f756e64657273636f72652f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://travis-ci.org/beltphp/releases)[![Coverage Status](https://camo.githubusercontent.com/12cb6216968af9df352d4a11d6286ec5cc5e28e3eb6ac82ef96153a7118ae11b/687474703a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f636f7665726167652f672f62656c747068702f756e64657273636f72652e7376673f7374796c653d666c61742d737175617265)](https://scrutinizer-ci.com/g/beltphp/underscore/code-structure)[![Quality Score](https://camo.githubusercontent.com/49a9ccb718a8a59722a2b398a768232731f68f180ad0b7994b1c34a04cdc122b/687474703a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f672f62656c747068702f756e64657273636f72652e7376673f7374796c653d666c61742d737175617265)](https://scrutinizer-ci.com/g/beltphp/underscore/)

> Pushing round things down square holes.

Belt`.Underscore` is an utility library that makes working with arrays in PHP a little bit more pleasant.

Installation
------------

[](#installation)

Via Composer

```
$ composer require belt/underscore
```

Usage
-----

[](#usage)

The following examples assume that you have included the Underscore utility:

```
use Belt\_;
```

Some of the examples might seem a bit contrived, but they're actually really handy. For example, let's say that we have a fictional social network and (for some reason) we want to get the names of all the authenticated user's 2nd degree friends (friends-of-friends) that are over the age of 18. Suddenly, that becomes real easy!

```
_::create($user->getFriends())->map(function ($f) {
    return $f->getFriends();
})->select(function ($f) {
    return $f->getAge() > 18;
})->pluck('username');
```

And now (for some even stranger reason) we want to know the total number of *third* degree friends (friends-of-friends-of-friends) of the 2nd degree friends that are over the age of 18.

```
_::create($user->getFriends())->map(function ($f) {
    return $f->getFriends();
})->select(function ($f) {
    return $f->getAge() > 18;
})->reduce(function ($s, $f) {
    return $s + count($f->getFriends());
});
```

That's it!

> **Note**: When, in the examples, the return value comment indicates an array the actual return value is a new `_` instance! You can get the actual PHP array value by calling the `toArray` method.

The `_` class implements `ArrayAccess` too, so you can access it like an usual array:

```
$groups = _::create($user->getFriends())->groupBy(function ($friend) {
    $name = $friend->getName();

    return $name[0];
});

$groups['A'] = ...; // All friends with the letter 'A' as the first letter in their name
```

Additionally, you can traverse the container in a `foreach` loop as well:

```
$users = _::create(['alice', 1337, 'bob', 42])->chunk(2);

foreach ($users as $name => $karma) {
    // ...
}
```

#### `all`

[](#all)

Call the given `callback` for each element in the container. Should the callback return `false`, the method immediately returns `false` and ceases enumeration. If all invocations of the callback return `true`, `all` returns `true`.

```
_::create([1, 2, 3])->all(function ($n) {
    return $n > 0;
}); // true
```

#### `any`

[](#any)

Call the given `callback` for each element in the container. Should the callback return `true`, the method immediately returns `true` and enumeration is ceased. If all invocations of the callback return `false`, `any` returns `false`.

```
_::create([1, 2, 3])->any(function ($n) {
    return $n > 2;
}); // true
```

#### `chunk`

[](#chunk)

Chunks the container into a new array of `n`-sized chunks.

```
_::create([1, 2, 3, 4])->chunk(2); // [[1, 2], [3, 4]]
```

#### `combine`

[](#combine)

Combine the container with another array into key/value pairs.

```
_::create([1, 2, 3])->combine(['foo', 'bar', 'baz']); // [1 => 'foo', 2 => 'bar', 3 => 'baz']
```

#### `concat`

[](#concat)

Returns a new array that is the container with the given `array` concatenated to the end.

```
_::create([1, 2])->concat([3, 4]); // [1, 2, 3, 4]
```

#### `dict`

[](#dict)

Convert an array of key/value pairs into the logical dictionary.

```
_::create([[1, 2], [3, 4]])->dict(); // [1 => 2, 3 => 4]
```

If you have a flat array you can call `chunk(2)` before `dict`.

```
_::create([1, 2, 3, 4])->chunk(2)->dict(); // [1 => 2, 3 => 4]
```

#### `each`

[](#each)

Calls the given callback once for each element in the container, passing that element as the argument.

```
_::create([1, 2, 3, 4])->each(function ($n) {
    printf("%d\n", $n);
}); // outputs: 1\n2\n3\n4\n
```

`each` also supports two and three parameter versions:

```
_::create([1, 2, 3, 4])->each(function ($n, $i) {
    printf("%d: %d\n", $i, $n);
}); //outputs: 0: 1\n1: 2\n2: 3\n3: 4\n

_::create([1, 2, 3, 4]->each(function ($n, $i, $array) {
    // ...
}));
```

#### `find`

[](#find)

Passes each entry in the container to the given callback, returning the first element for which callback is not `false`. If no entry matches, returns `null`.

```
_::create([1, 2, 3, 4])->find(function ($n) {
    return $n > 2;
}); // 3
```

#### `first`

[](#first)

Returns the first `n` elements in the container.

```
_::create([1, 2, 3, 4])->first(2); // [1, 2]
```

#### `flatten`

[](#flatten)

Returns a new, one-dimensional array that is a recursive flattening of the container.

```
_::create([1, [2], [3, [4]]])->flatten(); [1, 2, 3, 4]
```

> **Tip:** If you only want to flatten one level of an array, `flatMap` might be useful for you!

#### `flatMap`

[](#flatmap)

Returns a new array with the concatenated results of invoking the callback once for every element in the container.

```
_::create([1, 2, 3, 4])->flatMap(function ($n) {
    return [$n, $n];
}); // [1, 1, 2, 2, 3, 3, 4, 4]

_::create([1, 2, 3, 4])->flatMap(function ($n) {
    return [$n, [$n]];
}); // [1, [1], 2, [2], 3, [3], 4, [4]]
```

It might look a bit silly, but this is actually a really useful function when you combine it with other functions! For example, you can create a dictionary for (fictional) users.

```
_::create([new User('bob', 32), new User('alice', 35)])->flatMap(function ($u) {
    return [$n->getName(), $n->getAge()];
})->chunk(2)->dict(); // ['bob' => 32, 'alice' => 35]
```

Which finally allows us, as developers, to create key/value pairs when mapping arrays! Hoorah!

#### `groupBy`

[](#groupby)

Groups the container by result of the given callback.

```
_::create([1, 2, 3, 4])->groupBy(function ($n) {
    return $n % 2;
}); // [0 => [2, 4], 1 => [1, 3]]

_::create(['foo', 'bar', 'baz'])->groupBy(function ($s) {
    return $s[0];
}); // ['f' => ['foo'], 'b' => ['bar', 'baz']]
```

#### `has`

[](#has)

```
_::create([1, 2, 3, 4])->has(2); // true
_::create([1, 2, 3, 4])->has(0); // false
```

#### `indexOf`

[](#indexof)

Returns the index of the given object in the container or `null` if the element was not found.

```
_::create([1, 2, 3, 4])->indexOf(2); // 1
_::create([1, 2, 3, 4])->indexOf(0); // null
```

#### `inject`

[](#inject)

Combines all elements of the container by applying a binary operation.

```
_::create([1, 2, 3])->inject([], function ($m, $n) {
    $m[$n] = $n * $n;

    return $m;
}); // [1 => 1, 2 => 4, 3 => 9]

_::create(['foo', 'bar', 'baz'])->inject('', function ($m, $s) {
    $m .= $s;
}); // foobarbaz
```

> **Note**: This is the only exception to the note earlier. The return value here is the return value of the *last* itertation.

#### `join`

[](#join)

Returns a string of all the container's elements joined with the provided separator string.

```
_::create([1, 2, 3, 4])->join('');  // 1234
_::create([1, 2, 3, 4])->join(','); // 1,2,3,4
```

#### `last`

[](#last)

Returns the last `n` elements from the container.

```
_::create([1, 2, 3, 4, 5, 6])->last(2); // [5, 6]
```

#### `map`

[](#map)

Invokes the given callback for each element in the container. Creates a new array containing the values returned by the block.

If the given callback returns `null`, that element is skipped in the returned array.

```
_::create([1, 2, 3, 4])->map(function ($n) {
    return $n * $n;
}); // [1, 4, 9, 16]

_::create([1, 2, 3, 4])->map(function ($n) {
    return $n % 2 ? $n * $n : null;
}); // [1, 9]
```

#### `max`

[](#max)

Returns the element for which the given callback returns the largest integer.

```
_::create('1', 'two', 'three')->max(function ($s) {
    return strlen($s);
}); // 'three'
```

#### `min`

[](#min)

Returns the element for which the given callback returns the smallest integer.

```
_::create('1', 'two', 'three')->min(function ($s) {
    return strlen($s);
}); // '1'
```

#### `none`

[](#none)

Test if the given callback returns `false` for each element in the container.

```
_::create([1, 2, 3, 4])->none(function ($n) {
    return $n < 0;
}); // true

_::create([1, 2, 3, 4])->none(function ($n) {
    return $n > 0;
}); // false
```

#### `partition`

[](#partition)

Partitions the container into two arrays based on the boolean return value of the given block.

```
_::create(['A', 'B', 'C', 'AA'])->partition(function ($s) {
    return $s[0] == 'A';
}); // [['A', 'AA'], ['B', 'C']]
```

#### `pluck`

[](#pluck)

Returns a new array that is the result of retrieving the given property path on each element in the container.

```
_::create([new User('bob'), new User('alice')])->pluck('username'); // ['bob', 'alice']
```

#### `product`

[](#product)

Calculate the product of the container by assuming that all values can be casted to a double value.

```
_::create([1, 2, 3])->product(); // 6
```

#### `reduce`

[](#reduce)

Reduces the container to a single value.

The usual example of reduce is to sum all values in an array.

```
_::create([1, 2, 3, 4])->reduce(function ($memo, $n) {
    return $memo + $n;
}); // 10
```

Reduce also allows you to set an initial value before reducing the array.

```
_::create([1, 2, 3, 4])->reduce(function ($s, $n) {
    return $s + $n;
}, 10); // 20
```

#### `reject`

[](#reject)

Returns a new array containing all elements for which the given callback returns `false`.

```
_::create([1, 2, 3, 4])->reject(function ($n) {
    return ($n % 2) == 0;
}); // [1, 3]
```

#### `reverse`

[](#reverse)

Returns a new array that is the container, reversed.

```
_::create([1, 2, 3, 4])->reverse(); // [4, 3, 2, 1]
```

#### `rotate`

[](#rotate)

Returns a new array rotated about the provided index.

```
_::create([1, 2, 3, 4, 5, 6])->rotate(2); // [3, 4, 5, 6, 1, 2]
_::create([1, 2, 3, 4, 5, 6])->rotate(-2); // [5, 6, 1, 2, 3, 4]
```

#### `sample`

[](#sample)

Returns a random element from the container.

```
_::create([1, 2, 3, 4, 5, 6])->sample(); // Basically a dice roll...
```

#### `select`

[](#select)

Returns a new array containing all elements for which the given block returns `true`.

```
_::create([1, 2, 3, 4])->select(function ($n) {
    return ($n % 2) == 0;
}); // [2, 4]
```

#### `shuffle`

[](#shuffle)

Returns a new array that is shuffled.

```
_::create([1, 2])->shuffle(); // Either [1, 2] or [2, 1]
```

#### `skip`

[](#skip)

Skips the first `n` elements and returns the rest of the array.

```
_::create([1, 2, 3, 4, 5, 6])->skip(2); // [3, 4, 5, 6]
```

#### `slice`

[](#slice)

Returns a subarray consisting of the given number of elements from the given starting index.

```
_::create([1, 2, 3, 4])->slice(1, 2); // [2, 3]
```

#### `snip`

[](#snip)

Snips the end off the array. Returns the container *without* the last `n`elements.

```
_::create([1, 2, 3, 4, 5, 6])->snip(2); // [1, 2, 3, 4]
```

#### `sort`

[](#sort)

Returns the container, sorted.

```
_::create([1, 4, 2, 3])->sort(); // [1, 2, 3, 4]
```

#### `sortBy`

[](#sortby)

Sorts all objects using the return value of the given callback as the sorting criteria.

```
$rhombas = new Shape('rhombas');
$ellipse = new Shape('ellipse');
$hexagon = new Shape('hexagon');

_::create([ $rhombas, $ellipse, $hexagon ])->sortBy(function ($s) {
    return $s->getName();
}); // [ $ellipse, $hexagon, $rhombas ]
```

#### `sum`

[](#sum)

Sum all objects by casting the values to a double.

```
_::create([1, 2, 3, 4])->sum(); // 10
```

#### `transpose`

[](#transpose)

Assumes that the container is an array of arrays and transposes the rows and columns.

```
_::create([[1, 2, 3], [4, 5, 6]])->transpose(); // [[1, 4], [2, 5], [3, 6]]
```

#### `uniq`

[](#uniq)

Returns a new array by removing duplicate values in the container.

```
_::create([1, 2, 3, 1, 2, 4, 1, 2, 5])->uniq(); // [3, 4, 5]
```

#### `without`

[](#without)

Returns a new array where objects in the given array are removed from the container.

```
_::create([1, 2, 4, 3])->without([4]); // [1, 2, 3]
_::create([1, 2, 3, 4, 5])->without([4, 5]); // [1, 2, 3]
```

#### `pop`

[](#pop)

Treats container like a stack and removes the last object, returning it.

```
_::create()->push(1)->push(2)->push(3)->pop(); // 3
```

#### `push`

[](#push)

Treats container like a stack and adds the given object to the end of the container.

```
_::create()->push(1)->push(2)->push(3); // [1, 2, 3]
```

#### `shift`

[](#shift)

Removes the container's first object and returns it.

```
_::create([1, 2, 3])->shift(); // 1
```

#### `unshift`

[](#unshift)

Inserts the given object at the front of container, moving all other objects in the container up one index.

```
_::create([2, 3])->unshift(1); // [1, 2, 3]
```

#### `split`

[](#split)

Returns a new array of the strings in the given string that are separated by the given separator.

```
_::split('foo bar baz', ' '); // ['foo', 'bar', 'baz']
```

The second parameter is optional and `null` by default, if you pass `null` or an empty string as seperator, you will get an array of the individual characters in the given string.

```
_::split('1234'); // ['1', '2', '3', '4']
```

We can do some pretty neat stuff with this!

```
_::split('1234')->sum(); // 10
```

#### `first`, `last`, `skip`, `snip` &amp; `slice`

[](#first-last-skip-snip--slice)

These functions are strongly related and useful to remember.

```
_::create([1, 2, 3, 4, 5])->first(2);       // [1, 2]
_::create([1, 2, 3, 4, 5])->last(2);        // [4, 5]
_::create([1, 2, 3, 4, 5])->skip(2);        // [3, 4, 5]
_::create([1, 2, 3, 4, 5])->snip(2);        // [1, 2, 3]
_::create([1, 2, 3, 4, 5])->slice(2, 2);    // [3, 4]
```

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](https://github.com/beltphp/underscore/blob/master/CONTRIBUTING.md).

Credits
-------

[](#credits)

This project is heavily inspired by [YOLOKit](http://mxcl.github.io/YOLOKit/). For all of you who develop in Objective-C, I highly recommend you check it out!

License
-------

[](#license)

Please see [LICENSE](https://github.com/beltphp/underscore/blob/master/LICENSE).

###  Health Score

33

—

LowBetter than 75% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity28

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~33 days

Total

3

Last Release

4158d ago

Major Versions

v0.1 → v1.02014-10-24

PHP version history (2 changes)v0.1PHP &gt;=5.3.0

v1.0PHP &gt;=5.4.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/7c742d9a971e721439dab6897fa61e24052b4433845900a52480f66b90160793?d=identicon)[belt](/maintainers/belt)

---

Top Contributors

[![kleiram](https://avatars.githubusercontent.com/u/323498?v=4)](https://github.com/kleiram "kleiram (57 commits)")

---

Tags

underscoretoolkit

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/belt-underscore/health.svg)

```
[![Health](https://phpackages.com/badges/belt-underscore/health.svg)](https://phpackages.com/packages/belt-underscore)
```

###  Alternatives

[maciejczyzewski/bottomline

A full-on PHP manipulation utility belt that provides support for working with arrays, objects, and iterables; a lodash or underscore equivalent for PHP.

477631.4k10](/packages/maciejczyzewski-bottomline)[codeigniter4/devkit

Development toolkit for CodeIgniter libraries and projects

68187.1k82](/packages/codeigniter4-devkit)[mpetrovich/dash

A functional programming library for PHP. Inspired by Underscore, Lodash, and Ramda.

10428.9k1](/packages/mpetrovich-dash)[bdelespierre/underscore

Underscore.js port in PHP

6943.7k1](/packages/bdelespierre-underscore)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
