$30 off During Our Annual Pro Sale. View Details »

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. Iterators
    IN PHP
    NOW WITH GENERATORS

    View Slide

  2. http://bitly.com/wNwg6N

    View Slide

  3. 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

    View Slide

  4. 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

    View Slide

  5. One Iterator
    Two Iterator
    Three Iterator
    floor();

    View Slide

  6. Where are Iterators
    Used?

    View Slide

  7. Iterators in Source
    https://github.com/php/php-src/tree/master/ext/spl

    View Slide

  8. Everyone Loves
    Iterators

    View Slide

  9. Everyone Loves
    Iterators
    Have you used SimpleXML?

    View Slide

  10. Everyone Loves
    Iterators
    Have you used SimpleXML?
    Have you used pdo?

    View Slide

  11. 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

    View Slide

  12. 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

    View Slide

  13. Defining an Iterator

    View Slide

  14. Iterator Interfaces

    View Slide

  15. Iterator Interfaces
    • Traversable
    • Iterator
    • RecursiveIterator
    • Countable
    • SeekableIterator
    Source: http://www.php.net/manual/en/spl.iterators.php

    View Slide

  16. 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 )
    }

    View Slide

  17. 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 )
    }

    View Slide

  18. Interface -
    Countable
    Source: http://www.php.net/manual/en/spl.iterators.php
    Countable {
    /* Methods */
    abstract public int count ( void )
    }

    View Slide

  19. 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 )
    }

    View Slide

  20. Iterator Basics

    View Slide

  21. Iterator Aggregate
    Iterator Aggregate is used when you
    need to offload iteration, and its
    methods, to another iterator
    public function getIterator() { ... }

    View Slide

  22. Iterator Aggregate
    Iterator Aggregate
    Iterator

    View Slide

  23. Outer Iterator
    Outer Iterators act as a wrapper layer.
    Outer iterator is iterated and then
    internally iterates over inner iterator.
    *
    *
    *
    ITERATOR!

    View Slide

  24. Outer Iterator
    Outer Iterator
    Inner
    Iterator

    View Slide

  25. Outer Iterator
    Outer Iterator
    Inner
    Iterator

    View Slide

  26. Recursive Iterator
    Recursive Iterators prepare an iterator
    to be recursively iterated.
    * Requires RecursiveIteratorIterator to
    properly recursively Iterate. *

    View Slide

  27. Recursive
    Iterator
    Recursive Iterator
    Get Children

    View Slide

  28. Iterator Notes
    If you use foreach it will auto rewind.
    Using for or while will require you to
    rewind iterator.

    View Slide

  29. Recursive Iterators

    View Slide

  30. $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

    View Slide

  31. $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

    View Slide

  32. $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

    View Slide

  33. View Slide

  34. 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 ;
    }

    View Slide

  35. $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

    View Slide

  36. $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]

    View Slide

  37. $it = new RecursiveArrayIterator([
    'Home',
    'About' => ['Careers', 'Contact'],
    'Location',
    'FAQ',
    ]);
    Sub Title
    RecursiveNavigationIterator Hooks
    Output multi-dimensional array as UL/LI

    View Slide

  38. class RecursiveNavigationIterator extends RecursiveIteratorIterator
    {
    public $openTag = "";
    public $closeTag = "";
    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

    View Slide

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

    View Slide

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

    Home
    About

    Careers
    Contact

    Location
    FAQ

    View Slide

  41. Problem:
    Source: http://www.php.net/manual/en/spl.iterators.php
    I have a cache folder, but it goes
    many folders deep.

    View Slide

  42. $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

    View Slide

  43. Directory Iterator

    View Slide

  44. $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

    View Slide

  45. $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

    View Slide

  46. Directory Iterator Note
    If you attempt to access a file that you do
    not have permission to. You will receive a
    UnexpectedValueException.

    View Slide

  47. Filesystem Iterator

    View Slide

  48. 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

    View Slide

  49. Glob Iterator

    View Slide

  50. $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

    View Slide

  51. $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

    View Slide

  52. $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

    View Slide

  53. $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

    View Slide

  54. Filter Iterator

    View Slide

  55. 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:

    View Slide

  56. 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

    View Slide

  57. Source: http://www.php.net/manual/en/spl.iterators.php
    I need to see all images that are over
    5MB that have been uploaded.
    Problem:

    View Slide

  58. 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

    View Slide

  59. $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

    View Slide

  60. $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

    View Slide

  61. Regex Iterator

    View Slide

  62. /* 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

    View Slide

  63. /* 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

    View Slide

  64. Parent Iterator

    View Slide

  65. 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

    View Slide

  66. Limit Iterator

    View Slide

  67. 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:

    View Slide

  68. $usersCSV = <<"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

    View Slide

  69. $usersCSV = <<"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

    View Slide

  70. $usersCSV = <<"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

    View Slide

  71. $usersCSV = <<"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

    View Slide

  72. Callback Filter
    Iterator

    View Slide

  73. 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:

    View Slide

  74. $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

    View Slide

  75. $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

    View Slide

  76. Caching Iterator

    View Slide

  77. 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:

    View Slide

  78. $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

    View Slide

  79. $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

    View Slide

  80. Generators

    View Slide

  81. 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!

    View Slide

  82. NOW IN PHP

    View Slide

  83. 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

    View Slide

  84. 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

    View Slide

  85. 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

    View Slide

  86. 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

    View Slide

  87. 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

    View Slide

  88. 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"

    View Slide

  89. 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

    View Slide

  90. 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]

    View Slide

  91. 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

    View Slide

  92. 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

    View Slide

  93. 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

    View Slide

  94. 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

    View Slide

  95. Other Iterators

    View Slide

  96. Other Iterators
    •EmptyIterator
    •If you try to access current() it
    will throw an Exception
    •InfiniteIterator
    •Continuously runs (auto rewinds)

    View Slide

  97. Iterator Functions

    View Slide

  98. 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

    View Slide

  99. Questions?
    Concerns?
    Complaints?

    View Slide

  100. https://joind.in/12807

    View Slide

  101. jakefolio
    http://jakefolio.com
    [email protected]
    Jake Smith
    Thanks for Listening!

    View Slide