ramsey/collection
repository·main·Indexed 22 days ago
https://github.com/ramsey/collectionA PHP library for representing and manipulating collections, inspired by the Java Collections Framework. It provides robust tools for type-safe collections, including implementations for Queue, DoubleEndedQueue, Set, TypedMap, and NamedParameterMap.
What's inside ramsey/collection
- ramsey/collection is a PHP library designed for representing and manipulating collections. Its design and functionality are inspired by the Java Collections Framework.
Install ramsey/collection via Composer
mainTo use this library in your PHP project, install it as a dependency using Composer.
composer require ramsey/collectionExtend TypedMap or AbstractTypedMap for custom implementations
mainWhile you can use
TypedMapdirectly, it is often preferable to subclassAbstractTypedMapto create a specialized typed map implementation. This allows you to hardcode the key and value types within the class definition.There are two ways to extend the functionality:
- Subclassing
AbstractTypedMap: Best for creating a clean, custom implementation where you definegetKeyType()andgetValueType()methods. - Subclassing
TypedMap: Best for creating a specialized version of the existingTypedMapby overriding the constructor to pass specific types to the parent.
// Option 1: Subclassing AbstractTypedMap class FooTypedMap extends AbstractTypedMap { public function getKeyType() { return 'int'; } public function getValueType() { return Foo::class; } } // Option 2: Subclassing TypedMap class FooTypedMap extends TypedMap { public function __construct(array $data = []) { parent::__construct('int', Foo::class, $data); } }- Subclassing
Create custom typed collections by subclassing AbstractCollection
mainFor better type safety and the ability to perform type-checking on the collection object itself (e.g., using
instanceof), it is recommended to subclassRamsey\Collection\AbstractCollectioninstead of using the baseCollectionclass. When subclassing, you must implement thegetType()method to return the string name of the class type the collection holds.namespace My\Foo; class FooCollection extends \Ramsey\Collection\AbstractCollection { public function getType(): string { return 'My\\Foo'; } } // Usage: $fooCollection = new \My\Foo\FooCollection(); $fooCollection->add(new \My\Foo()); if ($fooCollection instanceof \My\Foo\FooCollection) { // This collection is guaranteed to be a collection of My\Foo objects }Use the Collection class for quick typed collections
mainThe
Ramsey\Collection\Collectionclass is a direct implementation ofCollectionInterfaceused to represent a group of objects of a specific type. You can instantiate it by passing the fully qualified class name of the objects it should contain as the first argument to the constructor. This is useful for quick implementations where you don't want to create a custom subclass.$collection = new \Ramsey\Collection\Collection('My\\Foo'); $collection->add(new \My\Foo()); $collection->add(new \My\Foo()); foreach ($collection as $foo) { // $foo is an instance of My\Foo }Use NamedParameterMap to manage typed named parameters
mainThe
NamedParameterMapclass is a specialized map implementation designed to hold values associated with a predefined set of named keys. It enforces two constraints:- Key Restriction: You can only set values for keys that were explicitly defined in the
$namedParametersarray during construction. Attempting to set an unconfigured key throws aRamsey\Collection\Exception\InvalidArgumentException. - Type Enforcement: If a type is specified for a named parameter, the map validates that any value assigned to that key matches the required type. If validation fails, it throws a
Ramsey\Collection\Exception\InvalidArgumentException.
When constructing the map, the
$namedParametersarray can be defined in two ways:- Keyed by name:
['param_name' => 'type'](e.g.,['id' => 'int']). - Indexed list:
['param_name_1', 'param_name_2'](where types default tomixed).
use Ramsey\Collection\Map\NamedParameterMap; // Define parameters: 'id' must be an int, 'name' must be a string, 'meta' is mixed $config = [ 'id' => 'int', 'name' => 'string', 'meta' ]; $map = new NamedParameterMap($config, ['id' => 1, 'name' => 'John Doe']); // Valid operations $map['id'] = 2; $map['meta'] = ['foo' => 'bar']; // This will throw InvalidArgumentException (unconfigured key) // $map['unknown'] = 'value'; // This will throw InvalidArgumentException (type mismatch) // $map['id'] = 'not-an-int'; // Retrieve the configuration $params = $map->getNamedParameters();- Key Restriction: You can only set values for keys that were explicitly defined in the
Use DoubleEndedQueue for FIFO and LIFO operations
mainThe
DoubleEndedQueueclass is a concrete implementation ofDoubleEndedQueueInterfacethat allows you to add or remove elements from both the front (head) and the back (tail) of the collection. It extends the baseQueueclass and enforces type safety based on a provided$queueType.Key Operations
Adding Elements
addFirst(mixed $element): bool: Adds an element to the front. ThrowsInvalidArgumentExceptionif the type is incorrect.addLast(mixed $element): bool: Adds an element to the back (alias foradd()).offerFirst(mixed $element): bool: Attempts to add to the front. Returnsfalseinstead of throwing an exception if the type is incorrect.offerLast(mixed $element): bool: Attempts to add to the back. Returnsfalseif the type is incorrect.
Removing Elements
removeFirst(): mixed: Removes and returns the first element. ThrowsNoSuchElementExceptionif empty.removeLast(): mixed: Removes and returns the last element. ThrowsNoSuchElementExceptionif empty.pollFirst(): mixed|null: Returns the first element ornullif the queue is empty.pollLast(): mixed|null: Returns the last element ornullif the queue is empty.
Inspecting Elements
firstElement(): mixed: Returns the first element. ThrowsNoSuchElementExceptionif empty.lastElement(): mixed: Returns the last element. ThrowsNoSuchElementExceptionif empty.peekFirst(): mixed|null: Returns the first element ornullif empty.peekLast(): mixed|null: Returns the last element ornullif empty.
use Ramsey\Collection\DoubleEndedQueue; // Initialize with a type (e.g., 'string') and optional initial data $queue = new DoubleEndedQueue('string', ['a', 'b']); $queue->addFirst('start'); // ['start', 'a', 'b'] $queue->addLast('end'); // ['start', 'a', 'b', 'end'] $first = $queue->removeFirst(); // 'start' $last = $queue->removeLast(); // 'end'Use the Set class for unique collections
mainThe
Setclass provides a collection that ensures all elements are unique. When adding an element, theadd()method returnstrueif the element was successfully added andfalseif the element already exists in the set.Warning on Mutable Objects: If you use mutable objects as set elements, changing the object's value in a way that affects equality comparisons while it is in the set can lead to undefined behavior. Use caution when storing objects that can change state.
$foo = new \My\Foo(); $set = new Set(\My\Foo::class); $set->add($foo); // returns TRUE, the element doesn't exist $set->add($foo); // returns FALSE, the element already exists $bar = new \My\Foo(); $set->add($bar); // returns TRUE, $bar !== $fooUse TypedMap to enforce type constraints on keys and values
mainThe
TypedMapclass is a map implementation where both keys and values must adhere to specific types. You instantiate it by providing the key type (as a string, e.g.,'string'or'int') and the value type (as a string, e.g., a class name likeFoo::class).When attempting to assign a key or value that does not match the defined types, the map will throw an exception. You can also initialize the map with an existing array of data.
Key behaviors:
- Keys must be unique.
- Values can be repeated but must be associated with different keys.
- The map is iterable via
foreach.
$map = new TypedMap('string', Foo::class); $map['x'] = new Foo(); foreach ($map as $key => $value) { // $key is a string, $value is an instance of Foo } // Initialize with data $map = new TypedMap('string', Foo::class, [ new Foo(), new Foo() ]);Use the Queue class for sequential data processing
mainThe
Ramsey\Collection\Queueclass is a basic implementation ofQueueInterfacethat extendsAbstractArray. It is designed for First-In-First-Out (FIFO) data processing. When instantiating aQueue, you must provide a$queueType(a string representing the expected type or class name) to ensure type safety for all elements added to the queue.Key behaviors:
- Type Safety: Adding an element of the wrong type via
add()or array offset assignment will throw aRamsey\Collection\Exception\InvalidArgumentException. - Non-throwing Offer: The
offer()method attempts to add an element but returnsfalseinstead of throwing an exception if the type is incorrect. - Empty Queue Handling: Methods like
element()andremove()throw aRamsey\Collection\Exception\NoSuchElementExceptionif called on an empty queue, whereaspeek()andpoll()returnnull.
use Ramsey\Collection\Queue; // Create a queue for strings $queue = new Queue('string'); // Add elements $queue->add('first'); $queue->offer('second'); // Peek at the first element without removing it echo $queue->peek(); // 'first' // Remove and return the first element echo $queue->poll(); // 'first' // Get the current head element (throws exception if empty) echo $queue->element();- Type Safety: Adding an element of the wrong type via
Queue API Reference
mainThe
Ramsey\Collection\Queueclass provides the following public methods for managing queue elements:Method Return Type Description __construct(string $queueType, array $data = [])voidInitializes the queue with a specific type and optional initial data. add(mixed $element): boolboolAdds an element to the end of the queue. Throws InvalidArgumentExceptionif type mismatch.element(): mixedTReturns the head element. Throws NoSuchElementExceptionif the queue is empty.offer(mixed $element): boolboolAttempts to add an element. Returns trueon success,falseif the type is invalid.peek(): mixed|nullT|nullReturns the head element without removing it. Returns nullif the queue is empty.poll(): mixed|nullT|nullRemoves and returns the head element. Returns nullif the queue is empty.remove(): mixedTRemoves and returns the head element. Throws NoSuchElementExceptionif the queue is empty.getType(): stringstringReturns the type or class name associated with this queue. Queue Exceptions
mainWhen working with
Ramsey\Collection\Queue, you should handle the following exceptions:Ramsey\Collection\Exception\InvalidArgumentException: Thrown byadd()oroffsetSet()when an element does not match the$queueTypedefined during construction.Ramsey\Collection\Exception\NoSuchElementException: Thrown byelement()orremove()when attempting to retrieve an item from an empty queue.