Home arrow PHP arrow PHP Service Layers: Modeling Domain Objects

PHP Service Layers: Modeling Domain Objects

In this first part of a series, I introduce you to what a service layer is and how to use it in conjunction with an MVC stack. While you donít need to use one in every possible case, a service layer can be of great help in interfacing sections of an application with multiple client layers.

TABLE OF CONTENTS:
  1. PHP Service Layers: Modeling Domain Objects
  2. Taking the first step: modeling domain objects
By: Alejandro Gervasio
Rating: starstarstarstarstar / 0
October 11, 2011

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

While an MVC stack can be implemented in several different ways (quite possibly there exists one per developer), you know that a minimalist approach goes in general with the following application flow: once a request has been triggered within the user interface, the front controller does some routing and dispatches the request to the appropriate action controller, along with the associated argument(s).

In turn, the action controller grabs one or more models and uses them to perform CRUD operations in the persistence layer (usually a RDBMS, but it could be a web service or anything else). Finally, the user interface is updated accordingly by passing to the view(s) the result of the operations (i.e. a list of database records, an updated form, or whatever is suitable for that specific request). From that point on, the entire operation cycle can be restarted over and over again, according to the actions triggered by the user.

Although Iíd agree that this schema is pretty efficient when implemented in a few simple use cases, unfortunately it doesnít scale up very well. As an application grows in size and complexity, itís necessary to take a more flexible approach. Thees include decoupling the models from the underlying storage (yes, the model = database equation is incorrect); implementing some mapping/repository layers; or even developing an independent, clean domain model, whose participants, entities and value objects, are persistence agnostic.

The scenario can become even more complicated, especially when itís necessary to perform some additional tasks, such as pulling in data from an external API (Twitter, Facebook), or interoperating with different front-ends. Now, imagine that you need to translate all of that functionality to each action controller in the original MVC layer described above. You'd end up not only having really fat controllers, but code duplication will reach alarming levels (even if youíre a copy/paste master). And if you ever needed to migrate your application to another infrastructure or framework...well, I wouldnít want to be in your shoes in a case like this, trust me!

So, what can be done to tackle such a situation without pulling your hair out? Well, there are a few approaches that can be taken. Thereís one, however, that's particularly engaging because of its straightforward implementation. As this articleís title suggests, Iím talking about a service layer.

A service layer is an enterprise-level pattern that permits you to encapsulate application logic behind a single interface (or a boundary, to express it a la Fowler). With this interface shielding from the outside all of the operations that are internally performed by a program, itís really simple to create complex services that can be consumed by different front-ends or by distinct client layers (in the previous example, your action controllers) while keeping code duplication to a minimum.

Of course, the academic concepts that surround the implementation of a service layer must be backed up with concrete, functional code. Therefore, in this article series Iíll be developing a user service with PHP, step by step, so that you can grasp the patternís underlying logic and see how it fits into the mainstream of modern web application development.

But before I move on, a word of caution is in order here. Keep in mind that creating the mentioned service will require us to implement a domain model, some data mappers, collections and a data access layer. This means you'll be confronted with a huge amount of code samples. Youíve been warned!  

Spotting the benefits of using a service layer: recreating a typical scenario

As I explained in the introduction, the implementation of a service layer can be really useful in the development of enterprise-level web applications, with a rich domain model entirely decoupled from the storage layer. Itís possible, though, that this concept sounds somewhat confusing to you.

Therefore, before I start out constructing the aforementioned user service, Iíd like you to take a quick look at the following code fragments. Hopefully, they will make things a bit clearer. The first one implements a basic, naive action user controller. It utilizes a simple model to perform CRUD operations in a relational database.  

This sample class looks like this:

(UserController.php)

<?php

class UserController
{
    protected $_userModel;
    protected $_view;
   
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->_userModel = ModelHelper::getModel('users');
    }
   
    /**
     * Fetch all users from the storage
     */  
    public function indexAction()
    {
        $users = $this->_userModel->fetchAll();
        $this->_view->users = $users;
        $this->_view->render();
    }
   
     /**
      * Save a new user to the storage ($data comes possibly from a POST request)
      */
     public function insertAction(array $data)
     {
         $this->_userModel->insert($data);
         // redirect to 'indexAction()' here...
     }
    
     /**
      * Update the specified user in the storage ($data comes possibly from a POST request)
      */
     public function updateAction($id, $data)
     {
         $this->_userModel->update($id, $data);
         // redirect to 'indexAction()' here...
     }
    
     /**
      * Delete the specified user from the storage
      */
     public function deleteAction($id)
     {
         $this->_userModel->delete($id);
         // redirect to 'indexAction()' here...
     }   
}

Even though I deliberately omitted the code for the error handling parts, the implementation of the above action controller is fairly easy to follow. It simply grabs an instance of a user model in the constructor (via a static service locator), which is then utilized for fetching, saving and deleting user data from the storage layer.

As I noted earlier, models that are coupled to the storage are rigid, inflexible elements that canít be ported to a different infrastructure. Of course, itís possible to use DAOs or data mappers to break up this coupling.

But what if itís necessary to do something else, like querying an external API, or processing a batch of entities in some additional form? Making the user controller directly consume the mappers, along with the external API or whatever is required, would create a mess of bloated code.    

This is exactly where the service layer comes into play. If youíre curious to see how the pattern solves such a mess, the following snippet shows the refactored version of the previous user controller. Check it out:

(UserController.php)

<?php

class UserController
{
    protected $_userService;
    protected $_view;
   
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->_userService = ServiceHelper::getService('users');
    }
   
    /**
     * Fetch all users from the storage
     */  
    public function indexAction()
    {
        $users = $this->_userService->fetchAll();
        $this->_view->users = $users;
        $this->_view->render();
    }
   
     /**
      * Save a new user to the storage ($data comes possibly from a POST request)
      */
     public function insertAction(array $data)
     {
         $this->_userService->insert($data);
         // redirect to 'indexAction()' here...
     }
    
     /**
      * Update the specified user in the storage ($data comes possibly from a POST request)
      */
     public function updateAction($id, $data)
     {
         $this->_userService->update($id, $data);
         // redirect to 'indexAction()' here...
     }
    
     /**
      * Delete the specified user from the storage
      */
     public function deleteAction($id)
     {
         $this->_userService->delete($id);
         // redirect to 'indexAction()' here...
     }   
}

Though subtle, the way that the controller has been implemented is radically different. Now, the class consumes a user service object, which is responsible for running CRUD operations. Thereís no direct interaction with a specific model, or even a clue as to how these operations are internally executed. Whatís more, the same service could be used within a different controller or client layer, and no code duplication would occur. With that said, are you beginning to see the real benefits to using a service layer? I guess you do.

And now that you have a clearer idea of how to utilize the pattern within an MVC schema, itís time to start implementing it as a standalone structure. Since my goal here is to build a user service from scratch, in the next segment Iíll be developing a basic domain layer which will be made up of a few user entities.    

To see how this brand new layer will be constructed, 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: