Login

The Dependency Injection Design Pattern in PHP 5

In this first part of a six-part series, I introduce you to the dependency injection design pattern and its use with MySQL. Specifically, I create a typical scenario where one persistent class needs the functionality of its dependency, in this case a database handler, to gain access to a MySQL table.

Without a doubt, design patterns are one of the big pillars of software development that allow you to build high-quality desktop and web applications through well-trusted solutions. A solid understanding of basic concepts such as inheritance and polymorphism, in conjunction with a respectable knowledge of the most popular design patterns, can be of great help in developing professional web-based programs.

Naturally, some design patterns are harder to master than others. A few of them, however, are remarkably simple to implement in real-world conditions, and their benefits can be really enormous.

In the particular case of PHP 5, one of easiest patterns that can be applied to improve the quality of object-oriented applications is one called Dependency Injection, even though it’s not as well known as others. As its name suggests, the Dependency Injection pattern permits you to define how a given class is going to accept its dependencies, or in other words, the way that the instances that a class needs to work will be injected into its internals.

To clarify a bit further, I’m going to cite a typical example that will be familiar to you. Say there’s a model class that needs to take in an instance of a database handler to perform queries against its associated database table. In a case like this, the database handler would obviously be a dependency of the model, and it could be passed in to the model’s environment either via the constructor, or via a setter method.

This would be a basic – yet realistic — example, where the Dependency Injection pattern is applied to promote encapsulation. Logically, this pattern can be implemented in several ways. In this series of articles I’m going to cover only some of them, including naturally the most relevant ones. In addition, I plan to touch superficially the construction of dependency injection containers, a subject that itself deserves an in-depth look.

Now, it’s time to leave the theory the drives the Dependency Injection pattern behind and start learning how to apply it in PHP 5-driven environments. Let’s get started!

As I explained in the introduction, the logic that stands behind the Dependency Injection pattern is quite easy to grasp, and despite its intimidating name, implementing it in concrete cases is a no-brainer process. However, for you to understand why this pattern is so useful, in this first tutorial of the series I’m going to build a basic MySQL-driven program using a “wrong” approach that will make you see how the application of this pattern can turn into a “good” one rapidly.

In this case, the program that I plan to develop will be composed of only two classes: the first one will be tasked with abstracting accesses to MySQL, while the second one will be charged with saving the properties of some fictional users to a specified database table. Also, it’s valid to clarify that I’ve used these example classes in other articles that I’ve written for the prestigious Developer Shed network, so you may find them familiar.

Having clarified that point, here’s the definition of the class that interacts with MySQL, not surprisingly called “MySQL” too:

As seen above, this MySQL abstraction class defines some simple methods for running queries, fetching and counting rows in a data set and so forth. So far, there’s nothing especially relevant about the way that this class works, so let me show you the signature of the class that uses the previous “MySQL” to store its properties on a predefined database table. This whole new class looks like this:

Regardless of the fact that the definition of the previous “User” class may look rather complex, in reality its functionality is remarkably simple. It uses some of the magic methods included with PHP 5 to fetch and retrieve its properties from a “users” MySQL table.

This is a simple way to create objects capable of persisting across different HTTP requests, due to the fact that their properties can be easily fetched and modified on a different web page. This process is partially illustrated by the following script:

// create a user object

$user1 = new User();

$user1->name = ‘Alejandro Gervasio';

$user1->email = ‘alejandro@domain.com';

// create another user object

$user2 = new User();

$user2->name = ‘Susan Norton';

$user2->email = ‘susan@domain.com';

In this particular example, a couple of persistent objects have been successfully spawned by the two classes that you saw before. That was really easy to achieve! But, if everything looks good at this point, what could be so wrong with the previous script? Well nothing, to be frank.

