Home arrow PHP arrow Page 2 - Handling Collections of Domain Objects in PHP

Building a class to handle collections of entities - PHP

In this fourth part of the series, I will build a simple countable iterator. It will be able to easily manipulate collections of entities by using an array-like notation. What’s more, if you frequently implement different kinds of inner iterators, then you'll quickly understand the logic behind this one.

TABLE OF CONTENTS:
  1. Handling Collections of Domain Objects in PHP
  2. Building a class to handle collections of entities
By: Alejandro Gervasio
Rating: starstarstarstarstar / 5
January 03, 2011

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

Actually, there are several approaches that can be used for handling collections of entities in a simple way. In this case, however, I will rely on building a countable iterator, which will also be able to  access stored entities such as plain array elements.

In fact, I developed a similar iterator when I discussed how to implement a repository in PHP here (http://www.devshed.com/c/a/PHP/Roll-Your-Own-Repository-in-PHP-Working-with-Collections-of-Entities/1/), so if you've already read that tutorial, you'll find the logic of the class below quite familiar. Here it is:

(CollectionAbstract.php)

<?php

abstract class CollectionAbstract implements Iterator, Countable, ArrayAccess
{
    protected $_entities = array();
   
    /**
     * Get the entities stored in the collection
     */
    public function getEntities()
    {
        return $this->_entities;
    }
   
    /**
     * Clear the collection of entities
     */
    public function clear()
    {
        $this->_entities = array();
    }
   
    /**
     * Reset the collection of entities (implementation required by Iterator Interface)
     */
    public function rewind()
    {
        reset($this->_entities);
    }
   
    /**
     * Get the current entity in the collection (implementation required by Iterator Interface)
     */ 
    public function current()
    {
        return current($this->_entities);
    }
   
    /**
     * Move to the next entity in the collection (implementation required by Iterator Interface)
     */
    public function next()
    {
        next($this->_entities);
    }
   
    /**
     * Get the key of the current entity in the collection (implementation required by Iterator Interface)
     */
    public function key()
    {
        return key($this->_entities);
    }
   
    /**
     * Check if there are more entities in the collection (implementation required by Iterator Interface)
     */
    public function valid()
    {
        return (boolean) $this->current();
    }
   
    /**
     * Count the number of entities in the collection (implementation required by Countable Interface)
     */
    public function count()
    {
        return count($this->_entities);
    }
   
    /**
     * Add an entity to the collection (implementation required by ArrayAccess interface)
     */
}

The above "CollectionAbstract" class is an implementer of the Iterator, Countable and ArrayAccess native PHP interfaces, which makes it possible to build an API that permits you to traverse collections of entities using a "foreach" construct, and even count the number of entities present in a specific collection.

Of course, if you try the class in its current state, you'll get an ugly fatal error from the PHP engine. It still doesn't implement the methods declared by the ArrayAccess interface. It's time to add this functionality to the class, so you can see how it looks when finished.

This will be accomplished in the lines to come, so keep reading.

Implementing the ArrayAccess PHP interface

If you want to see how the earlier "CollectionAbstract" class looks after implementing the set of methods defined by the ArrayAccess PHP interface, below I included the class' full source code. This way you can analyze it in a more detailed manner. Here it is:

(CollectionAbstract.php)

<?php

abstract class CollectionAbstract implements Iterator, Countable, ArrayAccess
{
    protected $_entities = array();
   
    /**
     * Get the entities stored in the collection
     */
    public function getEntities()
    {
        return $this->_entities;
    }
   
    /**
     * Clear the collection of entities
     */
    public function clear()
    {
        $this->_entities = array();
    }
   
    /**
     * Reset the collection of entities (implementation required by Iterator Interface)
     */
    public function rewind()
    {
        reset($this->_entities);
    }
   
    /**
     * Get the current entity in the collection (implementation required by Iterator Interface)
     */ 
    public function current()
    {
        return current($this->_entities);
    }
   
    /**
     * Move to the next entity in the collection (implementation required by Iterator Interface)
     */
    public function next()
    {
        next($this->_entities);
    }
   
    /**
     * Get the key of the current entity in the collection (implementation required by Iterator Interface)
     */
    public function key()
    {
        return key($this->_entities);
    }
   
    /**
     * Check if there are more entities in the collection (implementation required by Iterator Interface)
     */
    public function valid()
    {
        return (boolean) $this->current();
    }
   
    /**
     * Count the number of entities in the collection (implementation required by Countable Interface)
     */
    public function count()
    {
        return count($this->_entities);
    }
   
    /**
     * Add an entity to the collection (implementation required by ArrayAccess interface)
     */
    public function offsetSet($key, $entity)
    {
        if ($key === null) {
            if (!in_array($key, $this->_entities, true)) {
                $this->_entities[] = $entity;
                return;
            }
        }
        else if (!array_key_exists($key, $this->_entities)) {
            $this->_entities[$key] = $entity;
        }
    }
   
    /**
     * Remove an entity from the collection (implementation required by ArrayAccess interface)
     */
    public function offsetUnset($key)
    {
        if ($key instanceof EntityAbstract) {
            $entities = array();
            foreach ($this->_entities as $_entity) {
                if ($_entity !== $key) {
                    $entities[] = $_entity;
                }  
            }
            $this->_entities = $entities;
            return;
        }
        if (array_key_exists($key, $this->_entities)) {
            unset($this->_entities[$key]);
        }
    }
   
    /**
     * Get the specified entity from the collection (implementation required by ArrayAccess interface)
     */
    public function offsetGet($key)
    {
        return array_key_exists($key, $this->_entities) ?
               $this->_entities[$key] :
               null;
    } 
   
    /**
     * Check if the specified entity exists in the collection (implementation required by ArrayAccess interface)
     */    
    public function offsetExists($key)
    {
        return array_key_exists($key, $this->_entities);
    }
}

Mission accomplished, at least for now. Although the definition of this class seems to be somewhat irrelevant to the construction of a fully-functional Unit of Work, this is simply a misleading impression, trust me. When I show you how to put this class and others to work together, you'll see how neatly each piece fits into the schema dictated by the pattern.

Of course, this shouldn't stop you from playing with all of the code samples shown in this tutorial and tweaking them at will. So go ahead. You'll have a pretty good time, guaranteed! 

Final thoughts

In this fourth episode of the series, I built a simple countable iterator which could manipulate collections of entities by using an array-like notation. What's more, if you frequently implement different kinds of inner iterators, then the driving logic of the one coded in this tutorial should be fairly easy to grasp for you.

While it could be said that the scenario is finally set to start using the sample UoW developed in the first installment of the series (remember that one, right?), there's one more step that we still must take.  Since in most cases the domain layer of an application will be comprised of different kinds of entities, namely blog posts, comments, users and so forth, it'd be really helpful to create an abstraction layer that permits us to swap multiple UoWs at runtime.

To fit this requirement, in the upcoming tutorial I'm going to create an entity manager class (basically a very slimmed down version of the one included with Doctrine 2.0). It will be capable of handling entities by switching over distinct UoWs.

Want to see how this will be done? Then don't miss the next part! 



 
 
>>> More PHP Articles          >>> More By Alejandro Gervasio
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PHP ARTICLES

- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: