Simply put, I believe each of the main posts, Harry included, is wrong. The concept stems from my work with the Eclipse library, and the Iterator object presented here:
Code: Select all
<?php
class Iterator {
/***
* Create a new iterator that's immediately ready for use. Normally,
* the constructor calls <code>reset()</code>.
***/
function Iterator(& $container) {}
/***
* Initialize this iterator.
* @returns void
***/
function reset() {}
/***
* Advance the internal cursor to the next object. The behavior of this
* method is undefined if <code>isValid()</code> returns <code>false</code>.
* @returns void
***/
function next() {}
/***
* Check if the iterator is valid
* @returns bool
***/
function isValid() {}
/***
* Return a reference to the current object. The behavior of this method
* is undefined if <code>isValid()</code> returns <code>false</code>.
* @returns mixed
***/
function &getCurrent() {}
}
?>Harry proposed this option:
Code: Select all
<?php
/**
* Defines the interface for concrete Iterators
*
* @interface
*/
class SimpleIterator {
/**
* Returns the current element from the collection
* and moves the internal pointer forward one
*
* @return mixed
*/
function fetch() {
die ('SimpleIterator::fetch must be implemented');
}
/**
* Returns the number of elements in the collection
*
* @return int
*/
function size() {
die ('SimpleIterator::size must be implemented');
}
/**
* Resets the collection pointer to the start
*
* @return void
*/
function reset() {
die ('SimpleIterator::reset must be implemented');
}
}
?>The SimpleIterator doesn't solve the problem, it just shifts the potential solution from the potential problem.
Really, the problem is this. Why should a programmer do this:
Code: Select all
<?php
for ( $it2->reset(); $it2->isValid(); $it2->next() ) {
$row = $it2->getCurrent();
echo 'IT2 -> ',$row[0],"\n";
}
?>Code: Select all
<?php
while ( $it->next() ) {
$row = $it->getCurrent();
echo 'IT -> ',$row[0],"\n";
}
?>The problem wasn't with the interace, but with how the object worked interanally.
So I left the Iterator object the way it was, and just added:
Code: Select all
<?php
/**
* The current iteration value
* @type mixed
*/
var $current_iteration;
/**
* The result of the <code>next()</code> call
* @type bool
*/
var $next_result = null;
?>Anyways, looking at QueryIterator, I made the necessary changes to work with the new Iterator.
Code: Select all
<?php
class QueryIterator extends Iterator
{
// DATA MEMBERS
/***
* The query to iterator over (a <code>QueryResult</code> or a
* <code>Query</code>)
* @type QueryResult
***/
var $queryResult;
/***
* How each row should be retrieved. Should be <code>ECLIPSE_DB_BOTH</code>,
* <code>ECLIPSE_DB_ASSOC</code> or <code>ECLIPSE_DB_NUM</code>
* @type int
***/
var $rowType;
/***
* The index of the current row
* @type int
***/
var $index;
/***
* The total number of rows in the query
* @type int
***/
var $total;
// CREATORS
/***
* Construct a new <code>QueryIterator</code>-object
* @param $queryResult the <code>QueryResult</code> to iterate over
***/
function QueryIterator(&$queryResult, $rowType = ECLIPSE_DB_BOTH)
{
$this->queryResult =& $queryResult;
$this->rowType = $rowType;
$this->reset();
}
// MANIPULATORS
/***
* @returns void
***/
function reset()
{
$this->index = -1;
}
/***
* @returns void
***/
function next()
{
$this->index++;
$this->next_result = ( $this->current_iteration =& $this->queryResult->getRow($this->index, $this->rowType) );
return $this->next_result;
}
// ACCESSORS
/***
* @returns bool
***/
function isValid()
{
if ( $this->next_result == null ) return $this->next();
return $this->next_result;
}
/***
* Return a reference to the current row of the <code>QueryResult</code>
* @returns array
***/
function &getCurrent()
{
return $this->current_iteration;
}
}
?>Code: Select all
<?php
include 'MyDatabase.php';
include 'QueryIterator.php';
$db = &new MyDatabase('database', 'host');
$db->connect('username','password');
$result =& $db->query("SHOW TABLES");
$it = &new QueryIterator($result);
$it2 = &new QueryIterator($result);
while ( $it->next() ) {
$row = $it->getCurrent();
echo 'IT -> ',$row[0],"\n";
}
for ( $it2->reset(); $it2->isValid(); $it2->next() ) {
$row = $it2->getCurrent();
echo 'IT2 -> ',$row[0],"\n";
}
?>Thoughts, comments, flames?