DevConf 2015

The IteratorAggregate interface

(PHP 5 >= 5.0.0)

Introduzione

Interface to create an external Iterator.

Sommario dell'interfaccia

IteratorAggregate extends Traversable {
/* Metodi */
abstract public Traversable getIterator ( void )
}

Example #1 Basic usage

<?php
class myData implements IteratorAggregate {
    public 
$property1 "Public property one";
    public 
$property2 "Public property two";
    public 
$property3 "Public property three";

    public function 
__construct() {
        
$this->property4 "last property";
    }

    public function 
getIterator() {
        return new 
ArrayIterator($this);
    }
}

$obj = new myData;

foreach(
$obj as $key => $value) {
    
var_dump($key$value);
    echo 
"\n";
}
?>

Il precedente esempio visualizzerĂ  qualcosa simile a:

string(9) "property1"
string(19) "Public property one"

string(9) "property2"
string(19) "Public property two"

string(9) "property3"
string(21) "Public property three"

string(9) "property4"
string(13) "last property"

Indice dei contenuti

add a note add a note

User Contributed Notes 3 notes

up
11
Tab Atkins
3 years ago
Note that, at least as of 5.3, you still aren't allowed to return a normal Array from getIterator().

In some places, the docs wrap the array into an ArrayObject and return that.  DON'T DO IT.  ArrayObject drops any empty-string keys on the floor when you iterate over it (again, at least as of 5.3).

Use ArrayIterator instead.  I wouldn't be surprised if it didn't have its own set of wonderful bugs, but at the very least it works correctly when you use it with this method.
up
2
Lubaev.K
1 year ago
<?php
// IteratorAggregate
// Create indexed and associative arrays.

class myData implements IteratorAggregate {

    private
$array = [];
    const
TYPE_INDEXED = 1;
    const
TYPE_ASSOCIATIVE = 2;

    public function
__construct( array $data, $type = self::TYPE_INDEXED ) {
       
reset($data);
        while( list(
$k, $v) = each($data) ) {
           
$type == self::TYPE_INDEXED ?
           
$this->array[] = $v :
           
$this->array[$k] = $v;
        }
    }

    public function
getIterator() {
        return new
ArrayIterator($this->array);
    }

}

$obj = new myData(['one'=>'php','javascript','three'=>'c#','java',], /*TYPE 1 or 2*/ );

foreach(
$obj as $key => $value) {
   
var_dump($key, $value);
    echo
PHP_EOL;
}

// if TYPE == 1
#int(0)
#string(3) "php"
#int(1)
#string(10) "javascript"
#int(2)
#string(2) "c#"
#int(3)
#string(4) "java"

// if TYPE == 2
#string(3) "one"
#string(3) "php"
#int(0)
#string(10) "javascript"
#string(5) "three"
#string(2) "c#"
#int(1)
#string(4) "java"
?>

Good luck!
up
-1
thomas at gielfeldt dot dk
3 months ago
Be careful when caching the iterator AND supplying the iterator with a back reference to the IteratorAggregate implementor. This can cause a potential memory leak.

<?php

class MyClass implements IteratorAggregate {
  public
$data;
  protected
$iterator;

  public function
getIterator() {
   
// This is the culprit. Combined with the passing of $this,
    // neither this object nor the iterator will be destroyed until
    // php has finished execution and cleans up.
   
return $this->iterator ? $this->iterator : $this->iterator = new MyIterator($this);
  }

  public function
__construct($data) {
    print
"CONSTRUCTING MyClass!\n";
   
$this->data = $data;
  }

  public function
__destruct() {
    print
"DESTROYING MyClass!\n";
  }
}

class
MyIterator implements Iterator {
  protected
$obj;

  public function
__construct($obj) {
    print
"CONSTRUCTING MyIterator!\n";
   
$this->obj = $obj;
  }

  public function
current() { return current($this->obj->data); }
  public function
key() { return key($this->obj->data); }
  public function
next() { return next($this->obj->data); }
  public function
rewind() { return reset($this->obj->data); }
  public function
valid() { return key($this->obj->data) !== NULL; }

  public function
__destruct() {
    print
"DESTROYING MyIterator!\n";
  }
}

function
test1() {
 
$a = new MyClass(array(1, 2, 3, 4));

  foreach (
$a as $k => $v) {
    print
"$k => $v\n";
  }
  print
"Iteration done!\n";
}

test1();
print
"test1 done\n";

?>

Expected result
--------------------
CONSTRUCTING MyClass!
CONSTRUCTING MyIterator!
0 => 1
1 => 2
2 => 3
3 => 4
DESTROYING MyIterator!
Iteration done!
DESTROYING MyClass!
test1 done

Actual result
--------------------
CONSTRUCTING MyClass!
CONSTRUCTING MyIterator!
0 => 1
1 => 2
2 => 3
3 => 4
Iteration done!
test1 done
DESTROYING MyClass!
DESTROYING MyIterator!
To Top