Home arrow PHP arrow Page 2 - An Entity Manager for a Unit of Work in PHP

Factoring Units of Work with a factory class - PHP

In this fifth part of a series, I create a simple entity manager class, which can switch over multiple UoWs by using a single method call. The class will inject into its internals a factory responsible for spawning different UoWs on request. This will permit you to decouple object instantiation from application logic.

TABLE OF CONTENTS:
  1. An Entity Manager for a Unit of Work in PHP
  2. Factoring Units of Work with a factory class
By: Alejandro Gervasio
Rating: starstarstarstarstar / 2
January 05, 2011

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

We need to take one more step before creating the entity manager mentioned in the previous segment. You're wondering what is it, right? Well, considering that the manager will be able to use multiple UoWs at runtime, it'd be useful to inject into it a factory that creates instances of those UoWs on request.

If my description sounds somewhat confusing to you, just look at the following fragment, which shows the source code of the factory:

(UnitOfWorkFactory.php)

<?php

class UnitOfWorkFactory
{  
    /**
     * Create a Unit of Work with the specified name
     */
    public function create($name)
    {
        $name = ucfirst(strtolower($name));
        $collection = $name . 'Collection';
        $dataMapper = $name . 'Mapper';
        $unitOfWork = $name . 'UnitOfWork';
        return new $unitOfWork(
            new $dataMapper(
                MySQLAdapter::getInstance(), new $collection
            )
        );
    }
}

As you can see above, the previous "UnitOfWorkFactory" class implements a single method, called "create()", which takes as an incoming argument the name of the UoW that needs to be spawned. Finally, the method uses this argument to instantiate all of the pertinent dependencies, and returns to client code a fully-functional UoW object. Do you understand how the factory does its thing? I bet you do.

Moreover, the definition of this class not only separates object instantiation from application logic, but it shows how to wire together some of the classes discussed in earlier tutorials of the series.

So far, so good. Now that you understand the purpose of building the previous factory class, it's finally time to define the entity manager. The details of this process will be discussed below.

Building an entity manager class

As I said at the beginning of this tutorial, the entity manager class that I plan to build will act like a simple "switcher" capable of swapping multiple UoWs at runtime. To do this, however, it must use the functionality of the factory defined above, which means that the latter must be injected into the manager like a sort of service locator.

It's time to stop talking and show the source code of the entity manager, so you can grasp its logic. Here's the brand new class:  

(EntityManager.php)

<?php

class EntityManager
{
    protected $_unitOfWorkFactory;
    protected $_unitOfWorks = array();
    protected $_currentUnitOfWork;
   
    /**
     * Class constructor
     */
    public function __construct(UnitOfWorkFactory $unitOfWorkFactory)
    {
        $this->_unitOfWorkFactory = $unitOfWorkFactory;
        $this->init();
    }
   
    /**
     * Initialize the entity manager here
     */
    public function init()
    {
        $this->addUnitOfWork('user');
    }
   
    /**
     * Get the Unit of Work factory
     */
    public function getUnitOfWorkFactory()
    {
        return $this->_unitOfWorkFactory;
    }
   
    /**
     * Add a new Unit of Work by specifying its key
     */
    public function addUnitOfWork($key)
    {
        $key = strtolower($key);
        if (!array_key_exists($key, $this->_unitOfWorks)) {
            $unitOfWork = $this->_unitOfWorkFactory->create($key);
            $this->_unitOfWorks[$key] = $unitOfWork;
            $this->setCurrentUnitOfWork($key);
        }
        return $this;
    }
   
    /**
     * Add multiple Units of Work by specifying an array of keys
     */
    public function addUnitOfWorks(array $keys)
    {
        if (!empty($keys)) {
            foreach ($keys as $key) {
                $this->addUnitOfWork($key);
            } 
        }
        return $this;
    }
   
    /**
     * Get all the Units of Work
     */  
    public function getUnitOfWorks()
    {
        return $this->_unitOfWorks;
    }
   
    /**
     * Set the current Unit of Work
     */
    public function setCurrentUnitOfWork($key)
    {
        $key = strtolower($key);
        if (!array_key_exists($key, $this->_unitOfWorks)) {
            throw new EntityManagerException('The specified Unit of Work is not valid.');  
        }
        $this->_currentUnitOfWork = $this->_unitOfWorks[$key];
        return $this;
    }
   
