Home arrow PHP arrow Page 2 - Injecting Objects by Constructor with the Dependency Injection Pattern

Review: inefficiently handling class dependencies - PHP

While not being as widely known as other design patterns such as Factory, Singleton or Active Record, the Dependency Injection pattern provides both programmers and web developers with a well-structured solution that allows them to solve issues that arise when an object needs the functionality of another one (hence the dependency) to work as expected. This is the second part of a six-part series that shows you how to apply this pattern.

TABLE OF CONTENTS:
  1. Injecting Objects by Constructor with the Dependency Injection Pattern
  2. Review: inefficiently handling class dependencies
  3. Applying the Inversion of Control principle
  4. The dependency injection pattern in action
By: Alejandro Gervasio
Rating: starstarstarstarstar / 1
October 13, 2009

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement
 

As I said at the beginning of this article, the sample MySQL-driven program developed in the preceding tutorial showed pretty clearly how to use the wrong approach to the dependency of a persistent class. In this particular example, the dependency in question was a basic database handler, which was created inside the constructor of the persistent class. This is definitely a very bad thing; this approach doesn’t stick to the schema imposed by the Inversion of Control principle referenced in the introduction.

Therefore, it’s important to spend a few minutes recalling how this sample application was built originally, so you can discover for yourself why the classes that compose this program establish a incorrect relationship with each other.

First off, here’s the definition of the database handler. Pay close attention to it:

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

}

}

Obviously, the set of tasks performed by the above “MySQL” class are easy to follow. It allows you to run queries against a selected database, retrieve and count rows in a result set, and find insertion IDs. So far, there’s nothing special about the way that this abstraction class functions, right?

Moving on, below there’s the definition of the persistent class, which uses the previous database handler for saving and fetching its properties from a “users” MySQL table. Here’s how this class looks:

class User

{

private $data = array();

private $id = NULL;

private $db = NULL;

 

// constructor

public function __construct($id = NULL)

{

$this->db = MySQL::factory('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");

 }

}

}

As seen above, there are no major complaints about the logic implemented by this class. It simply uses some magic methods provided by PHP 5 for making its own properties persist across multiple HTTP requests. The following script demonstrates how to accomplish this process in a friendly way:

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

Regardless of the fact that the “User” class does a decent job when it comes to building some persistent objects, it exposes a serious drawback. Yes, you guessed right! Its constructor is responsible for creating an instance of its dependency, that is a MySQL object, to have access to the storage table.

This is a poor approach where an object controls its context, when in reality the opposite should happen. So, how can this issue be addressed? Well, here’s where the dependency injection pattern comes in, since it’s possible to implement a version of it called “injection by constructor,” which allows you to apply the Inversion of Control principle very easily.

Want to see how this principle will be put to work with the two classes shown before? Then read the following segment. 



 
 
>>> 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: