Home arrow PHP arrow PHP Service Layers: User Services

PHP Service Layers: User Services

In this fifth installment of the series, I will finally implement a fully functional user service. This additional layer will use the functionality of a mapper to run CRUD functions on user entities, as well as retrieve these domain objects in XML format.

TABLE OF CONTENTS:
  1. PHP Service Layers: User Services
  2. Building an abstract service
By: Alejandro Gervasio
Rating: starstarstarstarstar / 0
October 17, 2011

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

If you ever need to implement a pluggable structure that allow your PHP applications to interact easily with different client layers, such as several front-ends or multiple external APIs, then you might want to consider a service layer (http://martinfowler.com/eaaCatalog/serviceLayer.html). A service layer is an enterprise-level pattern that will let you achieve this kind of interaction by encapsulating application logic behind a single interface (AKA a boundary), which can be directly consumed by distinct clients.

Of course, highlighting the benefits that a service offers without adding some functional code is pretty pointless. In previous parts of this series I went through the development of a sample application, whose main responsibility is to perform CRUD operations on a few user entities that reside in a domain model completely decoupled from the storage mechanism (in this case, a MySQL database).

In its current state, the application is entirety functional. What’s more, with a little bit of effort from us, it’s perfectly feasible to fetch, save and remove user entities from the pertinent database simply by setting up a mapping layer. This layer would move data between the domain model and storage. However, making the mappers work directly with different clients is a rather inflexible approach, whose functionality is limited to that provided by the mappers themselves and nothing else.

The big question, then, is this: how can the application be turned into a more flexible and abstract structure? This is exactly where a service layer comes into play. Sitting a service on top of the mappers would make it really simple to execute the aforementioned operations, plus any others needed by a different client layer.

In this fifth installment I’ll be building such a service layer, so that you can see how easy it is to use it to manipulate user entities in all sorts of clever ways.

Now, jump in and read the next few lines!

Handling collections of entities: a quick look at the classes previously created

As always, before I show you how to implement a functional user layer, we'll quickly review the topics that were covered in the last tutorial. Below I reintroduced the pair of classes developed in that tutorial, which are tasked with manipulating collections of entities.

The first of these classes is an abstract one; it’s nothing but a simple array collection. Take a look at it:

(MyApplication/Collection/AbstractCollection.php)

<?php

namespace MyApplicationCollection;

abstract class AbstractCollection implements Iterator, Countable, ArrayAccess
{
    protected $_entities = array();
    protected $_entityClass;

    /**
     * Constructor
     */
    public function  __construct(array $entities = array())
    {
        if (!empty($entities)) {
            $this->_entities = $entities;
        }
        $this->rewind();
    }

    /**
     * Get the entities stored in the collection
     */
    public function getEntities()
    {
        return $this->_entities;
    }
   
    /**
     * Clear the collection
     */
    public function clear()
    {
        $this->_entities = array();
    }
    
    /**
     * Reset the collection (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're more entities in the collection (implementation required by Iterator Interface)
     */
    public function valid()
    {
        return ($this->current() !== false);
    }
   
    /**
     * 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 ($entity instanceof $this->_entityClass) {
            if (!isset($key)) {
                $this->_entities[] = $entity;
            }
            else {
                $this->_entities[$key] = $entity;
            }
            return true;
        }
        throw new CollectionException('The specified entity is not allowed for this collection.');
    }
   
    /**
     * Remove an entity from the collection (implementation required by ArrayAccess interface)
     */
    public function offsetUnset($key)
    {
        if ($key instanceof $this->_entityClass) {
            $this->_entities = array_filter($this->_entities, function ($v) use ($key) {
                return $v !== $key;
            });
            return true;
        }
        if (isset($this->_entities[$key])) {
            unset($this->_entities[$key]);
            return true;
        }
        return false;
    }
   
    /**
     * Get the specified entity in the collection (implementation required by ArrayAccess interface)
     */
    public function offsetGet($key)
    {
        return isset($this->_entities[$key]) ?
               $this->_entities[$key] :
               null;
    } 
   
    /**
     * Check if the specified entity exists in the collection (implementation required by ArrayAccess interface)
     */    
    public function offsetExists($key)
    {
        return isset($this->_entities[$key]);
    }
}

 

(MyApplication/Collection/CollectionException.php)

<?php

namespace MyApplicationCollection;

class CollectionException extends Exception{}

As I just noted, the previous “AbstractCollection” class is a basic wrapper for a plain PHP array that permits you to iterate, access and count its elements in a simple way, thanks to the implementation of the Iterator, Countable and ArrayAccess SPL interfaces. Nothing really complex to grasp here, right?

Now, we'll move on and look at the following subclass. It's a refined implementation of the earlier parent, and is charged with specifically handling collections of user entities:

(MyApplication/Collection/UserCollection.php)

<?php

namespace MyApplicationCollection;

class UserCollection extends AbstractCollection
{
    protected $_entityClass = 'MyApplicationEntityUser';

  
Done. At this point, it should be pretty clear how this sample application does its business in its current incarnation. Given that, the next step is… yes, to start building the user service mentioned at the beginning!

To learn the fine details of this process, click on the link below and keep reading. 



 
 
>>> 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: