Applying the Dependency Injection Pattern and Factory Methods in PHP 5

Welcome to the final part of a series on implementing factory methods in PHP 5. Composed of six approachable tutorials, this series uses numerous hands-on examples to teach you how to define specific methods within your own PHP programs. These methods return to client code instances from their originating classes, and from other classes as well.

And now that you know what to expect from this series of articles, it’s time to quickly review the topics that were covered in the last tutorial. In that part of the series I built a simple application in PHP 5 composed of two classes for its building blocks. The first was merely a basic MySQL abstraction class, while the second was a storage class that took advantage of the functionality given by the first to persist across different HTTP requests.

Of course, the interaction established between these two classes was achieved via a factory method that allowed sharing of the same database handler between multiple persistent objects. The process demonstrated how useful this type of method can be in such a situation.

However, I’d like to finish this series on building factory methods by explaining how the database-driven application developed in the preceding article can be optimized even more with a few little tweaks. In this case, thanks to a simple implementation of the Dependency Injection pattern, it’ll be possible to completely avoid the utilization of the factory method.

Do you want to learn how this will be done? Then start reading now!

{mospagebreak title=Review: the classes so far}

Before I start explaining how to apply the Dependency Injection pattern to the example application developed in the previous installment, let’s review how the classes that composed this small program were defined originally.

So, here is the signature corresponding to the class that abstracts accesses 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);

}

}

At this point, the definition of the above MySQL abstraction class should be pretty familiar to you, so I’m not going to waste your time explaining how it works. Instead, let me show you the signature of the other sample class, which takes advantage of the functionality given by the previous one to persist through multiple HTTP requests.

Here’s how this persistent class looks:

class User

{

private $data = array();

private $id = NULL;

private $db = NULL;

 

// constructor

public function __construct(MySQL $db, $id = NULL)

{

$this->db = $db;

if ($id !== NULL)

{

$this->id = $id;

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

$this->data = $this->db->fetch();

}

}

 

// set undeclared property

public function __set($property, $value)

{

if ($property !== ‘name’ and $property !== ‘email’)

{

return;

}

$this->data[$property] = $value;

}

 

// get undeclared property

public function __get($property)

{

if (isset($this->data[$property]) === TRUE)

{

return $this->data[$property];

}

}

 

// save object to session variable

public function __destruct()

{

if ($this->id === NULL)

{

$this->db->query("INSERT INTO users (id, name, email) VALUES (NULL, ‘$this->name’, ‘$this->email’)");

}

else

{

$this->db->query("UPDATE users SET name = ‘$this->name’, email = ‘$this->email’ WHERE id = $this->id");

}

}

}

Definitively, what I said about the previous MySQL abstraction class is also valid for the one above, since at this point you’ll be familiar with the logic driving this persistent class. It’s fair to note an important detail, though, about the way that this class uses the functionality of “MySQL.” As you can see, an instance of this database handler is directly passed to the constructor of the class, an approach commonly known in software development as “dependency injection by constructor.” Expressed in other words, it’s a simple implementation of the Dependency Injection pattern.

Well, having roughly outlined the logic that drives the previous “MySQL” and “User” classes, below I coded a couple of scripts that show them in action.

The first of these scripts uses the factory method of the database handler in a rather inefficient manner to create two persistent objects:

// create first user object

$user1 = new User(MySQL::factory(‘host’, ‘user’, ‘password’, ‘database’));

$user1->name = ‘Susan Norton’;

$user1->email = ‘susan@domain.com’;

 

// create second user object

$user2 = new User(MySQL::factory(‘host’, ‘user’, ‘password’, ‘database’));

$user2->name = ‘Mary Smith’;

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

That was easy to grasp, right? Now, take a look at the following fragment, which utilizes the factory method of the database handler in a slightly more clever way:

// create instance of MySQL class via the factory method

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

// create first user object

$user1 = new User($db);

$user1->name = ‘Susan Norton’;

$user1->email = ‘susan@domain.com’;

 

// create second user object

$user2 = new User($db);

$user2->name = ‘Mary Smith’;

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

Without a doubt, understanding how these two scripts work should be a straightforward process for you. All they do is show how useful a factory method can be for efficiently controlling the creation of objects.

However, this example is pretty particular, since the application of the Dependency Injection pattern permits you to easily get rid of the previous factory method. Don’t believe that this may be that easy? Well, to prove it, in the following section the method will be removed from the MySQL abstraction class, without producing any impact in the creation of persistent objects.

To see how this will be done, read the next segment.

{mospagebreak title=Removing the factory method from the MySQL class}

Remember what I said in the previous section? Due to the proper application of the Dependency Injection pattern, it’s possible to remove the factory method defined inside the earlier MySQL abstraction class, since in this case, it will be pretty useless for creating persistent objects.

However, the best approach to understanding why removing this factory method won’t cause any impact in the way that those persistent objects are spawned is by examining some functional code. So, below is the modified definition of the MySQL handling class, this time without exposing its factory method. Here it is:

class MySQL

{

private $result = NULL;

private $link = NULL;

 

// 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);

}

}

There you have it. As I explained a moment ago, now the “MySQL” class lacks its factory method, but its functionality remains practically the same. So, what’s the point in removing it, after all? Good question, indeed.

In reality there’s no an actual need to get rid of this method at all. Nonetheless, I wanted to do this so you could see that even without its presence, it’s feasible to build the same persistent objects that you saw before with only minor hassles.

But guess what? Showing you the example will be the perfect conclusion for this last part of the series. So click on the link below and read the next few lines. We’re almost finished!

{mospagebreak title=Creating persistent objects without a factory method}

As I expressed before, I’d like to conclude this tutorial by showing you how to build a couple of persistent objects (or more, if you want to) even though the factory method of the MySQL abstraction class has been removed. 

To prove that, here’s another script that shows how to perform this task, assuming that the definitions of the corresponding sample classes have been previously included. Take a look at it:  

// create instance of MySQL class and inject it into the user class constructor

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

// create first user object

$user1 = new User($db);

$user1->name = ‘Susan Norton’;

$user1->email = ‘susan@domain.com’;

 

// create second user object

$user2 = new User($db);

$user2->name = ‘Mary Smith’;

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

As shown above, an instance of the MySQL class has been injected directly into the constructor of each persistent object. Naturally, the most important thing to stress here is that this was achieved without calling any factory method. Pretty neat, huh?

This example demonstrates how an adequate implementation of the Dependency Injection pattern allows you to pass an instance of a given class to other objects without using factories. Of course, this is valid only when the dependency is injected via a constructor or setter method, but if a dependency container is required, then coding a factory method that returns Singletons surely will be a good option.

Final thoughts

It’s hard to believe, but we’ve come to the end of this series. Hopefully the experience has been educational for you, since you learned the basics of defining and implementing factory methods in PHP 5.

As you saw from the examples developed in the subsequent tutorials, a proper use of the Factory and Singleton patterns can be a powerful combination that allows you to write more robust and efficient applications. Think of them the next time that you need to build a truly killer PHP program.

See you in the upcoming PHP development tutorial!

Google+ Comments

Google+ Comments