The problem is with the way that the “User” class utilizes the functionality of “MySQL” to have access to the corresponding database table, because it creates an instance of the database handler inside its constructor, which is stored as a $db property. In general this approach is considered inefficient, since “User” shouldn’t be responsible for constructing its own dependencies. Instead, it should receive those dependencies from the outside via a specific method. Period.

This incorrect definition of the “User” class puts in evidence the need to have a mechanism that passes the database handler to the class’s internals. But I’m getting ahead of myself, since issue could be fixed with the dependency injection pattern.

However, for the moment I’m going to keep the suspense going. In the following segment, I’m going to modify the definitions of the two classes shown previously, which will improve the way that they interact with each other.

Now, click on the link below and keep reading.

{mospagebreak title=Defining a basic factory method}

Frankly speaking, the best way to define a relationship between the previous “User” class and its dependency, that is the database handler, is by applying the dependency injection pattern. Nonetheless, at least for the moment I’m going to introduce a couple of modifications to these classes, so they can interact with each other in a more efficient manner.

First, the “MySQL” class will expose a brand new method, called “factory(),” which will return to client code a Singleton instance of the class.

As I said before, the brand new “factory()” method added to the above “MySQL” class is simply responsible for returning Singletons of the class in question. It has been declared static for obvious reasons, since it uses the static “$instance” property to reduce to one the number of class instances created within a given script.

As you can see, the implementation of this factory method is straightforward and easy to follow, and additionally ensures that, if the “User” class calls it inside its context, only one single instance of the database handler will be returned.

Even though this method is not a truly clean solution that solves the dependency-related issue that exists between both “User” and “MySQL” classes, it does help to implement their relationship in a more efficient way.

However, the next step that must be taken to complete this improvement process is to change the definition of the “User” class, so it can take advantage of the factory method discussed a moment ago.

This modification will be discussed in the last section of this tutorial, so to learn more about it, click on the link below and read the next few lines.

{mospagebreak title=Changing the definition of the User class}

Now that you grabbed the logic that drives the factory method defined inside the previous “MySQL” database handler, it’s time to tweak the definition of the “User” class so it can use this method to have access to its corresponding database table.

The following code sample shows the modified version of this class, which looks as follows:

There you have it. Now the constructor of the persistent “User” class internally calls the factory method provided by “MySQL” to have access to its storage table. In this case, the relationship established between these classes has been slightly improved by simply refactoring the constructor of the first one.

Of course, I’m not saying that this is an ideal situation, but with this small change it’s possible to build the pair of persistent objects that you saw previously using the same script. Take a look at it:

// create a user object

$user1 = new User();

$user1->name = ‘Alejandro Gervasio';

$user1->email = ‘alejandro@domain.com';

// create another user object

$user2 = new User();

$user2->name = ‘Mary Smith';

$user2->email = ‘mary@domain.com';

Building two persistent objects took literall six lines of code, apart from the comments, which is not too bad at all, huh? Naturally, the most interesting things are happening behind that short code sample, since the objects now share a single instance of the database handler for storing and retrieving their properties.

This is a neat example that shows in a nutshell how useful Singletons can be when it comes to optimizing the creation of objects, even though this process, in this particular case, occurs in the wrong place. But not all is lost; thanks to the functionality given by the dependency injection pattern, it’s possible to solve this issue in a really simple way.

Learning how to implement this pattern will be the topic of the next tutorial. Meanwhile, keep yourself entertained by editing the examples shown in this one.

Final thoughts

In this introductory chapter of the series, I recreated a typical scenario where one persistent class needed the functionality of its dependency, in this case a database handler, to gain access to a MySQL table. Even though all of the examples that you saw before worked decently well, in all of them the instantiation of the dependency was a responsibility of the persistent class, which isn’t good, because it’s breaks up encapsulation.

Of course, it’s possible to quickly fix this issue by taking advantage of the functionality of the dependency injection pattern. Therefore, if you wish to learn how this pattern will be applied in conjunction with the aforementioned classes, then don’t miss the next article!