Certainly, a good epilogue for this article will be defining a factory method within the MySQL abstraction class that returns to client code only singletons and additionally, can be easily chained to other methods. Below I listed the full source code corresponding to the "MySQL" class, this time including the factory method. Please look at it: class MySQL { private $host = ''; private $user = ''; private $password = ''; private $database = ''; private $query = ''; private $result; private $link = NULL; private static $instance = NULL;
// factory method returns a singleton of MYSQL class public static function factory($host, $user, $password, $database) { if (self::$instance === NULL) { self::$instance = new MySQL($host, $user, $password, $database); } return self::$instance; }
// constructor public function __construct($host, $user, $password, $database) { if (FALSE === ($this->link = mysqli_connect($host, $user, $password, $database))) { throw new Exception('Error : ' . mysqli_connect_error()); } }
// create the SELECT part of the query // chainable public function select($table, $fields = '*') { $this->query = ' SELECT ' . $fields . ' FROM ' . $table; return $this; }
// create the WHERE part of the query // chainable public function where($where) { $this->query .= ' WHERE ' . $where; return $this; }
// create the ORDER BY part of the query // chainable public function orderby($order = 'id ASC') { $this->query .= ' ORDER BY ' . $order; return $this; }
// create the LIKE part of the query // chainable public function like($match = '', $wildcard = 'both') { if ($match != '') { if ($wildcard === 'both') { $this->query .= ' LIKE ' . ''%' . $match . '%''; } else if ($wildcard === 'pre') { $this->query .= ' LIKE ' . ''%' . $match . '''; } else if ($wildcard === 'post') { $this->query .= ' LIKE ' . ''' . $match . '%''; } } return $this; }
// fetch result set public function fetch() { if (FALSE === ($this->result = mysqli_query($this->link, $this->query))) { throw new Exception('Error performing query ' . $this->query); } return $this->result; }
// implement the destructor to free result set and close the database connection function __destruct() { mysqli_free_result($this->result); mysqli_close($this->link); } } If you're familiar with implementing the Factory pattern in PHP, you'll find the previous "factory()" method pretty easy to follow. All it does is create a Singleton of the "MySQL" class; as mentioned, it can also be chained to other methods. The following example shows how to retrieve records from the same "properties" MySQL table used in previous cases, by chaining the factory method to others: try { // fetch result set by chaining methods of MySQL class $result = MySQL::factory('host', 'user', 'password', 'database')->select('properties')->where("title LIKE 'c%'")->orderby('title DESC')->fetch(); while ($row = mysqli_fetch_object($result)){ echo $row->title . $row->description . '<br />'; } } catch(Exception $e) { echo $e->getMessage(); exit(); } Hopefully, this simple example gave you an accurate idea of how to take advantage of method chaining in PHP 5 for abstracting MySQL-related tasks through a highly compact API. As always, feel free to edit all of the code samples shown in this tutorial, so you can arm yourself with a better understanding of how to work with this useful programming methodology. Final thoughts That's all for the moment. In this sixth chapter of the series, I demonstrated how simple it is to add a couple of chainable methods within the previous "MySQL" class for dynamically creating LIKE clauses and for returning Singletons as well. Hopefully, the development of this class will help you understand more clearly how to use method chaining for building a real-world application. Speaking of developing real-world applications, in the next part I'm going to explain how to use chainable methods for creating a custom library for CodeIgniter, the popular PHP framework. Don't miss the upcoming article!
blog comments powered by Disqus |
|
|
|
|
|
|
|