Generic collections in PHP
September 17, 2008 – 10:46 am Tags: PHPToday while reading PHP::Impact’s refactoring guideline post I was reminded about collections.
As you probably know, arrays are very flexible in PHP and probably a good choice for many data storing tasks.
Strictly typed languages usually use “generic” collection classes instead of arrays. They are kind of like PHP arrays which the programmer can tell which type of items to accept. This is of course only natural when you don’t have dynamic typing, but it can also be useful for avoiding programming errors, so I thought I’d try making a basic generic collection class in PHP…
A basic generic collection
The idea was to make a simple class that could be used as a generic collection. You would have to be able to tell it which type it stores, and it would need to make sure that it won’t accept any other types.
By using some features from SPL, we can also make it work more like an array and not a class: implementing Countable, IteratorAggregate and ArrayAccess makes it possible to handle classes similar to arrays in looping, count() calls and accessing them by index.
Code
As always, the code for the class is available here, in my svn repo.
The class gives you some basic methods for playing with it: add(), remove(), get(), exists(), count(), set(), which all should be quite self explanatory.
Here’s an usage example:
//This collection only accepts strings $coll = new CU_Collection('string'); //Add a string and echo it $coll->add('This is a string'); echo $coll[0]; //This will throw an InvalidArgumentException $coll->add(1000);
The collection also works with classes: Instead of ’string’, pass it ‘SomeClass’ in construct, and then it will only accept instances of SomeClass.
There are two limitations here, though: The collection only accepts numeric indexes, and you can’t use interfaces or base classes as the type. Adding interface support could probably be done through reflection, or by modifying the code which checks the type a bit.












7 Responses to “Generic collections in PHP”
Maybe it would be better for objects to use the instanceof check?
That would work for interfaces and object inheritance.
Unfortinatly you can’t do class casting in PHP to force a child object to be casted to the parent class (without dirty serialize hacks).
By Harro on Sep 17, 2008
Have you tried to extend or aggregate SplObjectStorage ?
It’s a cool object to make collections ^^
By julien-pauli on Sep 17, 2008
I made some enhancements to your collection class:
Any type that has anything that has a matching “is_*” function listed in link http://us2.php.net/manual/en/ref.var.php can be used. Anything else is assumed to be the name of a class or interface.
Also, CU_Collection::isValidType() will return true for objects if the class or interface of the collection appears anywhere in the inheritance chain of the object.
Demo: http://aheimlich.dreamhosters.com/generic-collections/
By Aaron Heimlich on Sep 19, 2008
I think it’s better with instanceof. I just had the weird notion that I might want to store precise classes in it, though I don’t know why… However, I don’t really see the point of your change to check for the is_something function - in my opinion it’s just doing the same the gettype comparison does, but in a different way.
By Jani Hartikainen on Sep 20, 2008
>However, I don’t really see the point of your
>change to check for the is_something function -
>in my opinion it’s just doing the same the
>gettype comparison does, but in a different way.
I quote from the gettype documentation page[1]:
Warning
Never use gettype() to test for a certain type, since the returned string may be subject to change in a future version. In addition, it is slow too, as it involves string comparison.
Instead, use the is_* functions.
[1] http://www.php.net/gettype
By Aaron Heimlich on Sep 20, 2008
Ah, of course. Makes sense now =)
By Jani Hartikainen on Sep 20, 2008
yeah this is very basic, and i agree with jani…
By spaz on Oct 10, 2008