SplObjectStorage
In this post I will look at SplObjectStorage: a container that allows to store objects uniquly without the need to compare them one by one.
Adding objects
So, what can the SplObjectStorage do for you? Let’s see how it behaves when we start to use it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <?php /** * Test class that we will store in the * SplObjectStorage object. */ class StorageTest { private $title; public function __construct( $title ) { $this->title = $title; } public function __toString() { return $this->title; } } $storage = new SplObjectStorage(); $obj = new StorageTest( "wiki.cc" ); $storage->attach( $obj ); $obj2 = new StorageTest( "eide.org" ); $storage->attach( $obj2 ); foreach( $storage as $o ) { echo $o; echo "\n"; } ?> |
And this will, as you most likely would think, display the following:
wiki.cc eide.org
The SplObjectStorage class implements Iterator and Countable, so we can use the storage object as any other objects that implement these. Just look at this:
1 | echo count($storage ); |
Will output “2″
Adding the same object
The SplObjectStorage is, as the name suggests, a storage, so what will happen if we add the same object twice?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?php /** * Test class that we will store in the * SplObjectStorage object. */ class StorageTest { private $title; public function __construct( $title ) { $this->title = $title; } public function __toString() { return $this->title; } } $storage = new SplObjectStorage(); $obj = new StorageTest( "www.eide.org" ); $storage->attach( $obj ); $storage->attach( $obj ); foreach( $storage as $o ) { echo $o; echo "\n"; } ?> |
We now get:
www.eide.org
as output. So: the SplObjectStorage object can tell if you add the same object more than one time, this way we can keep adding N objects to the storage, and we can be sure that when we iterate over the object we will only get unique objects.
Updating objects
What then, if we update a object, will we get more than one object when we iterate over the storage?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <?php /** * Test class that we will store in the * SplObjectStorage object. */ class StorageTest { private $title; public function __construct( $title ) { $this->title = $title; } public function __toString() { return $this->title; } public function setTitle( $title ) { $this->title = $title; } } $storage = new SplObjectStorage(); $obj = new StorageTest( "wiki.cc" ); $storage->attach( $obj ); $obj->setTitle( "eide.org" ); $storage->attach( $obj ); foreach( $storage as $o ) { echo $o; echo "\n"; } ?> |
We now get:
eide.org
So: we can see that the storage object keeps track of the fact that we are manipulating the same object, and we can safely manipulate objects when adding them to the storage.
Check for objects added
With a storage like SplObjectStorage it is always interesting to check if a certain item has been added or not, this feature is covered with the contains() function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <?php /** * Test class that we will store in the * SplObjectStorage object. */ class StorageTest { private $title; public function __construct( $title ) { $this->title = $title; } public function __toString() { return $this->title; } } $storage = new SplObjectStorage(); $obj = new StorageTest( "wiki.cc" ); $storage->attach( $obj ); $obj2 = new StorageTest( "eide.org" ); if( $storage->contains( $obj ) ) { echo "storage contains the object\n"; } else { echo "storage does NOT contain the object\n"; } if( $storage->contains( $obj2 ) ) { echo "storage contains the object\n"; } else { echo "storage does NOT contain the object\n"; } ?> |
This will give us the following output:
storage contains the object storage does NOT contain the object
And you can see that SplObjectStorage correctly detects which of the two objects that has been added to it.
Detaching objects
With adding objects there always comes the time when you want to remove a object: this is covered by the detach() function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <?php /** * Test class that we will store in the * SplObjectStorage object. */ class StorageTest { private $title; public function __construct( $title ) { $this->title = $title; } public function __toString() { return $this->title; } } $storage = new SplObjectStorage(); $obj = new StorageTest( "eide.org" ); $storage->attach( $obj ); if( $storage->contains( $obj ) ) { echo "storage contains the object\n"; } else { echo "storage does NOT contain the object\n"; } $storage->detach( $obj ); if( $storage->contains( $obj ) ) { echo "storage contains the object\n"; } else { echo "storage does NOT contain the object\n"; } ?> |
This will give us:
storage contains the object storage does NOT contain the object
Finally
The SplObjectStorage object is a nice addition to the SPL family that will ease the use of object collections without worrying about what objects you already have added to the mix.
Nice general purpose class.. Spl is very useful as its OO approach make OO programming in php easier as developers don’t have to reinvent the wheel every time an iterator is needed.. I think it is ‘the right way’ of writing php code.
Now this SplObjectStorage will be a cute candidate for subclassing to make complex objects..
[...] Eide has a recent post to his blog that looks at a part of the Standard PHP Library (SPL) that can be used with objects to [...]