/array-with-secondary-keys

Like secondary indexes in databases, but for PHP arrays

Primary LanguagePHPMIT LicenseMIT

Array with Secondary Keys

Build Status (GitHub Actions)

Wraps a PHP array and maintains secondary lookup maps, for fast retrieval of items by nested field values.

This is conceptually similar to how secondary keys in databases work.

Features

Implements ArrayAccess, Iterator and Countable interfaces, so you can use it like you would a standard PHP array:

$a[] = ['foo' => 'bar'];
$value = $a[0];
unset($a[0]);
count($a);
foreach ($a as $key => $value);

Implemented in pure PHP. Secondary indexes are implemented as PHP associative arrays — hash tables with O(1) average lookup time.

Since the secondary index is a hash index, its keys are by design unique. While it is possible to have the same secondary key value in multiple documents in the collection, in such cases the secondary key will get overwritten and will point to the last added/modified document.

API Reference

A "document" is the value associated to a primary key. It can be of any type. If the document is an array, secondary indexes can be specified using the "dot" notation.

All created secondary key indexes are automatically updated when adding/removing/updating values.

Constructor

ArrayWithSecondaryKeys(array $array = [])

Creates a new ArrayWithSecondaryKeys collection, initialized from the given array. If called without arguments, an empty collection is created.

containsPrimaryKey

containsPrimaryKey($key): bool

Checks if the specified primary key is present in the collection.

containsSecondaryKey

containsSecondaryKey($index, $key): bool

Checks if the specified secondary key is present in the specified index.

count

count(): int

Returns the number of documents in the collection.

get

get($key, $default = null): mixed

Retrieves a document by key.

If the key is given in "dot" notation, the corresponding nested part of the document is returned. If the key is not a string that includes a dot, it is treated as a primary key.

has

has($key): bool

Check if an item or items exist in the collection using "dot" notation.

isEmpty

isEmpty(): bool

Returns true if there are no primary keys in the collection, false otherwise.

put

put($key, $document): ArrayWithSecondaryKeys

Adds a new document to the collection under the given key.

If the key is given in "dot" notation, and the top level primary key exists, a nested part is added to the existing document.

If the key is not a string that includes a dot, it is treated as a primary key.

add

add($key, $document): ArrayWithSecondaryKeys

An alias for put.

remove

remove($key): ArrayWithSecondaryKeys

Removes the document associated with the given primary key, or removes a nested part of the document if key is given in "dot" notation.

If the key is given in "dot" notation, the corresponding nested part of the document is removed. If the key is not a string that includes a dot, it is treated as a primary key.

updateSecondaryKey

updateSecondaryKey($index, $existingValue, $newValue)

Finds the document by existing value of secondary key and updates the existing value of secondary key in the document to new value.

Returns the primary key of the updated document, or null if a document with existing value is not found.

append

append($document): ArrayWithSecondaryKeys

Appends a document (using []=).

createIndex

createIndex($index)

Creates a new index and indexes existing documents. Index is given as string in "dot" notation (e.g. state.pid).

getPrimaryKeyByIndex

getPrimaryKeyByIndex($index, $secondaryKey): mixed

Retrieves a primary key by secondary key. Index is given as string in "dot" notation (e.g. state.pid).

Returns null if no document in collection matches the given secondary key.

Throws VladimirVrzic\ArrayWithSecondaryKeys\NoSuchIndexException if the given index does not exist.

getByIndex

getByIndex($index, $secondaryKey, $default = null): mixed

Retrieves a document by index (secondary key). Index is given as string in "dot" notation (e.g. state.pid).

Throws VladimirVrzic\ArrayWithSecondaryKeys\NoSuchIndexException if the given index does not exist.

updateByIndex

updateByIndex($index, $secondaryKey, $document)

Updates a document by index (secondary key). Index is given as string in "dot" notation (e.g. state.pid).

Throws VladimirVrzic\ArrayWithSecondaryKeys\NoSuchIndexException if the given index does not exist.

Returns true if the existing document associated with the given secondary key was found and replaced. Returns false if the document associated with the given secondary key was not found.

removeByIndex

removeByIndex($index, $secondaryKey)

Removes a document by index (secondary key). Index is given as string in "dot" notation (e.g. state.pid).

Throws VladimirVrzic\ArrayWithSecondaryKeys\NoSuchIndexException if the given index does not exist.

Returns true if the document associated with the given secondary key was found and removed. Returns false if a document associated with the given secondary key was not found.

putIfAbsent

putIfAbsent($key, $document): mixed

If the key doesn’t exist, adds the new key associated with the given document and returns null.

If the key exists, returns the current document.

asArray

asArray(): array

Returns a copy of the array as a normal PHP array (without secondary indexes).

primaryKeys

primaryKeys(): array

Returns an array of all primary keys.

secondaryKeys

secondaryKeys($index): array

Returns an array of all secondary keys associated with the given index.

Installation

Assuming you have PHP Composer installed, and that the composer executable is in your $PATH:

composer require cardinal-collections/array-with-secondary-keys

Name ideas

  • <[associative] array | map | dictionary> with secondary keys

  • multi-index <[associative] array | map | dictionary>