Today 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 ) ; //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.