Object Iterators in PHP

Object Iterators in PHP:

When you browse an array in PHP, you can use “foreach” . It would be interesting to be able to do the same with any given data as the result of a SQL query for example.

The simplest solution would be to put the result in a table, then browse it with “foreach”, but it’s a bit silly because you have to browse the data twice!

The solution is Iterator. Foreach does not necessarily wait for an array, but it can take an object as a parameter. Example :

$myArray = array();
$myArray[] = "item number 1";
$myArray[] = "item number 2";
$myArray[] = "item number 3";

foreach ($myArray as $i) {
echo "<p>$i</p>";
}

As well as arrays, it’s also possible loop through an object:

  • records from a database
  • navigation links
  • Files: lines of text read from a file
  • product objects in a specific shop category
  • etc

Now, we’ll create a basic class which defines a list of movies categories:

class Movies
{
private $tech;

// constructor
public function __construct() {
$this->tech = explode( ',', 'Comedie,Action,Horror,fan,TV,S fiction') ;
}

}

$tech is declared as private, so we can’t use it outside of the movies class.

Our data are in an array, so the quickest way to make an object traversable is to implement the IteratorAggregate interface:

class Movies implements IteratorAggregate
{...

We must define a public getIterator() function. This function will return something which can be iterated — such an ArrayIterator object with our
$tech array passed to its constructor:

// return iterator
public function getIterator() {
return new ArrayIterator( $this->tech );
}

 

We can iterate over all items within the $tech array. The full code:

<?php
class Movies implements IteratorAggregate
{

private $tech;

// constructor
public function __construct() {
$this->tech = explode( ',', 'Comedie,Action,Horror,fan,TV,S fiction') ;
}

// return iterator
public function getIterator() {
return new ArrayIterator( $this->tech );
}

}

// create object
$wt = new Movies();

// iterate over collection
foreach ($wt as $n => $t) {
echo "

Technology $n: $t

"
;
}

?>

The output is:

 

Other example:

Example 1:

<?php
class myIterator implements Iterator {
private $position = 0;
private $array = array(
"premierelement",
"secondelement",
"dernierelement",
);

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 output is:

Example 2:

<?php
//I wrote a quick piece of code to give the Fibonacci sequence
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;
}
?>

The output :

Example 3:

<?php
class myIterator implements Iterator
{
private
$_array = array();
public function __construct(array $array)
{
$this->_array = $array;
}
public function rewind()
{
reset($this->_array);
}
public function current()
{
return current($this->_array);
}
public function key()
{
return key($this->_array);
}
public function next()
{
next($this->_array);
}
public function valid()
{
return $this->key() !== null;
}
}

$it = new myIterator(array('foo_1' => 'bar_1','foo_2' => 'bar_2'));

//example 1 : foreach

foreach($it as $key => $value)
{
var_dump($key, $value);
}

//example 2 : while

$it -> rewind();
while($it->valid())
{
var_dump($it->key(), $it->current());

$it->next();
}

//example 3 : for

for($it->rewind();$it->valid();$it->next())
{
var_dump($it->key(), $it->current());
}
?>

The output:

Example 4:

<?php

/*
* An implementation of the Iterator
* with simpleXML to remove a node and generate a new XML file.
*
* project.xml file:
* <?xml version="1.0" encoding="UTF-8"?>
* ...
* <data>
* <item>
* <value>one</value>
* </item>
* <item>
* <value>two</value>
* </item>
* ...
* </data>
*
*/


class parseXML implements Iterator {

private $position;
private $xml;
public $item;

public function __construct() {

$this->position = 0;
$this->xml = simplexml_load_file('project.xml');

}

public function unsetItem() {

foreach ($this as $key => $value) {

if ($value->value == $this->item ) {

unset($this->xml->data->item[$key]);

}
}

$this->mkXML();
}

public function mkXML() {

file_put_contents('project.xml', $this->xml->asXML() );

}

function rewind() {
$this->position = 0;
}

function current() {
return $this->xml->data->item[$this->position];
}

function key() {
return $this->position;
}

function next() {
++$this->position;
}

function valid() {
return isset($this->xml->data->item[$this->position]);
}

}

$itemRemove = new parseXML();

$itemRemove->item = "one";

$itemRemove->unsetItem();

?>