In case you haven’t had the chance to read the initial installment of this series, where I showed how to build a MySQL abstraction layer that implements the Iterator Interface, below I reintroduced the definitions of the classes composing this layer. Here's the wrapper class that, among other things, is tasked with connecting to MySQL and performing specified SQL queries: class MySQLiWrapper extends MySQLi {
private static $_instance = NULL;
// return Singleton instance of MySQL class public static function getInstance(array $config = array()) { if (self::$_instance === NULL) { self::$_instance = new self($config); } return self::$_instance; }
// private constructor private function __construct(array $config) { if (count($config) < 4) { throw new Exception('Invalid number of connection parameters'); } list($host, $user, $password, $database) = $config; parent::__construct($host, $user, $password, $database); if ($this->connect_error) { throw new Exception('Error connecting to MySQL : ' . $this->connect_errno . ' ' . $this->connect_error); } }
// prevent cloning class instance private function __clone(){}
// perform query public function runQuery($query) { if (is_string($query) AND !empty($query)) { if ((!$this->real_query($query))) { throw new Exception('Error performing query ' . $query . ' - Error message : ' . $this->error); } return new MySQLi_ResultWrapper($this); } }
// get insertion ID public function getInsertID() { return $this->insert_id; }
// close database connection public function __destruct() { $this->close(); } } Without digging too much into its internals, the above class is nothing but a simple wrapper for the native “MySQLi” class that comes with PHP 5. In this particular case, its “runQuery()” method returns an instance of another class called “MySQLi_ResultWrapper,” whose source code is listed below: class MySQLi_ResultWrapper extends MySQLi_Result implements Iterator { private $_pointer = 0;
// fetch row as an object public function fetchObject() { if (!$row = $this->fetch_object()) { return NULL; } return $row; }
// fetch row as an associative array public function fetchAssocArray() { if (!$row = $this->fetch_assoc()) { return NULL; } return $row; }
// fetch row as an enumerated array public function fetchNumArray() { if (!$row = $this->fetch_row()) { return NULL; } return $row; }
// fetch all rows public function fetchAll($type = MYSQLI_ASSOC) { if ($type !== MYSQLI_ASSOC AND $type !== MYSQLI_NUM AND $type !== MYSQLI_BOTH) { $type = MYSQLI_ASSOC; } if (!$rows = $this->fetch_all($type)) { return NULL; } return $rows; }
// get definition information on fields public function fetchFieldsInfo() { if (!$fieldsInfo = $this->fetch_fields()) { throw new Exception('No information available for table fields.'); } return $fieldsInfo; }
// get definition information on next field public function fetchFieldInfo() { if (!$fieldInfo = $this->fetch_field()) { throw new Exception('No information available for current table field.'); } return $fieldInfo; }
// move pointer in result set to specified offset public function movePointer($offset) { $offset = abs((int)$offset); $limit = $this->num_rows - 1; if ($limit <= 0 OR $offset > $limit) { return NULL; } unset($limit); return $this->data_seek($offset); }
// reset result set pointer (implementation required by 'rewind()' method in Iterator interface) public function rewind() { $this->_pointer = 0; $this->movePointer($this->_pointer); return $this; }
// get current row set in result set (implementation required by 'current()' method in Iterator interface) public function current() { if (!$this->valid()) { throw new Exception('Unable to retrieve current row.'); } $this->movePointer($this->_pointer); return $this->fetchObject(); }
// free up result set public function __destruct() { $this->close(); } } As you can see, here’s where the Iterator SPL interface comes into play. The previous “MySQLi_ResultWrapper” class is an implementer of it, even though, for the time being, this process is achieved only partially. But why am I saying this? Well, in case you don’t know, the interface declares five methods called “rewind(),” “current(),” “key(),” “valid()” and “next()” respectively. However, at this moment the class only implements two of these, that is “rewind()” and “valid(),” which isn’t very useful. If you give the class a try, you’ll get a fatal error from the PHP engine. For obvious reasons, it’s necessary to implement the remaining interface methods, thus giving the class the ability to traverse data sets using an array-like notation. In the section to come I’m going to complete the implementation process. Now, click on the link below and keep reading.
blog comments powered by Disqus |
|
|
|
|
|
|
|