Note: This article serves as preliminary for SPL Interfaces article to be published later on.
I wanted to provide good overview of (highly under-used) Standard PHP Library (SPL) starting with interfaces. However, without firstly discussing predefined interfaces, which come bundled with each and every PHP distribution, discussion of SPL-provided ones seemed to be incomplete.
To be covered in this article:
- The Traversable Interface
- The Iterator Interface
- The IteratorAggregate Interface
- The ArrayAccess Interface
- The Serializable Interface
Basically this interface is used to mark that object of the class can be used in foreach i.e. it could be traversed. This interface is internal in a sense that you cannot use it directly in your scripts, instead you have to implement either Iterator or IteratorAggregate interfaces (which extend the Traversable). Since the interface is not implementable within your PHP classes, it’s synopsis does not enforce any methods:
Traversable
{}
Extends the Traversable, this interface can be used to produce objects that can iterate themselves. As a rule of thumb: if your object holds number of some items, and you need to access them individually in foreach, Iterator (or IteratorAggregate for that matter) is the good bid. Here is the synopsis:
Iterator extends Traversable {
/* Methods */
abstract public mixed current ( void ) // return current element's value
abstract public scalar key ( void ) // return current element's key
abstract public void next ( void ) // move internal pointer forward
abstract public void rewind ( void ) // move to the beginning
abstract public boolean valid ( void ) // check if current position is valid
}
To illustrate, here is sample Iterator implementation and usage:
class Item
{
protected $title = null;
public function __construct($title)
{
$this->title = $title;
}
public function __toString()
{
return $this->title;
}
}
class Items implements Iterator
{
/**
* List of contained items
* @var array
*/
protected $items = array();
/**
* Current iterator position
* @var int
*/
protected $pos = 0;
public function add(Item $item)
{
$this->items[] = $item;
return $this;
}
/**
* Iterator methods
*/
public function current()
{
return $this->items[$this->pos];
}
public function key()
{
return $this->pos;
}
public function next()
{
$this->pos++;
}
public function rewind()
{
$this->pos = 0;
}
public function valid()
{
return isset($this->items[$this->pos]);
}
}
$items = new Items();
$items->add(new Item('milk'))
->add(new Item('butter'))
->add(new Item('bread'));
foreach($items as $key => $item) {
printf('%d - %s ', $key, $item);
}
// Output:
// 0 - milk
// 1 - butter
// 2 - bread
Pretty simple, isn’t it? Granted, it takes time to get used to, but once you do, you would never look back.
The IteratorAggregate Interface
PHP5 comes with a lot of predefined iterators (and SPL adds to the list), so you rarely need to write your own. For situations when there’s already suitable iterator for your object (either pre-build or written by you), there’s little sense to implement Iterator interface, instead it’s just enough to implement the IteratorAggregate, which allows you to use external iterators. Here is interface synopsis:
IteratorAggregate extends Traversable {
/* Methods */
abstract public Traversable getIterator( void )
}
As you see, all you have to do is to provide getIterator() method, which would return suitable instance of iterator to be used for traversal:
class Numbers implements IteratorAggregate
{
protected $numbers = array(1, 2, 3);
public function getIterator()
{
return new ArrayIterator($this->numbers);
}
}
$nums = new Numbers();
foreach($nums as $k=>$v) {
printf('%d - %d ', $k, $v);
}
// Output:
//0 - 1
//1 - 2
//2 - 3
I used predefined ArrayIterator iterator, which allows to traverse arrays and objects. You can use your own iterator as well (the only requirement is that it implements on Traversable).
One of the coolest interfaces that come with PHP5, ArrayAccess allows you to interact with your objects as if they were arrays. If you are familiar with C++, it’s like overloading [] operator (well, almost). Anyway, here is interface synopsis:
ArrayAccess {
// whether an offset exists
abstract public boolean offsetExists( mixed $offset )
// returns the value at specified offset
abstract public mixed offsetGet( mixed $offset )
// assigns a value to the specified offset
abstract public void offsetSet( mixed $offset , mixed $value )
// unsets an offset
abstract public void offsetUnset( mixed $offset )
}
Don’t worry if interface doesn’t seem simple at first, everything would clear up once you review the example:
class Config implements ArrayAccess
{
protected $options = array(
'username' => 'torio',
'uri' => 'http://www.phpmag.ru/'
);
/**
* ArrayAccess implementation
*/
public function offsetExists($offset)
{
return isset($this->options[$offset]);
}
public function offsetGet($offset )
{
return $this->options[$offset];
}
public function offsetSet($offset, $value )
{
$this->options[$offset] = $value;
}
public function offsetUnset($offset )
{
unset($this->options[$offset]);
}
}
$config = new Config();
if(isset($config['uri'])) { // offsetExists() is called internally
printf('URI: %s ', $config['uri']); // offsetGet()
}
$config['username'] = 'vic'; // offsetSet()
printf('Username: %s', $config['username']);
unset($config['uri']); // offsetUnset()
if(!isset($config['uri'])) {
echo 'Offset deleted..';
}
// Output:
// URI: http://www.phpmag.ru/
// Username: vic
// Offset deleted..
Note: As of PHP 5.3 it is possible to return the value at a given offset by reference.
This is the last of predefined interfaces, and is actually quite a simple one (if you are familiar with data serialization). If you want your object to control its serialization/unserialization process you can either use magic methods __sleep()/__wakeup() or, more explicitly, just to implement the Serializable interface:
Serializable {
/* Methods */
abstract public string serialize( void )
abstract public mixed unserialize( string $serialized )
}
Here is trivial example:
class Item implements Serializable
{
protected $title = null;
public function __construct($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
/**
* Serializable implementation
*/
public function serialize()
{
return serialize(array($this->title));
}
public function unserialize($serialized )
{
list($title) = unserialize($serialized);
// this method is invoked as constructor, if you need to use
// default constructor, invoke it manually:
$this->__construct($title);
}
}
$serialized = serialize(new Item('milk'));
$obj = unserialize($serialized);
printf('Title: %s ', $obj->getTitle()); // Title: milk
That’s about it! If you liked the article, consider subscribing to RSS, so that you can follow up the incoming SPL tutorials.

I think that also SplQueue and SplStack could be defined as interfaces, but there is a lack of interfaces in php: I miss Collection, List, Set, Map…
[...] interfaces presupposes that you know standard interfaces that come build-in with PHP5. So, I wrote preliminary article discussing them – I consider it to be a prerequisite for good understanding of the current [...]
Giorgio,
).
SplQueue and SplStack are data-structures, not interfaces i.e. they provide implementation (and a lot of
As about missing data-structures, well, it depends on what you knew before coming into PHP – if you have some well-abstracted language under your belt..mm, PHP wouldn’t make you very happy. In essence, it is really simple language that does its job. It’s only with PHP5 any serious attempts started to make PHP meet enterprise (due to its popularity, language needed quite an update to suit the growing practitioners’ needs).
[...] PHP5: Predefined Interfaces [...]
[...] PHP5: Predefined Interfaces [...]
[...] PHP5: Predefined Interfaces [...]