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.
blog comments powered by Disqus |
|
|
|
|
|
|
|