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

    View full-size slide

  2. http://bitly.com/wNwg6N

    View full-size 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 full-size 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 full-size slide

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

    View full-size slide

  6. Where are Iterators
    Used?

    View full-size slide

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

    View full-size slide

  8. Everyone Loves
    Iterators

    View full-size slide

  9. Everyone Loves
    Iterators
    Have you used SimpleXML?

    View full-size slide

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

    View full-size 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 full-size 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 full-size slide

  13. Defining an Iterator

    View full-size slide

  14. Iterator Interfaces

    View full-size slide

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

    View full-size 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 full-size 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 full-size slide

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

    View full-size 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 full-size slide

  20. Iterator Basics

    View full-size slide

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

    View full-size slide

  22. Iterator Aggregate
    Iterator Aggregate
    Iterator

    View full-size slide

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

    View full-size slide

  24. Outer Iterator
    Outer Iterator
    Inner
    Iterator

    View full-size slide

  25. Outer Iterator
    Outer Iterator
    Inner
    Iterator

    View full-size slide

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

    View full-size slide

  27. Recursive
    Iterator
    Recursive Iterator
    Get Children

    View full-size slide

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

    View full-size slide

  29. Recursive Iterators

    View full-size 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 full-size 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 full-size 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 full-size slide

  33. 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 full-size slide

  34. $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 full-size 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
    title: how to work with iterators
    title: introduction to iterators
    email: [email protected]
    title: extending iterators
    email: [email protected]

    View full-size slide

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

    View full-size slide

  37. 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 full-size slide

  38. $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 full-size 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

    Home
    About

    Careers
    Contact

    Location
    FAQ

    View full-size slide

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

    View full-size slide

  41. $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 full-size slide

  42. Directory Iterator

    View full-size slide

  43. $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 full-size 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
    .
    ..
    aura
    autoload.php
    bin
    composer
    monolog
    psr
    robmorgan
    slim
    slimcontroller
    symfony
    vlucas

    View full-size slide

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

    View full-size slide

  46. Filesystem Iterator

    View full-size slide

  47. 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 full-size slide

  48. Glob Iterator

    View full-size slide

  49. $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 full-size 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
    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 full-size slide

  51. $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 full-size 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
    \-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 full-size slide

  53. Filter Iterator

    View full-size slide

  54. 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 full-size slide

  55. 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 full-size slide

  56. 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 full-size slide

  57. 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 full-size slide

  58. $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 full-size slide

  59. $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 full-size slide

  60. Regex Iterator

    View full-size slide

  61. /* 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 full-size 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
    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 full-size slide

  63. Parent Iterator

    View full-size slide

  64. 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 full-size slide

  65. Limit Iterator

    View full-size slide

  66. 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 full-size slide

  67. $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 full-size 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
    Jake Smith
    Steve Austin
    Steven Rogers

    View full-size 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);
    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 full-size 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
    Error: Cannot seek to 20 which is behind offset 0 plus count 3

    View full-size slide

  71. Callback Filter
    Iterator

    View full-size slide

  72. 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 full-size slide

  73. $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 full-size 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
    /recursive_cache.php
    /recursive_it.php

    View full-size slide

  75. Caching Iterator

    View full-size slide

  76. 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 full-size slide

  77. $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 full-size 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
    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 full-size slide

  79. 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 full-size slide

  80. 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 full-size slide

  81. 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 full-size slide

  82. 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 full-size slide

  83. 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 full-size slide

  84. 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 full-size slide

  85. 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 full-size slide

  86. 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 full-size slide

  87. 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 full-size slide

  88. 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 full-size slide

  89. 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 full-size slide

  90. 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 full-size 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
    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 full-size slide

  92. Other Iterators

    View full-size slide

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

    View full-size slide

  94. Iterator Functions

    View full-size slide

  95. 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 full-size slide

  96. Questions?
    Concerns?
    Complaints?

    View full-size slide

  97. https://joind.in/12807

    View full-size slide

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

    View full-size slide