Home arrow PHP arrow Page 2 - Implementing the Iterator SPL Interface

Review: partially implementing partially the Iterator SPL interface - PHP

In this second part of a series, I make the MySQLi_ResultWrapper class a full implementer of the Iterator SPL interface. Implementing the rest of the methods declared by the interface is a straightforward process that allows us to traverse MySQL result sets by using a plain “foreach” construct.

TABLE OF CONTENTS:
  1. Implementing the Iterator SPL Interface
  2. Review: partially implementing partially the Iterator SPL interface
  3. Implementing the remaining methods of the Iterator interface
  4. The full source code of the MySQLi_ResultWrapper class
By: Alejandro Gervasio
Rating: starstarstarstarstar / 2
March 18, 2010

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

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.



 
 
>>> More PHP Articles          >>> More By Alejandro Gervasio
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PHP ARTICLES

- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: