Since my goal in this article is to make the MySQL handling class built in the prior chapter a full implementer of the ArrayAccess SPL interface, first I want to review the definition of this class, along with the one that connects to the database server and runs hard-coded SQL statements. Having explained that, here’s the source code of the sample class that performs the aforementioned tasks: 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(); } } Since at this point the inner workings of the previous “MySQLiWrapper” class should be pretty familiar to you, we'll move forward and take a close look at the definition of the following class. As I explained in the introduction, aside from implementing the Iterator and Countable PHP interfaces, this class includes two of the methods declared by ArrayAcess. Here’s how this other sample class has been defined: class MySQLi_ResultWrapper extends MySQLi_Result implements Iterator, ArrayAccess, Countable { 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); }
// count rows in result set (implementation required by 'count()' method in Countable interface) public function count() { return $this->num_rows; }
// 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(); }
// get current result set pointer (implementation required by 'key()' method in Iterator interface) public function key() { return $this->_pointer; }
// move forward result set pointer (implementation required by 'next()' method in Iterator interface) public function next() { ++$this->_pointer; $this->movePointer($this->_pointer); return $this; }
// determine if result set pointer is valid or not (implementation required by 'valid()' method in Iterator interface) public function valid() { return $this->_pointer < $this->num_rows; }
// determine if the given offset exists (implementation required by 'offsetExists()' method in ArrayAccess interface) public function offsetExists($offset) { $this->movePointer($offset); $row = $this->fetchObject(); return isset($row); }
// not implemented (required by 'offsetSet()' method in ArrayAccess interface) public function offsetSet($offset, $value){}
// free up result set public function __destruct() { $this->close(); } } So far, there’s nothing hard to understand with reference to the way the “MySQLi_ResultWrapper” class has been defined, right? As I said before, this class is only a partial implementer of the ArrayAccess interface, as it defines two of the four methods of the interface, “offsetExists()” and “offsetSet()” respectively. For obvious reasons, in its current state the class isn’t fully functional, since it must include all of the methods defined by ArrayAccess. Therefore, to suit this requirement, in the following section I’m going to add to the class another method of the corresponding interface, called “offsetUnset(),” which in this case won’t have any explicit implementation. Now, click on the link below and read the next segment.
blog comments powered by Disqus |
|
|
|
|
|
|
|