Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Iterators in PHP

jakefolio
February 08, 2014

Iterators in PHP

PHP iterators have been around since PHP 5, but are heavily under utilized. With all the built-in iterators there is no reason you shouldn't be leveraging it's power and flexibility. In this session you will learn about all the built-in PHP iterators and be guided on how to extend and/or create your own iterators.

jakefolio

February 08, 2014
Tweet

More Decks by jakefolio

Other Decks in Programming

Transcript

  1. An iterator is an object that enables a programmer to

    traverse a container. Various types of iterators are often provided via a container's interface. Source: http://en.wikipedia.org/wiki/Iterator
  2. PHP also have a lot of awesome features; at least

    two of them are in my opinion largely underused: Iterators and Streams. “ ” Fabien Potencier (Lead Developer of Symfony Project) Source: http://fabien.potencier.org/article/44/php-iterators-and-streams-are-awesome
  3. class IterableFilterIterator extends FilterIterator { public function accept() { return

    in_array("Iterator", class_implements($this->current())); } } $classes = new IterableFilterIterator(new ArrayIterator(get_declared_classes())); foreach ($classes as $name) { echo $name . "\n"; } Classes that implement Iterator
  4. class IterableFilterIterator extends FilterIterator { public function accept() { return

    in_array("Iterator", class_implements($this->current())); } } $classes = new IterableFilterIterator(new ArrayIterator(get_declared_classes())); foreach ($classes as $name) { echo $name . "\n"; } Classes that implement Iterator Generator RecursiveIteratorIterator IteratorIterator FilterIterator RecursiveFilterIterator CallbackFilterIterator RecursiveCallbackFilterIterator ParentIterator LimitIterator CachingIterator RecursiveCachingIterator NoRewindIterator AppendIterator InfiniteIterator RegexIterator RecursiveRegexIterator EmptyIterator RecursiveTreeIterator ArrayIterator RecursiveArrayIterator DirectoryIterator FilesystemIterator RecursiveDirectoryIterator GlobIterator SplFileObject SplTempFileObject SplDoublyLinkedList SplQueue SplStack SplHeap SplMinHeap SplMaxHeap SplPriorityQueue SplFixedArray SplObjectStorage MultipleIterator IntlIterator IntlPartsIterator Phar PharData SimpleXMLIterator MongoCursor
  5. Iterator Interfaces • Traversable • Iterator • RecursiveIterator • Countable

    • SeekableIterator Source: http://www.php.net/manual/en/spl.iterators.php
  6. Interface - Iterator Source: http://us.php.net/manual/en/class.iterator.php Iterator extends Traversable { /*

    Methods */ abstract public mixed current ( void ) abstract public scalar key ( void ) abstract public void next ( void ) abstract public void rewind ( void ) abstract public boolean valid ( void ) }
  7. Interface - RecursiveIterator Source: http://www.php.net/manual/en/spl.iterators.php RecursiveIterator extends Iterator { /*

    Methods */ public RecursiveIterator getChildren ( void ) public bool hasChildren ( void ) /* Inherited methods */ abstract public mixed Iterator::current ( void ) abstract public scalar Iterator::key ( void ) abstract public void Iterator::next ( void ) abstract public void Iterator::rewind ( void ) abstract public boolean Iterator::valid ( void ) }
  8. Interface - Seekable Source: http://www.php.net/manual/en/spl.iterators.php SeekableIterator extends Iterator { /*

    Methods */ abstract public void seek ( int $position ) /* Inherited methods */ abstract public mixed Iterator::current ( void ) abstract public scalar Iterator::key ( void ) abstract public void Iterator::next ( void ) abstract public void Iterator::rewind ( void ) abstract public boolean Iterator::valid ( void ) }
  9. Iterator Aggregate Iterator Aggregate is used when you need to

    offload iteration, and its methods, to another iterator public function getIterator() { ... }
  10. Outer Iterator Outer Iterators act as a wrapper layer. Outer

    iterator is iterated and then internally iterates over inner iterator. * * * ITERATOR!
  11. Recursive Iterator Recursive Iterators prepare an iterator to be recursively

    iterated. * Requires RecursiveIteratorIterator to properly recursively Iterate. *
  12. Iterator Notes If you use foreach it will auto rewind.

    Using for or while will require you to rewind iterator.
  13. $data = [ 'title' => 'how to work with iterators',

    'posts' => [ [ 'title' => 'introduction to iterators', 'email' => '[email protected]', ], [ 'title' => 'extending iterators', 'email' => '[email protected]', ], ], ]; foreach (new RecursiveArrayIterator($data) as $field => $val) { echo "{$field}:{$val}\n"; } Sub Title Recursive*Iterator Recursively Iterate Array
  14. $data = [ 'title' => 'how to work with iterators',

    'posts' => [ [ 'title' => 'introduction to iterators', 'email' => '[email protected]', ], [ 'title' => 'extending iterators', 'email' => '[email protected]', ], ], ]; foreach (new RecursiveArrayIterator($data) as $field => $val) { echo "{$field}:{$val}\n"; } Sub Title Recursive*Iterator Recursively Iterate Array title: how to work with iterators posts: Array
  15. $data = [ 'title' => 'how to work with iterators',

    'posts' => [ [ 'title' => 'introduction to iterators', 'email' => '[email protected]', ], [ 'title' => 'extending iterators', 'email' => '[email protected]', ], ], ]; foreach (new RecursiveArrayIterator($data) as $field => $val) { echo "{$field}:{$val}\n"; } Sub Title Recursive*Iterator Recursively Iterate Array title: how to work with iterators posts: Array
  16. RecursiveIteratorIterator implements OuterIterator , Traversable , Iterator { /* Constants

    */ const integer LEAVES_ONLY = 0 ; const integer SELF_FIRST = 1 ; const integer CHILD_FIRST = 2 ; const integer CATCH_GET_CHILD = 16 ; }
  17. $data = [ 'title' => 'how to work with iterators',

    'posts' => [ [ 'title' => 'introduction to iterators', 'email' => '[email protected]', ], [ 'title' => 'extending iterators', 'email' => '[email protected]', ], ], ]; $it = new RecursiveIteratorIterator( new RecursiveArrayIterator($data) ); foreach($it as $field => $val) { echo "{$field}:{$val}\n"; } Sub Title Recursive*Iterator Recursively Iterate Array
  18. $data = [ 'title' => 'how to work with iterators',

    'posts' => [ [ 'title' => 'introduction to iterators', 'email' => '[email protected]', ], [ 'title' => 'extending iterators', 'email' => '[email protected]', ], ], ]; $it = new RecursiveIteratorIterator( new RecursiveArrayIterator($data) ); foreach($it as $field => $val) { echo "{$field}:{$val}\n"; } Sub Title Recursive*Iterator Recursively Iterate Array title: how to work with iterators title: introduction to iterators email: [email protected] title: extending iterators email: [email protected]
  19. $it = new RecursiveArrayIterator([ 'Home', 'About' => ['Careers', 'Contact'], 'Location',

    'FAQ', ]); Sub Title RecursiveNavigationIterator Hooks Output multi-dimensional array as UL/LI
  20. class RecursiveNavigationIterator extends RecursiveIteratorIterator { public $openTag = "<ul>"; public

    $closeTag = "</ul>"; public function beginIteration() { echo $this->openTag . PHP_EOL; } public function endIteration() { echo $this->closeTag . PHP_EOL; } public function beginChildren() { echo $this->openTag . PHP_EOL; } public function endChildren() { echo $this->closeTag . PHP_EOL; } } Sub Title RecursiveNavigationIterator Hooks Output multi-dimensional array as UL/LI
  21. $it = new RecursiveArrayIterator([ 'Home', 'About' => ['Careers', 'Contact'], 'Location',

    'FAQ', ]); $navIt = new RecursiveNavigationIterator($it, RecursiveIteratorIterator::SELF_FIRST); foreach ($navIt as $navItem) { echo "<li>{$navItem}</li>" . PHP_EOL; } Sub Title RecursiveNavigationIterator Hooks Output multi-dimensional array as UL/LI
  22. $it = new RecursiveArrayIterator([ 'Home', 'About' => ['Careers', 'Contact'], 'Location',

    'FAQ', ]); $navIt = new RecursiveNavigationIterator($it, RecursiveIteratorIterator::SELF_FIRST); foreach ($navIt as $navItem) { echo "<li>{$navItem}</li>" . PHP_EOL; } Sub Title RecursiveNavigationIterator Hooks Output multi-dimensional array as UL/LI <ul> <li>Home</li> <li>About</li> <ul> <li>Careers</li> <li>Contact</li> </ul> <li>Location</li> <li>FAQ</li> </ul>
  23. $it = new RecursiveIteratorIterator( new RecursiveDirectoryIterator('cache', FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST ); function

    clearCache(Iterator $it) { // Check if directory if ($it->current()->isDir()) { rmdir($it->key()); return true; } return unlink($it->key()); } iterator_apply($it, 'clearCache', [$it]); Sub Title iterator_apply Clear all files/folders in cache folder
  24. $it = new DirectoryIterator('vendor'); foreach ($it as $file) { echo

    $file->getFilename() . PHP_EOL; } Sub Title DirectoryIterator Source: Output directory content for Composer vendors http://us.php.net/manual/en/class.directoryiterator.php SplFileInfo
  25. $it = new DirectoryIterator('vendor'); foreach ($it as $file) { echo

    $file->getFilename() . PHP_EOL; } Sub Title DirectoryIterator Source: Output directory content for Composer vendors http://us.php.net/manual/en/class.directoryiterator.php SplFileInfo . .. aura autoload.php bin composer monolog psr robmorgan slim slimcontroller symfony vlucas
  26. Directory Iterator Note If you attempt to access a file

    that you do not have permission to. You will receive a UnexpectedValueException.
  27. FilesystemIterator extends DirectoryIterator implements SeekableIterator , Traversable , Iterator {

    /* Constants */ const integer CURRENT_AS_PATHNAME = 32 ; const integer CURRENT_AS_FILEINFO = 0 ; const integer CURRENT_AS_SELF = 16 ; const integer CURRENT_MODE_MASK = 240 ; const integer KEY_AS_PATHNAME = 0 ; const integer KEY_AS_FILENAME = 256 ; const integer FOLLOW_SYMLINKS = 512 ; const integer KEY_MODE_MASK = 3840 ; const integer NEW_CURRENT_AND_KEY = 256 ; const integer SKIP_DOTS = 4096 ; const integer UNIX_PATHS = 8192 ; // Default Flags FilesystemIterator::KEY_AS_PATHNAME FilesystemIterator::CURRENT_AS_FILEINFO FilesystemIterator::SKIP_DOTS Sub Title FileSystemIterator (PHP 5.3.x) FileSystemIterator Constants/Flags
  28. $it = new GlobIterator('vendor/*/*.php'); foreach ($it as $path => $file)

    { echo $path . " - " . $file->getFilename() . PHP_EOL; } Sub Title GlobIterator Source: Output directory content for Composer vendors http://us.php.net/manual/en/class.globiterator.php
  29. $it = new GlobIterator('vendor/*/*.php'); foreach ($it as $path => $file)

    { echo $path . " - " . $file->getFilename() . PHP_EOL; } Sub Title GlobIterator Source: Output directory content for Composer vendors http://us.php.net/manual/en/class.globiterator.php vendor/composer/ClassLoader.php - ClassLoader.php vendor/composer/autoload_classmap.php - autoload_classmap.php vendor/composer/autoload_namespaces.php - autoload_namespaces.php vendor/composer/autoload_psr4.php - autoload_psr4.php vendor/composer/autoload_real.php - autoload_real.php
  30. $it = new RecursiveDirectoryIterator('vendor'); foreach (new RecursiveTreeIterator($it) as $file) {

    echo $file . PHP_EOL; } Sub Title RecursiveTreeIterator Source: Output ASCII view of Directory Structure http://us.php.net/manual/en/class.recursivetreeiterator.php
  31. $it = new RecursiveDirectoryIterator('vendor'); foreach (new RecursiveTreeIterator($it) as $file) {

    echo $file . PHP_EOL; } Sub Title RecursiveTreeIterator Source: Output ASCII view of Directory Structure http://us.php.net/manual/en/class.recursivetreeiterator.php \-vendor/vlucas |-vendor/vlucas/. |-vendor/vlucas/.. \-vendor/vlucas/phpdotenv |-vendor/vlucas/phpdotenv/. |-vendor/vlucas/phpdotenv/.. |-vendor/vlucas/phpdotenv/.git | |-vendor/vlucas/phpdotenv/.git/. | |-vendor/vlucas/phpdotenv/.git/.. | |-vendor/vlucas/phpdotenv/.git/FETCH_HEAD | |-vendor/vlucas/phpdotenv/.git/HEAD | |-vendor/vlucas/phpdotenv/.git/ORIG_HEAD | |-vendor/vlucas/phpdotenv/.git/branches | | |-vendor/vlucas/phpdotenv/.git/branches/. | | \-vendor/vlucas/phpdotenv/.git/branches/.. | |-vendor/vlucas/phpdotenv/.git/config | |-vendor/vlucas/phpdotenv/.git/description
  32. Source: http://www.php.net/manual/en/spl.iterators.php Need to view all files in a directory,

    but it keeps returning Version Control folders (.svn and .git). Problem:
  33. class NoVCSIterator extends FilterIterator { public function accept() { $vcsFolders

    = array(".git", ".svn"); $file = $this->current(); if ($file->isDir() && (in_array($vcsFolders, $file->getFilename())) { return false; } return true; } } Sub Title FilterIterator Do not show Version Control folders
  34. class LargeFileFilterIterator extends FilterIterator { public function accept() { $file

    = $this->current(); if ($file->getSize() > $this->fileSizeMin) { return true; } return false; } } class ImageFilterIterator extends FilterIterator { public function accept() { $file = $this->current(); if (in_array($file->getExtension(), $this->imageWhiteList)) { return true; } return false; } } Sub Title FilterIterator Only show images greater than 5MB
  35. $dir = new FileSystemIterator(UPLOADS_PATH); $filterIt = new LargeFileFilterIterator( new ImageFilterIterator($dir,

    ['jpg']) ); foreach($filterIt as $file) { echo $file->getFileName() . PHP_EOL; } Sub Title FilterIterator Only show images greater than 5MB
  36. $dir = new FileSystemIterator(UPLOADS_PATH); $filterIt = new LargeFileFilterIterator( new ImageFilterIterator($dir,

    ['jpg']) ); echo count($filterIt); // 1 echo iterator_count($filterIt); // 2 foreach($filterIt as $file) { echo $file->getFileName() . PHP_EOL; } Sub Title iterator_count Countable with Filters
  37. /* Constants */ const integer RegexIterator->MATCH = 0 ; const

    integer GET_MATCH = 1 ; const integer ALL_MATCHES = 2 ; const integer SPLIT = 3 ; const integer REPLACE = 4 ; const integer USE_KEY = 1 ; $it = new RecursiveDirectoryIterator( 'vendor', RecursiveDirectoryIterator::SKIP_DOTS ); $regexIt = new RecursiveRegexIterator( $it, '/^.*\.(php|env|json|yml)$/', RegexIterator::ALL_MATCHES ); foreach (new RecursiveIteratorIterator($regexIt) as $path => $file) { echo $path . PHP_EOL; } Sub Title RegexIterator Source: Match specific file types with RecursiveDirectoryIterator http://us3.php.net/manual/en/class.regexiterator.php
  38. /* Constants */ const integer RegexIterator->MATCH = 0 ; const

    integer GET_MATCH = 1 ; const integer ALL_MATCHES = 2 ; const integer SPLIT = 3 ; const integer REPLACE = 4 ; const integer USE_KEY = 1 ; $it = new RecursiveDirectoryIterator( 'vendor', RecursiveDirectoryIterator::SKIP_DOTS ); $regexIt = new RecursiveRegexIterator( $it, '/^.*\.(php|env|json|yml)$/', RegexIterator::ALL_MATCHES ); foreach (new RecursiveIteratorIterator($regexIt) as $path => $file) { echo $path . PHP_EOL; } Sub Title RegexIterator Source: Match specific file types with RecursiveDirectoryIterator http://us3.php.net/manual/en/class.regexiterator.php vendor/autoload.php vendor/composer/ClassLoader.php vendor/composer/autoload_classmap.php vendor/composer/autoload_namespaces.php vendor/composer/autoload_psr4.php vendor/composer/autoload_real.php vendor/composer/installed.json
  39. Source: http://www.php.net/manual/en/spl.iterators.php Parent Iterator is a FilterIterator that only accepts

    elements that have children. Hence the name ParentIterator Parent Iterator
  40. Source: http://www.php.net/manual/en/spl.iterators.php Currently have a CSV with a lot of

    lines, but I need to paginate with 3 results per page. Problem:
  41. $usersCSV = <<<CSV "jsmith", "Jake", "Smith", "[email protected]" "saustin", "Steve", "Austin",

    "[email protected]" "srogers", "Steven", "Rogers", "[email protected]" "ballen", "Barry", "Allen", "[email protected]" "bbanner", "Bruce", "Banner", "[email protected]" CSV; $csv = new SplTempFileObject(); $csv->fwrite($usersCSV); $csv->setFlags(SplFileObject::READ_CSV); $it = new LimitIterator($csv, 0, 3); foreach ($it as list($username, $firstName, $lastName, $email)) { echo "{$firstName} {$lastName}" . PHP_EOL; } Sub Title LimitIterator Limit CSV output to first 3
  42. $usersCSV = <<<CSV "jsmith", "Jake", "Smith", "[email protected]" "saustin", "Steve", "Austin",

    "[email protected]" "srogers", "Steven", "Rogers", "[email protected]" "ballen", "Barry", "Allen", "[email protected]" "bbanner", "Bruce", "Banner", "[email protected]" CSV; $csv = new SplTempFileObject(); $csv->fwrite($usersCSV); $csv->setFlags(SplFileObject::READ_CSV); $it = new LimitIterator($csv, 0, 3); foreach ($it as list($username, $firstName, $lastName, $email)) { echo "{$firstName} {$lastName}" . PHP_EOL; } Sub Title LimitIterator Limit CSV output to first 3 Jake Smith Steve Austin Steven Rogers
  43. $usersCSV = <<<CSV "jsmith", "Jake", "Smith", "[email protected]" "saustin", "Steve", "Austin",

    "[email protected]" "srogers", "Steven", "Rogers", "[email protected]" "ballen", "Barry", "Allen", "[email protected]" "bbanner", "Bruce", "Banner", "[email protected]" CSV; $csv = new SplTempFileObject(); $csv->fwrite($usersCSV); $csv->setFlags(SplFileObject::READ_CSV); $it = new LimitIterator($csv, 0, 3); try { $it->seek(20); } catch (OutOfBoundsException $e) { echo "Error: " . $e->getMessage() . PHP_EOL; } Sub Title LimitIterator Throw Exception if seeking beyond total number of elements
  44. $usersCSV = <<<CSV "jsmith", "Jake", "Smith", "[email protected]" "saustin", "Steve", "Austin",

    "[email protected]" "srogers", "Steven", "Rogers", "[email protected]" "ballen", "Barry", "Allen", "[email protected]" "bbanner", "Bruce", "Banner", "[email protected]" CSV; $csv = new SplTempFileObject(); $csv->fwrite($usersCSV); $csv->setFlags(SplFileObject::READ_CSV); $it = new LimitIterator($csv, 0, 3); try { $it->seek(20); } catch (OutOfBoundsException $e) { echo "Error: " . $e->getMessage() . PHP_EOL; } Sub Title LimitIterator Throw Exception if seeking beyond total number of elements Error: Cannot seek to 20 which is behind offset 0 plus count 3
  45. Source: http://www.php.net/manual/en/spl.iterators.php I need to find all files that contain

    the word “recursive”, but don’t want to create a new class to extend FilterIterator. Problem:
  46. $dirIt = new GlobIterator('*.php'); $recursiveFiles = new CallbackFilterIterator( $dirIt, function($current,

    $key, $it) { return preg_match('/recursive/i', $current); } ); foreach($recursiveFiles as $name) { echo $name . PHP_EOL; } Sub Title CallbackFilterIterator CallbackFilterIterator requires PHP 5.4
  47. $dirIt = new GlobIterator('*.php'); $recursiveFiles = new CallbackFilterIterator( $dirIt, function($current,

    $key, $it) { return preg_match('/recursive/i', $current); } ); foreach($recursiveFiles as $name) { echo $name . PHP_EOL; } Sub Title CallbackFilterIterator CallbackFilterIterator requires PHP 5.4 /recursive_cache.php /recursive_it.php
  48. Source: http://www.php.net/manual/en/spl.iterators.php I need to know what value of the

    next element will be. Think prev/ next navigation. Problem:
  49. $articles = new ArrayIterator([ 'NetTuts.com: Integrating Zendesk With WordPress', 'Laravel

    News: The Artisan Files Alex Dover', 'That Podcast: Episode 10 The one with the "best practices"', 'Community News: Packagist Latest Releases for 11.14.2014', ]); $it = new CachingIterator($articles); $it->rewind(); foreach ($it as $article) { echo "{$article}"; if ($it->hasNext()) { echo " --- {$it->getInnerIterator()->current()}"; } echo PHP_EOL; } Sub Title CachingIterator CachingIterator? Look Ahead Iterator! Source: http://stackoverflow.com/questions/2458099/peek-ahead-when-iterating-an-array-in-php-5-2
  50. $articles = new ArrayIterator([ 'NetTuts.com: Integrating Zendesk With WordPress', 'Laravel

    News: The Artisan Files Alex Dover', 'That Podcast: Episode 10 The one with the "best practices"', 'Community News: Packagist Latest Releases for 11.14.2014', ]); $it = new CachingIterator($articles); $it->rewind(); foreach ($it as $article) { echo "{$article}"; if ($it->hasNext()) { echo " --- {$it->getInnerIterator()->current()}"; } echo PHP_EOL; } Sub Title CachingIterator CachingIterator? Look Ahead Iterator! Source: http://stackoverflow.com/questions/2458099/peek-ahead-when-iterating-an-array-in-php-5-2 NetTuts.com: Integrating Zendesk With WordPress --- Laravel News: The Artisan Files Alex Dover Laravel News: The Artisan Files Alex Dover --- That Podcast: Episode 10 The one with the "best practices" That Podcast: Episode 10 The one with the "best practices" --- Community News: Packagist Latest Releases for 11.14.2014 Community News: Packagist Latest Releases for 11.14.2014
  51. function getLines($file) { $f = fopen($file, 'r'); if (!$f) throw

    new Exception(); while ($line = fgets($f)) { yield $line; } fclose($f); } Sub Title Generator We Have a Generator http://blog.ircmaxell.com/2012/07/what-generators-can-do-for-you.html It’s really that easy!
  52. function easyAsAbc() { yield 1; yield 2; yield 3; }

    foreach (easyAsAbc() as $num) { echo $num . PHP_EOL; } Sub Title Quick Tips with Yield http://us3.php.net/manual/en/language.generators.syntax.php
  53. function easyAsAbc() { yield 1; yield 2; yield 3; }

    foreach (easyAsAbc() as $num) { echo $num . PHP_EOL; } Sub Title Quick Tips with Yield http://us3.php.net/manual/en/language.generators.syntax.php 1 2 3
  54. function easyAsAbc() { yield 1; return; yield 2; yield 3;

    } foreach (easyAsAbc() as $num) { echo $num . PHP_EOL; } Sub Title Quick Tips with Yield http://us3.php.net/manual/en/language.generators.syntax.php End an iteration
  55. function easyAsAbc() { yield 1; return; yield 2; yield 3;

    } foreach (easyAsAbc() as $num) { echo $num . PHP_EOL; } Sub Title Quick Tips with Yield http://us3.php.net/manual/en/language.generators.syntax.php End an iteration 1
  56. function easyAsAbc() { yield 1; return true; yield 2; yield

    3; } foreach (easyAsAbc() as $num) { echo $num . PHP_EOL; } Sub Title Quick Tips with Yield http://us3.php.net/manual/en/language.generators.syntax.php Returning a value will cause a PHP Fatal Returning ANY VALUE will cause a PHP Fatal
  57. function easyAsAbc() { yield 1; return true; yield 2; yield

    3; } foreach (easyAsAbc() as $num) { echo $num . PHP_EOL; } Sub Title Quick Tips with Yield http://us3.php.net/manual/en/language.generators.syntax.php Returning a value will cause a PHP Fatal Returning ANY VALUE will cause a PHP Fatal PHP Fatal error: Generators cannot return values using "return"
  58. function userAttributes() { yield 'id' => 1; yield 'username' =>

    'jsmith'; yield 'email' => '[email protected]'; } foreach (userAttributes() as $key => $val) { echo $key . ':' . $val . PHP_EOL; } Sub Title Quick Tips with Yield http://us3.php.net/manual/en/language.generators.syntax.php Key and Value yield
  59. function userAttributes() { yield 'id' => 1; yield 'username' =>

    'jsmith'; yield 'email' => '[email protected]'; } foreach (userAttributes() as $key => $val) { echo $key . ':' . $val . PHP_EOL; } Sub Title Quick Tips with Yield http://us3.php.net/manual/en/language.generators.syntax.php Key and Value yield id:1 username:jsmith email:[email protected]
  60. function counter($start) { for ($i = $start; $i >= $start;

    $i++) { $command = (yield $i); if ($command == "stop") { return; } } } $counter = counter(1); foreach ($counter as $num) { if ($num >= 20) { $counter->send('stop'); } echo $num . PHP_EOL; } Receive data Quick Tips with Yield
  61. function counter($start) { for ($i = $start; $i >= $start;

    $i++) { $command = (yield $i); if ($command == "stop") { return; } } } $counter = counter(1); foreach ($counter as $num) { if ($num >= 20) { $counter->send('stop'); } echo $num . PHP_EOL; } Receive data Quick Tips with Yield
  62. function counter($start) { for ($i = $start; $i >= $start;

    $i++) { $command = (yield $i); if ($command == "stop") { return; } } } $counter = counter(1); foreach ($counter as $num) { if ($num >= 20) { $counter->send('stop'); } echo $num . PHP_EOL; } Receive data Quick Tips with Yield Receiving values via send method
  63. function counter($start) { for ($i = $start; $i >= $start;

    $i++) { $command = (yield $i); if ($command == "stop") { return; } } } $counter = counter(1); foreach ($counter as $num) { if ($num >= 20) { $counter->send('stop'); } echo $num . PHP_EOL; } Receive data Quick Tips with Yield Receiving values via send method 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  64. Other Iterators •EmptyIterator •If you try to access current() it

    will throw an Exception •InfiniteIterator •Continuously runs (auto rewinds)
  65. Iterator Functions • iterator_to_array • If Iterator is Recursive, it

    will flatten array • iterator_apply • similar to array_walk • iterator_count • used when iterator doesn’t implement countable