PHPackages                             smoren/containers - 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. smoren/containers

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

smoren/containers
=================

Abstract data containers and structures for PHP

v0.2.8(3y ago)511411MITPHPPHP &gt;=7.4

Since Dec 23Pushed 3y ago4 watchersCompare

[ Source](https://github.com/Smoren/containers-php)[ Packagist](https://packagist.org/packages/smoren/containers)[ RSS](/packages/smoren-containers/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (8)Dependencies (7)Versions (11)Used By (1)

Data containers
===============

[](#data-containers)

[![Packagist PHP Version Support](https://camo.githubusercontent.com/28d53ac64e9d33260d173a21599bed503cebda05c9d27098f5afb30c513b9a38/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f736d6f72656e2f636f6e7461696e657273)](https://camo.githubusercontent.com/28d53ac64e9d33260d173a21599bed503cebda05c9d27098f5afb30c513b9a38/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f736d6f72656e2f636f6e7461696e657273)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/0b29f3208b73a038a17e264c8b89364f393df41deac5488c5ccd0a8b964655d3/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f536d6f72656e2f636f6e7461696e6572732d7068702f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/Smoren/containers-php/?branch=master)[![Coverage Status](https://camo.githubusercontent.com/8c8014bbc44fc8042762df3fd90ee98ab396e9d97f9562a414816c34fed4bfb7/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f536d6f72656e2f636f6e7461696e6572732d7068702f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/Smoren/containers-php?branch=master)[![Build and test](https://github.com/Smoren/containers-php/actions/workflows/test_master.yml/badge.svg)](https://github.com/Smoren/containers-php/actions/workflows/test_master.yml/badge.svg)[![License: MIT](https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667)](https://opensource.org/licenses/MIT)

Abstract data containers and structures for PHP

### How to install as dependency to your project

[](#how-to-install-as-dependency-to-your-project)

```
composer require smoren/containers

```

### Unit testing

[](#unit-testing)

```
composer install
./vendor/bin/codecept build
./vendor/bin/codecept run unit tests/unit

```

### LinkedList

[](#linkedlist)

Classic implementation of linked list structure. Also can be used as stack and queue.

```
use Smoren\Containers\Structs\LinkedList;
use Smoren\Containers\Structs\LinkedListItem;

$ll = new LinkedList([6, 4, 2]);
var_dump($ll->count()); // output: 3

$ll->pushBack(1);
$ll->pushFront(7);
var_dump($ll->count()); // output: 5
print_r($ll->toArray()); // output: [7, 6, 4, 2, 1]

$ll->sort(function($lhs, $rhs) {
    return $lhs > $rhs;
});

print_r($ll->toArray()); // output: [1, 2, 4, 6, 7]

$ll->swap($ll->getFirst(), $ll->getLast());
print_r($ll->toArray()); // output: [7, 2, 4, 6, 1]

$ll->swap($ll->getFirst()->getNext(), $ll->getLast()->getPrev());
print_r($ll->toArray()); // output: [7, 6, 4, 2, 1]

var_dump($ll->popFront()); // output: 7
var_dump($ll->popBack()); // output: 1
print_r($ll->toArray()); // output: [6, 4, 2]

$ll->delete($ll->getFirst()->getNext());
print_r($ll->toArray()); // output: [6, 2]

$llNew = LinkedList::merge(new LinkedList([-2, -1]), $ll, new LinkedList([1, 2]));
var_dump($llNew->count()); // output: 6
print_r($llNew->toArray()); // output: [-2, -1, 6, 2, 1, 2]

$ll->pushBefore($ll->getFirst(), -3);
$ll->pushAfter($ll->getLast(), 3);
print_r($llNew->toArray()); // output: [-3, -2, -1, 6, 2, 1, 2, 3]

/**
 * @var LinkedListItem $id
 * @var mixed $item
 */
foreach($ll as $id => $item) {
    // you can iterate collection
}

$ll->clear();
print_r($ll->toArray()); // output: []
```

### MappedCollection

[](#mappedcollection)

Map-like data structure.

```
use Smoren\Containers\Exceptions\MappedCollectionException;
use Smoren\Containers\Structs\MappedCollection;

$coll = new MappedCollection(['1' => ['id' => 1]]);
var_dump($coll->count()); // output: 1
print_r($coll->toArray()); // output: ['1' => ['id' => 1]]

$coll->add('2', ['id' => 2]);
var_dump($coll->count()); // output: 1
print_r($coll->toArray()); // output: ['1' => ['id' => 1], '2' => ['id' => 2]]

var_dump($coll->exist(1)); // output: true
var_dump($coll->exist(2)); // output: true
var_dump($coll->exist(3)); // output: false

try {
    $coll->add('1', ['id' => 1, 'extra' => 'test']);
} catch(MappedCollectionException $e) {
    // cannot silently replace existing value
}

print_r($coll->get(1)); // output: ['id' => 1]

$coll->replace('1', ['id' => 1, 'extra' => 'test']);
print_r($coll->get(1)); // output: ['id' => 1, 'extra' => 'test']

try {
    $coll->get('3');
} catch(MappedCollectionException $e) {
    // element with id = 3 does not exist so you cannot get it
}

/**
 * @var string $id
 * @var mixed $item
 */
foreach($coll as $id => $item) {
    // you can iterate collection
}

$coll->clear();
print_r($coll->toArray()); // output: []
```

### MappedLinkedList

[](#mappedlinkedlist)

LinkedList with mapping by id.

```
use Smoren\Containers\Structs\MappedLinkedList;

$mll = new MappedLinkedList([]);
var_dump($mll->count()); // output: 0

$mll->pushBack(102, 2);
$mll->pushFront(101, 1);
$mll->pushBack(100, 0);
var_dump($mll->count()); // output: 4
print_r($mll->toArray()); // output: [101 => 1, 102 => 2, 100 => 0]]

$mll->sort(function($lhs, $rhs) {
    return $lhs > $rhs;
});
print_r($mll->toArray()); // output: [100 => 0, 101 => 1, 102 => 2]]

$mll->swap(100, 101);
print_r($mll->toArray()); // output: [101 => 1, 100 => 0, 102 => 2]]

var_dump($mll->popFront()); // output: [101, 1]
var_dump($mll->popBack()); // output: [102, 2]
print_r($mll->toArray()); // output: [100 => 0]

$mllNew = MappedLinkedList::merge(
    new MappedLinkedList([-999 => -99]),
    $mll,
    new MappedLinkedList([999 => 99])
);
var_dump($mllNew->count()); // output: 5
print_r($mllNew->toArray()); // output: [-999 => 99, 100 => 0, 999 => 9]

$mllNew->pushBefore(100, -101, -1);
$mllNew->pushAfter(100, 101, 1);
print_r($mllNew->toArray()); // output: [-999 => 99, -101 => -1, 100 => 0, 101 => 1, 999 => 9]

/**
 * @var string $id
 * @var mixed $value
 */
foreach($mllNew as $id => $value) {
    // you can iterate collection
}

$mllNew->clear();
print_r($mllNew->toArray()); // output: []
```

### SortedLinkedList

[](#sortedlinkedlist)

```
use Smoren\Containers\Structs\SortedLinkedList;
use Smoren\Containers\Exceptions\LinkedListException;

/**
 * Class IntegerSortedLinkedList
 */
class IntegerSortedLinkedList extends SortedLinkedList
{
    /**
     * @inheritDoc
     */
    protected function getComparator(): callable
    {
        return function(int $lhs, int $rhs) {
            return $lhs > $rhs;
        };
    }
}

$sll = new IntegerSortedLinkedList([2, 5, 1]);
var_dump($sll->count()); // output: 3
print_r($sll->toArray()); // output: [1, 2, 5]

$sll->insert(2);
$pos = $sll->insert(3);
var_dump($sll->count()); // output: 5
print_r($sll->toArray()); // output: [1, 2, 2, 3, 5]

var_dump($sll->delete($pos)); // output: 3
var_dump($sll->count()); // output: 4
print_r($sll->toArray()); // output: [1, 2, 2, 5]

var_dump($sll->popBack()); // output: 5
var_dump($sll->popFront()); // output: 1
var_dump($sll->count()); // output: 2
print_r($sll->toArray()); // output: [2, 2]

/**
 * @var string $id
 * @var mixed $value
 */
foreach($sll as $id => $value) {
    // you can iterate collection
}

$sll->clear();
var_dump($sll->count()); // output: 0
print_r($sll->toArray()); // output: []

try {
    $sll->popBack();
} catch(LinkedListException $e) {
    // cannot pop when collection is empty
}

try {
    $sll->popFront();
} catch(LinkedListException $e) {
    // cannot pop when collection is empty
}
```

### SortedMappedLinkedList

[](#sortedmappedlinkedlist)

LinkedList with presort and mapping.

```
use Smoren\Containers\Exceptions\MappedLinkedListException;
use Smoren\Containers\Structs\LinkedListItem;
use Smoren\Containers\Structs\SortedMappedLinkedList;

$smll = new SortedMappedLinkedList([1 => -1, 10 => -10, 5 => -5]);
var_dump($smll->count()); // output: 3
print_r($smll->toArray()); // output: [1 => -1, 5 => -5, 10 => -10]

$smll->insert(3, -3);
var_dump($smll->count()); // output: 4
print_r($smll->toArray()); // output: [1 => -1, 3 => -3, 5 => -5, 10 => -10]

$smll->popBack();
$smll->popFront();
var_dump($smll->count()); // output: 2
print_r($smll->toArray()); // output: [3 => -3, 5 => -5]

/**
 * Class ArrayMappedSortedLinkedList
 */
class ArraySortedMappedLinkedList extends SortedMappedLinkedList
{
    /**
     * @inheritDoc
     */
    protected function getComparator(): callable
    {
        return function(array $lhs, array $rhs) {
            return $lhs['a'] > $rhs['a'];
        };
    }
}

$ll = new ArraySortedMappedLinkedList([
    -5 => ['a' => 5],
    -1 => ['a' => 1],
    -2 => ['a' => 2],
]);
var_dump($smll->count()); // output: 3
print_r($smll->toArray()); // output: [-1 => ['a' => 1], -2 => ['a' => 2], -5 => ['a' => 5]]

/**
 * @var string $id
 * @var mixed $value
 */
foreach($smll as $id => $value) {
    // you can iterate collection
}

try {
    $smll->insert(-2, ['a' => 2, 'extra' => 'test']);
} catch(MappedLinkedListException $e) {
    // cannot simply replace existing element
}

/** @var LinkedListItem $pos */
$pos = $ll->delete(-1);
print_r($pos->getData()); // output: ['a' => 1]
var_dump($smll->count()); // output: 2
print_r($smll->toArray()); // output: [-2 => ['a' => 2], -5 => ['a' => 5]]

print_r($ll->popBack()); // output: [-5, ['a' => 5]]
print_r($ll->popFront()); // output: [-2, ['a' => 2]]
var_dump($smll->count()); // output: 0
print_r($smll->toArray()); // output: []
```

### Graph

[](#graph)

Graph data structure with tools for traversing.

```
use Smoren\Containers\Structs\Graph;

$graph = new Graph(
    [1 => 11, 2 => 22, 3 => 33, 4 => 44, 5 => 55, 6 => 66],
    [[1, 2, 'a'], [2, 3, 'a'], [3, 4, 'a'], [2, 5, 'b'], [5, 3, 'b'], [5, 6, 'c'], [6, 4, 'c']]
);

$paths = $graph->traverseBackward(4);
var_dump($paths); // output: 3
var_dump($paths[0]->toArray(true)); // output: [4, 3, 2, 1]
var_dump($paths[1]->toArray(true)); // output: [4, 3, 5, 2, 1]
var_dump($paths[2]->toArray(true)); // output: [4, 6, 5, 2, 1]

$paths = $graph->traverseForward(1);
var_dump(3, $paths); // output: 3
var_dump($paths[0]->toArray(true)); // output: [1, 2, 3, 4]
var_dump($paths[1]->toArray(true)); // output: [1, 2, 5, 3, 4]
var_dump($paths[2]->toArray(true)); // output: [1, 2, 5, 6, 4]

$paths = $graph->traverseForward(1, ['a', 'b']);
var_dump(2, $paths); // output:
var_dump($paths[0]->toArray(true)); // output: [1, 2, 3, 4]
var_dump($paths[1]->toArray(true)); // output: [1, 2, 5, 3, 4]

$graph->insert(7, 77);
$graph->link(7, 1, 'a');

$paths = $graph->traverseBackward(7);
var_dump($paths); // output: 3
var_dump($paths[0]->toArray(true)); // output: [4, 3, 2, 1, 7]
var_dump($paths[1]->toArray(true)); // output: [4, 3, 5, 2, 1, 7]
var_dump($paths[2]->toArray(true)); // output: [4, 6, 5, 2, 1, 7]
var_dump($paths[2]->reverse()->toArray(true)); // output: [1, 2, 5, 6, 4, 7]
```

###  Health Score

25

—

LowBetter than 37% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity15

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 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 ~29 days

Recently: every ~59 days

Total

9

Last Release

1369d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/fdc9e8df44cbbc0fc88885a4f1daa2cad755266e73eb0bac15efaf0d47ecbae2?d=identicon)[smoren](/maintainers/smoren)

---

Top Contributors

[![Smoren](https://avatars.githubusercontent.com/u/7403235?v=4)](https://github.com/Smoren "Smoren (37 commits)")

---

Tags

data-containersgraphgraph-algorithmslinked-listmapphp-librarycontainermapcollectionlistabstractlinked listStructures

###  Code Quality

TestsCodeception

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/smoren-containers/health.svg)

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

###  Alternatives

[phpcollection/phpcollection

General-Purpose Collection Library for PHP

1.0k64.0M34](/packages/phpcollection-phpcollection)[aimeos/map

Easy and elegant handling of PHP arrays as array-like collection objects similar to jQuery and Laravel Collections

4.2k412.9k11](/packages/aimeos-map)[graze/data-structure

Data collections and containers

12287.4k8](/packages/graze-data-structure)[chdemko/sorted-collections

Sorted Collections for PHP &gt;= 8.2

222.5M3](/packages/chdemko-sorted-collections)[graze/sort

A collection of array sorting transforms and functions

12289.6k2](/packages/graze-sort)[bnomei/kirby3-recently-modified

Kirby Section to display recently modified content pages

309.3k](/packages/bnomei-kirby3-recently-modified)

PHPackages © 2026

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