Home arrow PHP arrow Page 2 - The Dependency Injection Design Pattern in PHP 5

A basic MySQL-driven application with the dependency injection pattern - PHP

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.

TABLE OF CONTENTS:
  1. The Dependency Injection Design Pattern in PHP 5
  2. A basic MySQL-driven application with the dependency injection pattern
  3. Defining a basic factory method
  4. Changing the definition of the User class
By: Alejandro Gervasio
Rating: starstarstarstarstar / 5
October 08, 2009

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

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:

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

}

}

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:

class User

{

private $data = array();

private $id = NULL;

private $db = NULL;

 

// constructor

public function __construct($id = NULL)

{

$this->db = new MySQL('host', 'user', 'password', 'database');

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

}

}

}

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.



 
 
>>> More PHP Articles          >>> More By Alejandro Gervasio
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PHP ARTICLES

- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: