The Role of Interfaces in Applying the Dependency Injection Design Pattern

Welcome to the sixth part of a series covering the dependency injection pattern. In this part, I build a PHP 5-based application that can work seamlessly with MySQL and SQLite. It will feature a simple interface and a MySQL driver.

When it comes to defining the way that a PHP class is going to accept the instances that it will need to work within a given application, there’s a simple and powerful approach that allows you to achieve this goal in a truly effective way, without suffering premature hair loss.

Does this phrase ring any bells for you? Enter the dependency injection pattern, a proven programming methodology that will let you specify how one or more classes will take from their working context the dependencies (hence the pattern’s name) that they require to function properly.

In general, there are two approaches that can be used for implementing dependency injection successfully. It’s quite probable that both of them will be equally familiar to you. The first one relies on the dependency being injected via the constructor of the receiver class, while the second one accomplishes the same thing using a setter method instead.

Naturally, as with any other design pattern, the theoretical concepts that stand behind the dependency injection pattern must be backed up with a substantial amount of functional code. And that’s exactly what I attempted to do in the previous articles of this series. In those tutorials I explained how to implement the two approaches, first by using persistent objects and second, a model class, which hopefully showed that combining the functionality of the Model-View-Controller pattern and dependency injection within the same PHP 5-driven application is actually a no-brainer process.

However, there are many other scenarios where dependency injection can be used for optimizing the relationship between classes. One of the most common is when building polymorphs, or in other words, objects that are of the same type, but behave differently under certain conditions.

Very frequently, polymorphism is used in PHP 5 to develop web sites, applications, frameworks and so forth that transparently support the use of multiple database drivers. But, can this programming pillar be combined with dependency injection in a successful way? Fortunately, the answer is yes! And to prove this, in the upcoming sections I’m going to start building a basic web program that will be capable of interacting seamlessly with MySQL and SQLite, thanks to the clever use of dependency injection and interfaces altogether.

Now, it’s time to begin creating this sample database-driven application with PHP 5. Let’s get going!

{mospagebreak title=Review: implementing dependency injection via a setter method}

Before I start building the database-driven application mentioned in the introduction, which will combine the functionality of interfaces and dependency injection to support the use of MySQL and SQLite drivers, first I will review the example developed in the previous installment of the series. In that article, I went through the development of a basic MVC-based program that used dependency injection via a setter method to perform CRUD operations against a predefined MySQL table.

Given that, first here is the definition of the class that abstracts the access to MySQL:

class MySQL

{

private $result = NULL;

private $link = NULL;

private static $instance = NULL;

 

// returns a singleton instance of MySQL class (chainable)

public static function factory($host, $user, $password, $database)

{

if (self::$instance === NULL)

{

self::$instance = new MySQL($host, $user, $password, $database);

}

return self::$instance;

}

// connect to MySQL

public function __construct($host, $user, $password, $database)

{

if (FALSE === ($this->link = mysqli_connect($host, $user, $password, $database)))

{

throw new Exception(‘Error : ‘ . mysqli_connect_error());

}

}

 

// perform query

public function query($query)

{

if (is_string($query) AND empty($query) === FALSE)

{

if (FALSE === ($this->result = mysqli_query($this->link, $query)))

{

throw new Exception(‘Error performing query ‘ . $query . ‘ Error message :’ .mysqli_error($this->link));

}

}

}

 

// fetch row from result set

public function fetch()

{

if (FALSE === ($row = mysqli_fetch_assoc($this->result)))

{

mysqli_free_result($this->result);

return FALSE;

}

return $row;

}

 

// get insertion ID

public function getInsertID()

{

return mysqli_insert_id($this->link);

}

// count rows in result set

public function countRows()

{

if ($this->result !== NULL)

{

return mysqli_num_rows($this->result);

}

}

// implement destructor to close the database connection

function __destruct()

{

mysqli_close($this->link);

}

}

Without a doubt, at this point the definition of the previous “MySQL” class should be very familiar to you, so I’m not going to waste your time (and mine) discussing how it works. Instead, it’s time to show the signature of the model class that comprises this example program, which takes advantage of dependency injection via a setter method to query a “users” MySQL table in a quite abstract manner.

Here’s how this model class was built previously:

class UserModel

{

private $db = NULL;

 

// constructor (not implemented)

public function __construct(){}

 

// setter for database handler

public function setDatabaseHandler(MySQL $db)

{

$this->db = $db;

}

 

 

// get all users

public function getAll()

{

return $this->db->query("SELECT * FROM users");

}

 

// get a single user

public function get($id = 1)

{

return $this->db->query("SELECT * FROM users WHERE id = ‘$id’");

}

 

// create/update user

public function save($data, $id = NULL)

{

if (is_array($data) && !empty($data))

{

if ($id === NULL)

{

$data = array_values($data);

$fields = ”’ . implode("’,’", $data) . ”';

$this->db->query("INSERT INTO users (id, fname, lname, email) VALUES (NULL, $fields)");

}

else

{

$fields = ”;

foreach ($data as $field => $value)

{

$fields .= $field . ‘=” . $value . ”,';

}

$fields = substr($fields, 0, -1);

$this->db->query("UPDATE users SET $fields WHERE id=$id");

}

}

}

 

// delete user

public function delete($id = NULL)

{

if ($id !== NULL)

{

$this->db->query("DELETE FROM users WHERE id=$id");

}

}

}

As I explained before, in this particular case the above model class simply takes an instance of “MySQL” by means of its “setDatabaseHandler()” method, which permits it to execute CRUD operations against a MySQL table.