    /**
     * Get the current Unit of Work
     */
    public function getCurrentUnitOfWork()
    {
        if ($this->_currentUnitOfWork === null) {
            throw new EntityManagerException('No current Unit of Work has been set yet.');
        }
        return $this->_currentUnitOfWork;
    }
   
    /**
     * Set the specified entity 'new'
     */
    public function setNew(EntityAbstract $entity)
    {
        $this->getCurrentUnitOfWork()->setNew($entity);       
    }
   
    /**
     * Set the specified entity 'clean'
     */
    public function setClean(EntityAbstract $entity)
    {
        $this->getCurrentUnitOfWork()->setClean($entity);       
    }
   
    /**
     * Set the specified entity 'dirty'
     */
    public function setDirty(EntityAbstract $entity)
    {
        $this->getCurrentUnitOfWork()->setDirty($entity);       
    }
   
    /**
     * Set the specified entity 'removed'
     */
    public function setRemoved(EntityAbstract $entity)
    {
        $this->getCurrentUnitOfWork()->setRemoved($entity);       
    }
   
    /**
     * Clear the 'new' entities stored in the current Unit of Work
     */
    public function clearNew()
    {   
        $this->getCurrentUnitOfWork()->clearNew();
    }
   
    /**
     * Clear the 'clean' entities stored in the current Unit of Work
     */
    public function clearClean()
    {   
        $this->getCurrentUnitOfWork()->clearClean();
    }
   
    /**
     * Clear the 'dirty' entities stored in the current Unit of Work
     */
    public function clearDirty()
    {   
        $this->getCurrentUnitOfWork()->clearDirty();
    }
   
    /**
     * Clear the 'removed' entities stored in the current Unit of Work
     */
    public function clearRemoved()
    {   
        $this->getCurrentUnitOfWork()->clearRemoved();
    }
   
    /**
     * Clear the entities stored in all the Units of Work
     */
    public function clearAll()
    {
        if (!empty($this->_unitOfWorks)) {
            foreach ($this->_unitOfWorks as $unitOfWork) {
                $unitOfWork->clearAll();
            } 
        }
    }
   
    /**
     * Find an entity by its ID
     */  
    public function findById($id)
    {
        return $this->getCurrentUnitOfWork()->findById($id);
    }
   
    /**
     * Find all the entities
     */
    public function findAll()
    {
        return $this->getCurrentUnitOfWork()->findAll();  
    } 
   
    /**
     * Commit all the pending entity operations (create, update, remove)
     */
    public function commit()
    {
        if (!empty($this->_unitOfWorks)) {
            foreach ($this->_unitOfWorks as $unitOfWork) {
                $unitOfWork->commit();
            }   
        }
    }           
}

 

(EntityManagerException.php)

<?php

class EntityManagerException extends Exception {}

To be frank, there's no reason to feel intimidated by the rather long definition of the above "EntityManager" class. The tasks that it performs are fairly straightforward. The manager is nothing but a wrapper for a Unit of Work, except that in this case it's capable of using multiple UoWs via its complementary "setCurrentUnitOfWork()" and "addUnitOfWork()" methods. What's more, the latter uses  the injected factory internally to create a UoW with the specified name. That's quite simple to grasp, isn't it?

In addition, you should notice that the class's "init()" method creates by default a UoW that specifically manipulates user entities. While this may not make much sense now, it will later on. In a coming tutorial I plan to demonstrate how to implement a UoW that executes transactional operations in user entities, so defining the method that way offers a pretty solid foundation.

But I'm getting ahead of myself, since the implementation of a concrete UoW will be covered in depth in another installment of this series.  

Final thoughts

In this fifth installment of the series, I created a simple entity manager class, which is capable of switching over multiple UoWs by using something as simple as a single method call. Also, the class injects into its internals a factory responsible for spawning different UoWs on request, which permits you to decouple object instantiation from application logic.

With the previous entity manager already up and running, the conditions are finally set to create an example application that shows how to put the sample UoW in action. In line with this concept, in the coming tutorial I'm going to start defining the building blocks of this application, which will be tasked with performing CRUD operations on a few user entities.

Here's my final piece of advice: 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: