Login

Roll Your Own Repository in PHP: a Final Example

Welcome to the conclusion to an eight-part article series on constructing your own repository from scratch in PHP. In this article, we’ll go through an example that shows you how the repository we completed in the previous article actually performs. You’ll see all of the classes we created in action.

Constructing a repository in PHP can be an enriching and fun experience. The process not only demands that you create the class (or classes) that implements this additional abstraction layer, but requires you to build other structures closely related to Domain-Driven Design (DDD), such as entities, collections and mappers — not to mention the typical persistence layer, which in most use cases rests on a relational database.

To demonstrate that the my previous statement is not simply a biased opinion, in earlier parts of this series I went through the development of a sample web application, whose main task was to handle collections of user entities via a simple repository. This user repository defined a few straightforward methods, which permitted the concentration of query code in one single point and the retrieval of the corresponding collections of domain objects according to a certain number of basic conditions.

While speaking of a repository’s benefits can be pretty useful, at least from a theoretical point of view, the best way to understand its driving logic and illustrate its actual functionality is by example. With that in mind, in this final installment of the series I’m going to set up a concluding example. It will put all of the sample classes developed so far to work together. In doing so, you’ll realize how easy it is to manipulate collections of entities through this basic repository class.

Well, the spotlights are on, the audience is already clapping and the curtain is starting to rise, so let’s get rid of the preliminaries and start writing some functional code. It’s show time!

Summary: all of the sample classes created so far

Before I start creating the hands-on example mentioned in the introduction, it’d be helpful to list all of the sample classes developed so far. This way, you can have them available in one place for further analysis or editing. Get ready to be confronted with long chunks of code. You’ve been warned!

First, here is the autoloader, which lazy-loads source classes using the SPL stack:

Now that you’ve recalled how the above autoloader works, it’s time to show the classes that make up the domain layer of this sample application. As you’ll remember, these are tasked with modeling generic and user entities respectively. The definition of the first of these classes is as follows:

/** * Get the values assigned to the fields of the entity */ public function toArray() { return $this->_values; } }

(EntityException.php)

<?php

class EntityException extends Exception {}

Well, considering that the previous abstract parent already encapsulates most of the functionality required to create generic entities, deriving a subclass that models users specifically is this simple:

Done. Having included the pair of classes that compose the domain layer, the next step is to show the ones responsible for implementing the persistence layer. In fact, this new layer is integrated by an interface and a MySQL abstraction class, and their corresponding definitions are included below:

/** * Close automatically the database connection when the instance of the class is destroyed */ public function __destruct() { $this->disconnect(); } }

(MySQLAdapterException.php)

<?php

class MySQLAdapterException extends Exception{}

Still with me? Great. Now, take a deep breath and look at the following code snippet, which includes the interface and the pair of mapper classes that make up the mapping layer of this sample application. Check them out:

Even though a lot of code has been covered so far, don’t relax yet; there’s still one thing left to do. But what is it? Well, for obvious reasons it’s necessary to show the user repository and the factory that takes care of instantiating all of its dependencies. Below you’ll find the definitions of these classes:

Mission accomplished, at least for now. Having made a quick summary of all the classes and interfaces that comprise this example application, it’s time to develop the example mentioned at the beginning. It will show how to put those classes to work side by side, and how to use the previous user repository in a truly useful fashion.

This new example will be created in the upcoming segment. Therefore, to learn more about it, click on the link below and keep reading.

{mospagebreak title=The user repository in action}

To demonstrate how to take advantage of the functionality offered by the user repository that you saw in the previous section, I’m going to use a simple MySQL table, which has been previously populated with data corresponding to a few trivial users. The sample table looks like this:

So far, nothing unexpected, right? As you can see, the table contains four columns that store the ID (an autonumeric, unsigned primary key) of each user, as well as their first and last names and their email addresses. Now, if I wanted to retrieve some of the stored users by specifying some basic conditions, the process would be this simple:

As the above code fragment shows, putting the user repository into action and fetching different collections of user entities that match a specific condition is amazingly easy! In this case, the criteria used to retrieve the previous users are very simple. It’s feasible, however, to create a repository capable of working with more complex conditions than simple first and last names. The possibilities are endless.

Naturally, the repository can be used to insert new users into the above table, and even to remove existing users through the same API. Therefore, in the last section I’m going to build a final example that will show how to perform these additional operations.

Now, jump ahead and keep reading.

One step further: adding and deleting user entities

As I noted in the section that you just read, the user repository makes it really easy to add new users to the persistence layer, and to delete existing ones. If you want to see how these operations can be executed in a few steps, simply pay attention to the code snippet below, which will hopefully be self-explanatory:

There you have it. Thanks to the functionality provided by the repository’s “insert()” and “delete()” methods, inserting and deleting users from the persistence layer is indeed a straightforward process that can be tackled in a snap.

Needless to say, there’s plenty of room to experiment here, and extend the current capability of the repository in such a way that it can perform more complex queries. Considering this scenario, I encourage you to tweak this class in many clever ways and add your own custom methods to it. In doing so, you’ll acquire a better background in mastering one of the big pillars of Domain-Driven Design.

Final thoughts

Finally, we’ve come to the end of this series. From a strong hands-on standpoint, I attempted to demonstrated in a step-by-step fashion how to build a repository from scratch. Hopefully, during the development process, you learned not only how to create such an abstraction layer, but how to apply some concepts inherent to modern application design, such as building models that are loosely coupled to the persistence mechanism.

If you feel that the implementation of Active Record, widely promulgated by Rails and even other well-known PHP frameworks out there, doesn’t suit your needs any longer and want to create programs that scale up well in different conditions and with multiple infrastructures, then this series might help you start migrating to more flexible solutions.