And speaking of running CRUD operations, below is a script that demonstrates how to do that in a few simple steps:

// create new instance of MySQL class

$db = new MySQL(‘host’, ‘user’, ‘password’, ‘database’);

$userModel = new UserModel();

// inject MySQL instance in the model via its setter method

$userModel->setDatabaseHandler($db);

// add new user

$userModel->save(array(‘fname’ => ‘Alejandro’, ‘lname’ => ‘Gervasio’, ‘email’ => ‘alejandro@domain.com’));

// update existing user

$userModel->save(array(‘fname’ => ‘Mary’, ‘lname’ => ‘Wilson’, ‘email’ => ‘mary@domain.com’), 1);

// delete existing user

$userModel->delete(1);

That was really easy to achieve, wasn’t it? As this script shows, it’s amazingly simple to insert, update and delete user-related records, thanks to the intuitive API provided by the model class. However, the nitty-gritty of this example is unquestionably the clever use of dependency injection by means of the “setDatabaseHandler()” method, which expects to passively  receive an instance of “MySQL” from the outside.

Now that you hopefully recalled how the previous PHP 5-driven application functions, it’s time to continue exploring other scenarios where the dependency injection pattern can be applied successfully. So, in consonance with the concepts deployed in the introduction, in the next segment I’m going to start building a brand new program. It will be able to work equally well with MySQL and SQLite, thanks to the combined use of dependency injection and interfaces.

Want to see how the skeleton of this program will be sketched out? Then click on the link below and keep reading.

{mospagebreak title=Defining a database access interface}

As I expressed at the beginning of this article, one typical situation where dependency injection is used at its most efficient is when it comes to building applications that need to work with multiple database systems.

To demonstrate this concept as clearly as possible, I’m going to start developing a PHP 5 program that will be capable of using both MySQL and SQLite to perform CRUD operations against a selected database. So, the first step that must be taken is defining a simple interface that will declare at an abstract level the methods that will be implemented by the respective database drivers.

Now that I have explained that, please examine the definition of the following interface, which not surprisingly is called “DbHandler.” Here it is:

// define ‘DbHandler’ interface

 

interface DbHandler

{

public function __construct($host, $user, $password, $database);

 

public function query($query);

 

public function fetch();

 

public function count();

}

Were you expecting to see longer code? Sorry to disappoint you if you were, but I’d like to keep the structure of the above “DbHandler” interface pretty simple and uncluttered (after all, that’s the idea behind defining an interface, right?). As you can see, it declares four public methods that will come in handy for connecting to the specified database and running queries, as well as for fetching and counting rows in result sets.

So far, there’s nothing unusual about the way that this interface has been defined. So, it’s time to start out building the first database driver class. This clase will be responsible for implementing the methods declared by the interface to work with MySQL.

The definition of this class will be shown in the last section of this tutorial. Therefore, go ahead and read that segment.

{mospagebreak title=Building a MySQL database driver}

Having already defined an interface that declares some generic methods not tied to a specified database system, I’m going to build the driver class that will interact specifically with MySQL.

Of course, this class will give a concrete implementation to all of the methods defined by the interface, and its signature is as follows:

 

class MySQL implements DbHandler

{

private $result = NULL;

private $link = NULL;

 

public function __construct($host, $user, $password, $database)

{

if (FALSE === ($this->link = mysqli_connect($host, $user, $password, $database)))

{

throw new Exception(‘Error: ‘ . mysqli_connect_error());

}

}

 

// perform query

public function query($query)

{

if (is_string($query) AND !empty($query))

{

if (FALSE === ($this->result = mysqli_query($this->link, $query)))

{

throw new Exception(‘Error performing query ‘ . $query . ‘ Error message : ‘ .mysqli_error($this->link));

}

}

}

 

// fetch row from result set

public function fetch()

{

if (FALSE === ($row = mysqli_fetch_assoc($this->result)))

{

mysqli_free_result($this->result);

return FALSE;

}

return $row;

}

// count rows in result set

public function count()

{

if ($this->result !== NULL)

{

if (0 === ($rows = mysqli_num_rows($this->result)))

{

return ‘No rows in result set';

}

return $rows;

}

}

}

As seen above, this new “MySQL” class is nothing but a shortened version of the example shown in previous chapters of the series, except for one important difference. In this case, this class is an implementer of the “DbHandler” interface.

What does this mean in practical terms? Well, in other words, it can be said that any instance created from the “MySQL” class will eventually be a polymorph object. But, actually I’m getting ahead of myself, since this concept will be much better understood when I define the driver for SQLite, over the course of the upcoming article.

In the meantime, it’s time to recapitulate the things that have been accomplished so far. First, I defined an interface whose methods were implemented by a MySQL database driver. That is good, but it’s possible that you’re wondering where dependency injection comes into play, right?

However, as you may know, a long way always takes many small steps, so bear with me for the moment. In the next tutorial I’m going to take the next step by defining the driver class that will be responsible for interacting with SQLite, which not surprisingly will be another implementer of the “DbHandler” interface.

Final thoughts

That’s all for the moment. In this sixth episode of the series, I began building a PHP 5-based application that will have the ability to work seamlessly with MySQL and SQLite. In its current state, this application is composed only of a simple interface and a MySQL driver; therefore, it’s necessary to build the class that will interact specifically with SQLite.

That’s exactly what you’ll learn to do in the next article, so you don’t have any excuses to miss it!

[gp-comments width="770" linklove="off" ]

chat