PHP Page 2 - Injecting Objects Using Setter Methods with the Dependency Injection Design Pattern |
Before I explain how to apply the dependency injection pattern by using a setter method, it’d be helpful to review the sample application developed in the preceding article. It implemented another version of the pattern by utilizing a constructor. Having said that, here’s the complete definition of the MySQL abstraction class, whose instance needs to be injected straight into the internals of a couple of persistent objects. Check it out: 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); } } The clock is ticking, so I’m not going to spend a long time explaining the full details for how this MySQL-handling class works, since you already know this. Instead, let me go one step further and show you the signature of the persistent class that uses the functionality of the previous database handler to do its business Here it is: 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"); } } } Definitely, the most relevant method of the above “User” class to look at is its constructor. It accepts an instance of the “MySQL” class to have access to its storage “users” table. This method itself shows clearly how simple and efficient it is to use dependency injection through a constructor; in this case, the process is easy to achieve thanks to the type hinting feature included with PHP 5. Finally, here’s a short script that illustrates how the pattern is used to build two persistent objects: // example of dependency injection via the constructor // create instance of MySQL class $db = new MySQL('host', 'user', 'password', 'database'); // create first user object $user1 = new User($db); $user1->name = 'Alejandro Gervasio'; $user1->email = 'alejandro@domain.com';
// create second user object $user2 = new User($db); $user2->name = 'Mary Smith'; $user2->email = 'mary@domain.com'; This isn’t rocket science, but it works like a charm. As you can see, due to a proper implementation of the dependency injection pattern, the persistent objects just created are no longer responsible for spawning an instance of the database handler. They suddenly became passive entities that expect to receive their dependency or dependencies from their context. Isn’t that good and effective? You bet it is. Well, having exemplified the use of dependency injection by means of a constructor, it’s time to move forward and continue exploring other approaches that can be used to produce the same result. Therefore, according to the concepts deployed in the introduction, in the next section I’m going to discuss how to implement this pattern using a simple setter method. To learn more about this process, please click on the link that appears below and keep reading.
blog comments powered by Disqus |
|
|
|
|
|
|
|