PHPackages                             ascetik/objectstorage - 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. ascetik/objectstorage

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

ascetik/objectstorage
=====================

Self-made SplObjectStorage extension

v0.3.0(2y ago)012MITPHP

Since Dec 6Pushed 2y ago1 watchersCompare

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

READMEChangelogDependencies (2)Versions (5)Used By (0)

objectstorage
=============

[](#objectstorage)

Self-made SplObjectStorage extension

The purpose of this package is to use a **SplObjectStorage** in an easier and faster way. The native implementation of this class leads to some complications to access to its content.

I tried to use the php DS package but came back to the enhancement of this present tool.

Release notes
-------------

[](#release-notes)

> version 0.3.0

- Offset read/write access

Implementations
---------------

[](#implementations)

### Box

[](#box)

A **Box** uses a **SplObjectStorage** to store objects. It provides easy ways to add content at the top or the bottom of the container, retrieve or remove some content.

Methods available :

- **Box**::associate(*object*, *mixed*, *?int*): *void* - add or replace the offset of given object
- **Box**::clear(): *void* - remove all content
- **Box**::contains(*object*): *bool* - Check the existence of an instance (strict comparison)
- **Box**::count(): *int* - return the number of items
- **Box**::each(*Closure*): *void* - call given closure for avery items
- **Box**::filter(*Closure*): *self* - return a new Box with elements filtered by Closure
- **Box**::find(*Closure*): *?object* - find an element matching closure result
- **Box**::first(): *?object* - Return the first stored element
- **Box**::getIterator(): SplObjectStorage - Return Box iterator
- **Box**::hasAny(*object*): *bool* - Check the existence of an instance (value comparison)
- **Box**::isEmpty(): *bool* - check if Box is empty
- **Box**::last(): *?object* - Return the last stored element
- **Box**::map(*Closure*): *self* - return a new Box containing instances returned by Closure
- **Box**::pop(): *?object* - Remove and return the last element
- **Box**::push(*object*, *mixed*): *void* - add content at the top of the storage
- **Box**::readonly(): *ReadonlyBox* - return a readonly Box
- **Box**::remove(*Closure*): *bool* - Remove filtered element if any and return true on success, false otherwise
- **Box**::sort(*callable*, *?BoxSortOrder*): *void* - sort the box using given algorithm, ASC default order
- **Box**::sortReverse(*callable*): *void* - sort the box using given algorithm, DESC order
- **Box**::shift(): *?object* - Remove and return the first element
- **Box**::unshift(*object*, *mixed*): *void* - add content at the tail of the storage
- **Box**::valueOf(*object*): *mixed* - get the offset associated to the given object if present, null otherwise

### ReadonlyBox

[](#readonlybox)

A **ReadonlyBox** is, as the name suggests, a **Box** in readonly mode. It just provides read methods.

Methods available :

- **Box**::contains(*object*): *bool* - Check the existence of an instance (strict comparison)
- **Box**::count(): *int* - return the number of items
- **Box**::find(*Closure*): *?object* - find an element matching closure result
- **Box**::each(*Closure*): *void* - call given closure for avery items
- **Box**::first(): *?object* - Return the first stored element
- **Box**::getIterator(): SplObjectStorage - Return Box iterator
- **Box**::hasAny(*object*): *bool* - Check the existence of an instance (value comparison)
- **Box**::isEmpty(): *bool* - check if Box is empty
- **Box**::last(): *?object* - Return the last stored element
- **Box**::map(*Closure*): *self* - return a new Box containing instances returned by Closure
- **Box**::valueOf(*object*): *mixed* - get the offset associated to the given object if present, null otherwise

Sorting
-------

[](#sorting)

A **Box** is sortable but needs an algorithm to work with the instances registered by the Box.

This algorithm takes 2 arguments : The current Box value and the next one. It returns an integer as the result of the comparison between those values, just like *usort()* with instances.

Offset access
-------------

[](#offset-access)

The box instance provides methods to access the offset of all its content.

Methods *push* and *unshift* accept a first parameter that is the object to store, and a second nullable parameter for the offset. However, it is still possible to add or change the offset of a value during runtime by using the *associate* method.

It accepts 3 parameters :

- the object that MAY be registered by the Box
- the value to add/modify/remove as offset
- an optionnal boolean value, default set to false, to force pushing given object and associated offset in the Box :

```
$box = new Box();
$class1 = new MyClass(1);
$class2 = new MyClass(2);
$class3 = new MyClass(3);
$box->push($class2, 'offset2'); // registering class2 with an offset as Box head
$box->unshift($class1, 'offset1'); // registering class2 with an offset as Box tail

$box->associate($class1, 'new offset'); // changing class1 offset

$box->associate($class2, null); // removing class2 offset

$box->associate($class3, 'offset3', $box::IGNORE_ON_MISSING); // $class3 not registered, no action (default behavior)

$box->associate($class3, 'offset3', $box::APPEND_ON_MISSING); // $class3 pushed in Box with its offset

$box->associate($class4, 'offset4', $box::PREPEND_ON_MISSING); // $class4 added as Box tail with its offset
```

> The *associate* method is not available with **ReadonlyBox**.

To retrieve the offset of a registered object :

```
// from last example
$offset1 = $box->valueOf($class1); // 'new offset'

$offset2 = $box->valueOf($class2); // null

$offset3 = $box->valueOf(new MyClass(4)); // null, unregistered object
```

###  Health Score

18

—

LowBetter than 8% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity5

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity35

Early-stage or recently created project

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

Total

4

Last Release

886d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/4a4d8042606038f6fe934a289278b31406405b77801d3e77142b29341a2614d6?d=identicon)[ascetik](/maintainers/ascetik)

---

Top Contributors

[![ascetik](https://avatars.githubusercontent.com/u/92370226?v=4)](https://github.com/ascetik "ascetik (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/ascetik-objectstorage/health.svg)

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

###  Alternatives

[politriukas/avataaars

PHP SVG avatar generator based on https://github.com/fangpenlin/avataaars-generator

112.0k](/packages/politriukas-avataaars)

PHPackages © 2026

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