• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 位置: php 中文手册 -> php 语言

    php 预定义聚合式迭代器接口

    (No version information available, might only be in Git)

    简介

    创建外部迭代器的接口。

    接口摘要

    IteratorAggregate extends Traversable 
    {
    	/* 方法 */
    	abstract public getIterator ( void ) : Traversable
    }
    

    Example #1 基本用法

    <?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";
    }
    ?>
    

    以上例程的输出类似于:

    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"
    
    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.
    It might seem obvious, but you can return a compiled generator from your IteratorAggregate::getIterator() implementation.
    <?php
    class Collection implements IteratorAggregate
    {
      private $items = [];
      public function __construct($items = [])
      {
        $this->items = $items;
      }
      public function getIterator()
      {
        return (function () {
          while(list($key, $val) = each($this->items)) {
            yield $key => $val;
          }
        })();
      }
    }
    $data = [ 'A', 'B', 'C', 'D' ];
    $collection = new Collection($data);
    foreach ($collection as $key => $val) {
      echo sprintf("[%s] => %s\n", $key, $val);
    }
    ?>
    
    <?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!
    You can use yield from in getIterator in recent PHP 7 versions: 
    <?php 
    class Example implements \IteratorAggregate
    {
     protected $data = [];
     public function __construct(array $data) 
     {
      $this->data = $data;
     }
     public function getIterator() 
     {
      yield from $this->data;
     }
    }
    $test = new Example([1, 2, 3]);
    foreach ($test as $node) {
     echo $test, PHP_EOL;
    }
    /*
     * Outputs:
     *
     * 1
     * 2
     * 3 
     */ ?>
    
    Example of the Iterator Pattern
    <?php
    namespace DesignPaterns;
    class BookCollection implements \IteratorAggregate
    {
      private $a_titles = array();
      public function getIterator()
      {
        return new BookIterator($this);
      }
      public function addTitle($string)
      {
        $this->a_titles[] = $string;
      }
      public function getTitle($key)
      {
        if (isset($this->a_titles[$key])){
          return $this->a_titles[$key];
        }
        return null;
      }
      public function is_empty()
      {
        return empty($a_titles);
      }
    }
    <?php
    namespace DesignPaterns;
    class BookIterator implements \Iterator
    {
      private $i_position = 0;
      private $booksCollection;
      public function __construct(BookCollection $booksCollection)
      {
        $this->booksCollection = $booksCollection;
      }
      public function current()
      {
        return $this->booksCollection->getTitle($this->i_position);
      }
      public function key()
      {
        return $this->i_position;
      }
      public function next()
      {
        $this->i_position++;
      }
      public function rewind()
      {
        $this->i_position = 0;
      }
      public function valid()
      {
        return !is_null($this->booksCollection->getTitle($this->i_position));
      }
    }
    <?php require 'vendor/autoload.php';
    use DesignPaterns\BookCollection;
    $booksCollection = new BookCollection();
    $booksCollection->addTitle('Design Patterns');
    $booksCollection->addTitle('PHP7 is the best');
    $booksCollection->addTitle('Laravel Rules');
    $booksCollection->addTitle('DHH Rules');
    foreach($booksCollection as $book){
      var_dump($book);
    }
    /* === Output ===
     * string(15) "Design Patterns"
     * string(16) "PHP7 is the best"
     * string(13) "Laravel Rules"
     * string(9) "DHH Rules"
    */