Here's a Fibonacci example using the formula, rather than addition.
<?php
/**
* @author Anthony Sterling
*/
class FibonacciSequence implements Iterator
{
protected
$limit = 0;
protected
$key = 0;
public function __construct($limit = 0)
{
$this->limit = (integer)$limit;
}
public function current()
{
return round(
(pow(((1 + sqrt(5)) / 2), $this->key) - pow((-1 / (1 + sqrt(5)) / 2), $this->key)) / sqrt(5),
null
);
}
public function key()
{
return $this->key;
}
public function next()
{
$this->key++;
}
public function rewind()
{
$this->key = 0;
}
public function valid()
{
return $this->key < $this->limit;
}
}
foreach(new FibonacciSequence() as $number)
{
printf(
'%d<br />',
$number
);
}
/*
0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
17711
28657
46368
75025
121393
196418
317811
514229
*/
?>
Anthony.
The Iterator interface
Introduction
Interface for external iterators or objects that can be iterated themselves internally.
Interface synopsis
Example #1 Basic usage
This example demonstrates in which order methods are called when using foreach with an iterator.
<?php
class myIterator implements Iterator {
private $position = 0;
private $array = array(
"firstelement",
"secondelement",
"lastelement",
);
public function __construct() {
$this->position = 0;
}
function rewind() {
var_dump(__METHOD__);
$this->position = 0;
}
function current() {
var_dump(__METHOD__);
return $this->array[$this->position];
}
function key() {
var_dump(__METHOD__);
return $this->position;
}
function next() {
var_dump(__METHOD__);
++$this->position;
}
function valid() {
var_dump(__METHOD__);
return isset($this->array[$this->position]);
}
}
$it = new myIterator;
foreach($it as $key => $value) {
var_dump($key, $value);
echo "\n";
}
?>
The above example will output something similar to:
string(18) "myIterator::rewind" string(17) "myIterator::valid" string(19) "myIterator::current" string(15) "myIterator::key" int(0) string(12) "firstelement" string(16) "myIterator::next" string(17) "myIterator::valid" string(19) "myIterator::current" string(15) "myIterator::key" int(1) string(13) "secondelement" string(16) "myIterator::next" string(17) "myIterator::valid" string(19) "myIterator::current" string(15) "myIterator::key" int(2) string(11) "lastelement" string(16) "myIterator::next" string(17) "myIterator::valid"
Table of Contents
- Iterator::current — Return the current element
- Iterator::key — Return the key of the current element
- Iterator::next — Move forward to next element
- Iterator::rewind — Rewind the Iterator to the first element
- Iterator::valid — Checks if current position is valid
Iterator
Anthony Sterling
17-Sep-2009 04:20
17-Sep-2009 04:20
Geoffrey Sneddon
23-May-2009 12:42
23-May-2009 12:42
So, playing around with iterators in PHP (coming from languages where I'm spoiled with generators to do things like this), I wrote a quick piece of code to give the Fibonacci sequence (to infinity, though only the first terms up to F_{10} are output).
<?php
class Fibonacci implements Iterator {
private $previous = 1;
private $current = 0;
private $key = 0;
public function current() {
return $this->current;
}
public function key() {
return $this->key;
}
public function next() {
$newprevious = $this->current;
$this->current += $this->previous;
$this->previous = $newprevious;
$this->key++;
}
public function rewind() {
$this->previous = 1;
$this->current = 0;
$this->key = 0;
}
public function valid() {
return true;
}
}
$seq = new Fibonacci;
$i = 0;
foreach ($seq as $f) {
echo "$f\n";
if ($i++ === 10) break;
}
?>
RocketInABog at techno-monks dot net
11-May-2009 06:35
11-May-2009 06:35
<?php
# - Here is an implementation of the Iterator interface for arrays
# which works with maps (key/value pairs)
# as well as traditional arrays
# (contiguous monotonically increasing indexes).
# Though it pretty much does what an array
# would normally do within foreach() loops,
# this class may be useful for using arrays
# with code that generically/only supports the
# Iterator interface.
# Another use of this class is to simply provide
# object methods with tightly controlling iteration of arrays.
class tIterator_array implements Iterator {
private $myArray;
public function __construct( $givenArray ) {
$this->myArray = $givenArray;
}
function rewind() {
return reset($this->myArray);
}
function current() {
return current($this->myArray);
}
function key() {
return key($this->myArray);
}
function next() {
return next($this->myArray);
}
function valid() {
return key($this->myArray) !== null;
}
}
?>
mike dot thornton at firstroi dot com
05-May-2009 03:40
05-May-2009 03:40
It's important to note that following won't work if you have null values.
<?php
function valid() {
var_dump(__METHOD__);
return isset($this->array[$this->position]);
}
?>
Other examples have shown the following which won't work if you have false values:
<?php
function valid() {
return $this->current() !== false;
}
?>
Instead use:
<?php
function valid() {
return array_key_exists($this->array, $this->position);
}
?>
Or the following if you do not store the position.
<?php
public function valid() {
return !is_null(key($this->array));
}
?>
nullhility at gmail dot com
19-Feb-2009 09:13
19-Feb-2009 09:13
Because the purpose of the above example is to illustrate the foreach statement's call sequence I made my own example of the Iterator interface just to give other user's some idea of possible solutions that might benefit from the interface.
<?php
class MysqlResult implements Iterator
{
private $result;
private $position;
private $row_data;
public function __construct ($result)
{
$this->result = $result;
$this->position = 0;
}
public function current ()
{
return $this->row_data;
}
public function key ()
{
return $this->position;
}
public function next ()
{
$this->position++;
$this->row_data = mysql_fetch_assoc($this->result);
}
public function rewind ()
{
$this->position = 0;
mysql_data_seek($this->result, 0);
/* The initial call to valid requires that data
pre-exists in $this->row_data
*/
$this->row_data = mysql_fetch_assoc($this->result);
}
public function valid ()
{
return (boolean) $this->row_data;
}
}
$link = mysql_connect("localhost", "user");
mysql_select_db('example_db', $link);
$result = new MysqlResult(mysql_query("SELECT * FROM `example_tbl`"));
foreach ($result as $pos => $row) {
var_dump($pos, $row);
}
?>
http://chanibal.net
28-Jan-2009 10:11
28-Jan-2009 10:11
For anyone interested in how exactly does a iterator work in a foreach:
<?php
class SomeIterator implements Iterator {/*...implement...*/}
$it=new SomeIterator();
foreach($it as $key => $val) {
print "{$key}=>{$val}\n";
}
// works exactly the same as
$it=new SomeIterator();
for(
$it->rewind();
$it->valid();
$val=$it->current(), $key=$it->key(), $it->next()
) {
print "{$key}=>{$val}\n";
}
// and if someone forgot how for(;;) works...
$it=new SomeIterator();
$it->rewind;
while($it->valid()) {
$val=$it->current();
$key=$it->key();
$it->next();
print "{$key}=>{$val}\n";
}
?>
