While the term may make you nervous, the truth is a service is nothing but an abstraction layer which permits you to interface application logic with different client layers. These client layers can range from several front-ends, to the so-called action controllers that can be found in many MVC frameworks available today. Put in a simpler way, a service is an enterprise-level pattern, and as such, it’s both language and platform agnostic. This means that it can be implemented in most programming languages, including PHP, even though in general it’s not considered by many to be a true “enterprisey” contender. Of course, abstaining from the joys of creating a functional service layer only because there exist some biased opinions is a lame excuse. Therefore, in previous chapters of this series I started building a basic web application, whose functionality is aimed at performing CRUD operation on some user entities through a basic service. Admittedly, in its current state the application doesn’t do anything especially useful. So far, I've only implemented its domain and mapping layers. However, this is about to change. In this article I'll be adding to it a whole new layer, tasked with persisting domain objects in the underlying storage mechanism -- in this case, a MySQL database, but it could be a web service, etc. As you’ll see in a moment, this data access layer will be made up of a segregated interface and a basic MySQL abstraction class, which you’ll be able to customize at will. To sum up: are you ready to continue learning how to progressively implement a user service layer in PHP? Then let's get started. Interfacing domain objects with the persistence layer: a quick look at the previous data mappers As usual, before I start developing the persistence layer corresponding to the sample application mentioned in the introduction, I’d like to spend a few moments reviewing the topics covered in the preceding installment of the series. In that tutorial I implemented the application’s mapping layer, which was comprised of a simple segregated interface and a couple of data mappers. Well, here’s the definition of the pertinent interface, which makes extending the mapping layer a breeze: (MyApplication/Mapper/DataMapperInterface.php) <?php namespace MyApplicationMapper; interface DataMapperInterface public function findAll(); public function search($criteria); public function insert($entity); public function update($entity); public function delete($entity); The contract defined by the above interface speaks for itself. So let's move on and take a look at the following abstract class, which encapsulates the functionality required to map generic entities: (MyApplication/Mapper/AbstractDataMapper.php) <?php namespace MyApplicationMapper; abstract class AbstractDataMapper implements DataMapperInterface /** /** /** /** /** /** /** /** /** /** /** /**
(MyApplication/Mapper/DataMapperException.php) <?php namespace MyApplicationMapper; class DataMapperException extends Exception{} From the above code fragment, it’s clear to see that all the “AbstractMapper” class does is fetch, save and remove entities from the storage layer. While this is all well and good, my purpose here is to implement a functional user service. Therefore, it’s mandatory to spawn a subclass from the abstract parent that works exclusively with user entities. The one shown below does exactly that: (MyApplication/Mapper/UserMapper.php) <?php namespace MyApplicationMapper; class UserMapper extends AbstractDataMapper That was much easier to accomplish than one might think, wasn’t it? In a few easy steps, I managed to implement an extendable mapping layer, which moves data between the domain model and the underlying database. However, there’s a couple of things that need to be done to persist the model in the storage mechanism. First, we need to build the database adapter injected in the mappers’ constructor; and second, we need to develop the other dependency, namely a collection handling class. But first things first, right? Thus, in the following section I’ll be defining the contract implemented by the former, which logically will be represented by an interface. To learn more about this process, click on the link below and keep reading.
blog comments powered by Disqus |
|
|
|
|
|
|
|