SlideShare a Scribd company logo
Iteratory
Iteracja po tablicach
$array = range(1, 5); // generuje tablicę z wartościami od 1 do 5
foreach ($array as $key => $value) {
    echo $key.' => '.$value.PHP_EOL;
}
/* wynik
0 => 1
1 => 2
2 => 3
3 => 4
4 => 5
*/
Iteracja po tablicach –
              wewnętrzny kursor
$array = range(1, 5);
current($array); // 1
next($array); // 2
current($array); // 2
next($array);
each($array); // array(2, 3)
end($array); // 5
current($array); // 5

while (list($key, $value) = each($array)) {
    echo $key .' => '.$value.PHP_EOL;
}
// 4 => 5
Iteracja po obiekcie
$object = new stdClass;
$object->key = 'value';
$object->key_2 = 'value_2';

foreach ($object as $key=>$value) {
    echo $key.' => '.$value.PHP_EOL;
}

// key => value
// key_2 => value_2
Iteracja po obiekcie – tylko
          właściwości publiczne
class foo {
    public $key = 'value';
    protected $key_2 = 'value_2';
    private $key_3 = 'value_3';
    static public $staticKey = 'value';
    static protected $staticKey_2 = 'value_2';
    static private $staticKey_3 = 'value_3';
}
$object = new foo;
foreach ($object as $key=>$value) {
    echo $key.' => '.$value.PHP_EOL;
}
// key => value
Zachowanie iteracji wg obiektu
class MyIterator implements Iterator {
private $_tab = array();
public function __construct(array $tab){
  $this->_tab = $tab;
}
public function current() {                     $object = new MyIterator(range(1,3));
  return current($this->_tab).'_MyIteration';   foreach ($object as $key=>$value) {
}                                                   echo $key.' => '.$value.PHP_EOL;
public function next() {                        }
  next($this->_tab);                            // rewind
}                                               // check_valid
public function key() {                         // 0 => 1_MyIteration
  return key($this->_tab);                      // check_valid
}                                               // 1 => 2_MyIteration
public function valid() {                       // check_valid
  echo 'check_valid' . PHP_EOL;                 // 2 => 3_MyIteration
  return key($this->_tab) !== null;             // check_valid
}
public function rewind() {
  echo 'rewind' . PHP_EOL;
  reset($this->_tab);
}
}
Iterator, IteratorAggregate oraz
                Traversable
interface Iterator implements Traversable {

     // definicja interfejsu

}

interface IteratorAggregate implements Traversable {

     // definicja interfejsu

}




•
     Grupuje dwa rodzaje iteratorów w jedno
•
     Nie może być implementowany bez Iteratora lub IteratorAggregate
Traversable jako typowany
              argument
function foo(Traversable $object) {
}

class Foo implements IteratorAggregate {
    public function getIterator() {
        return new EmptyIterator();
    }
}

foo(new ArrayIterator()); // przykładowa implementacja Iterator
foo(new Foo()); // implementacja IteratorAggregate
Kiedy używać interfejsu Iterator?
●
    Uzyskanie całkowitej kontroli nad zwracanymi
    wartościami
●
    Definiowanie własnych ścieżek poruszania po danych
●
    Generowanie danych
Kiedy używać interfejsu Iterator?
class PaginationIterator implements Iterator {
// definicja prywatnych właściwości
public function __construct($entriesLength, $entriesPerPage = 20, $activePage = 1) {
    $this->_entriesLength = (int)$entriesLength;
    $this->_entriesPerPage = (int)$entriesPerPage;
    $this->_activePage = (int)$activePage;
    $this->_maxPages = (int)ceil($this->_entriesLength / $this->_entriesPerPage);
}
public function current() {
    $object = new stdClass();
    $key = $this->_iterationIndex;
    $object->page = $key + 1;
    $object->isActive = $key === ($this->_activePage - 1);
    return $object;
}
public function next() { $this->_iterationIndex++; }
public function key() { return $this->_iterationIndex; }
public function valid() { return $this->_iterationIndex < $this->_maxPages; }
public function rewind() { $this->_iterationIndex = 0; }
}
Kiedy używać interfejsu Iterator?



$iterator = new PaginationIterator(100, 30, 1);
foreach ($iterator as $page) {
    echo 'Page: '.$page->page;
    echo ' isActive: '.var_export($page->isActive, true).PHP_EOL;
}

//   Page:   1   isActive:   true
//   Page:   2   isActive:   false
//   Page:   3   isActive:   false
//   Page:   4   isActive:   false
Kiedy używać interfejsu
         IteratorAggregate?
●
    Szybkie zwrócenie danych do iteracji
●
    Idealne we wszelkiego rodzaju klasach
    agregujących listy wartości
●
    Brak konieczności obróbki danych
Kiedy używać interfejsu
           IteratorAggregate?

class Form implements IteratorAggregate {
    private $_elements = array();

    public function addElement(FormElement $element) {
        $this->_elements[] = $element;
    }

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

class FormElement {
    public function __construct($type, $name) {
        $this->type = $type;
        $this->name = $name;
    }
}
Kiedy używać interfejsu
           IteratorAggregate?


$form = new Form();
$form->addElement(new FormElement('text', 'name'));
$form->addElement(new FormElement('test', 'surname'));

foreach ($form as $element) {
    echo 'Type: '.$element->type;
    echo ' Name: '.$element->name.PHP_EOL;
}

// Type: text Name: name
// Type: test Name: surname
SPL – Dodatkowe interfejsy
               iteratorów
     SeekableIterator
$iterator = new ArrayIterator(range(1, 5));
$seekAlready = false;

foreach ($iterator as $key => $value) {
    echo $key.' => '.$value.PHP_EOL;

      if (!$seekAlready && $key === 3) {
          $iterator->seek(1);
          $seekAlready = true;
          echo 'seek'.PHP_EOL;
      }
}
//   0 =>   1
//   1 =>   2
//   2 =>   3
//   3 =>   4
//   seek
//   2 =>   3
//   3 =>   4
//   4 =>   5
SPL – Dodatkowe interfejsy
                 iteratorów
     OuterIterator
$iterator = new AppendIterator();
$iterator->append(new ArrayIterator(range(1, 2)));
$iterator->append(new ArrayIterator(range(3, 6)));

foreach ($iterator as $key => $value) {
    echo $key.' => '.$value.' : ';
    echo $iterator->getInnerIterator()->count().PHP_EOL;
}

//   0   =>   1   :   2
//   1   =>   2   :   2
//   0   =>   3   :   4
//   1   =>   4   :   4
//   2   =>   5   :   4
//   3   =>   6   :   4
SPL – Dodatkowe interfejsy
               iteratorów
     RecursiveIterator
$array = array( 1, 2,
    array(3, 4, 5)
);
$iterator = new RecursiveArrayIterator($array);
foreach ($iterator as $key=>$value) {
    if ($iterator->hasChildren()) {
        echo 'children'.PHP_EOL;
        foreach ($iterator->getChildren() as $key => $value) {
             echo $key.' => '.$value.PHP_EOL;
        }
    } else {
        echo 'no children'.PHP_EOL;
    }
}

//   no children
//   no children
//   children
//   0 => 3
//   1 => 4
//   2 => 5
SPL – ArrayIterator
●   Wszystkie możliwości sortowania (natsort,
    usort, ksort)
●   Dostęp do wartości za pomocą []
●   Zliczanie ilości elementów
●   Dodawanie kolejnych elementów
●   Serializacja, deserializacja
SPL – RecursiveIteratorIterator
●   Iteruje rekursywnie po RecursiveIterator
●   Niezwykle potężne narzędzie do obsługi
    struktur drzewiastych oraz wszelkich
    zagnieżdżeń
●   3 tryby iteracji
    ●   LEAVES_ONLY
    ●   SELF_FIRST
    ●   CHILD_FIRST
SPL – RecursiveIteratorIterator
$array = array(
    1, 2,
    array(3, 4,
         array( 5,
              array(6, 7)
         , 8)
    , 9)
);
// domyślnie RecursiveIteratorIterator::LEAVES_ONLY
$iterator = new RecursiveArrayIterator($array);
$iterator = new RecursiveIteratorIterator($iterator);
foreach ($iterator as $key => $value) {
    echo $key.' => '.$value.' : ';
    echo $iterator->getDepth().PHP_EOL;
}

//   0   =>   1   :   0
//   1   =>   2   :   0
//   0   =>   3   :   1
//   1   =>   4   :   1
//   0   =>   5   :   2
//   0   =>   6   :   3
//   1   =>   7   :   3
//   2   =>   8   :   2
//   3   =>   9   :   1
SPL – RecursiveIteratorIterator


// LEAVES_ONLY            // SELF_FIRST             // CHILD_FIRST

//   0   =>   1   :   0   //   0   =>   1 : 0       //   0   =>   1 : 0
//   1   =>   2   :   0   //   1   =>   2 : 0       //   1   =>   2 : 0
//   0   =>   3   :   1   //   2   =>   Array : 0   //   0   =>   3 : 1
//   1   =>   4   :   1   //   0   =>   3 : 1       //   1   =>   4 : 1
//   0   =>   5   :   2   //   1   =>   4 : 1       //   0   =>   5 : 2
//   0   =>   6   :   3   //   2   =>   Array : 1   //   0   =>   6 : 3
//   1   =>   7   :   3   //   0   =>   5 : 2       //   1   =>   7 : 3
//   2   =>   8   :   2   //   1   =>   Array : 2   //   1   =>   Array : 2
//   3   =>   9   :   1   //   0   =>   6 : 3       //   2   =>   8 : 2
                          //   1   =>   7 : 3       //   2   =>   Array : 1
                          //   2   =>   8 : 2       //   3   =>   9 : 1
                          //   3   =>   9 : 1       //   2   =>   Array : 0
SPL – CallbackFilterIterator –
              od PHP 5.4


class CallbackFilterIterator extends FilterIterator {
    private $_callback;
    public function __construct(Iterator $iterator, Closure $callback) {
        parent::__construct($iterator);
        $this->_callback = $callback;
    }

    public function accept() {
        return call_user_func(
            $this->_callback,
            $this->current(),
            $this->key(),
            $this->getInnerIterator());
    }
}
SPL – CallbackFilterIterator
class Form implements IteratorAggregate {
    public function getElementsByType($type) {
        return new CallbackFilterIterator(
             $this->getIterator(),
             function($element) use ($type) {
                 return $type === $element->type;
             });
    }
}

$form = new Form();
$form->addElement(new FormElement('text', 'name'));
$form->addElement(new FormElement('number', 'age'));
$form->addElement(new FormELement('range', 'weight'));

foreach ($form->getElementsByType('text') as $element) {
    echo 'Type: '.$element->type;
    echo ' Name: '.$element->name.PHP_EOL;
}

// Type: text Name: name
SPL - AppendIterator

$form = new Form();
$form->addElement(new FormElement('text', 'name'));
$form->addElement(new FormElement('number', 'age'));
$form->addElement(new FormELement('range', 'weight'));

$iterator = new AppendIterator();
$iterator->append($form->getElementsByType('text'));
$iterator->append($form->getElementsByType('range'));

foreach ($iterator as $element) {
echo 'Type: '.$element->type;
echo ' Name: '.$element->name.PHP_EOL;
}

// Type: text Name: name
// Type: range Name: weight
SPL - DirectoryIterator
●    Rozszerza SplFileInfo – cała masa
     dobrodziejstw
$iterator = new DirectoryIterator('some_dir');
foreach ($iterator as $file) {
    echo $file->getPathName().PHP_EOL;
}

//   some_dir.
//   some_dir..
//   some_dirtest_file.txt
//   some_dirtest_file_2.txt
SPL - RegexIterator
$array = array(
    'Jabłko', 'Banan', 'Ananas', 'Wiśnia', 'Arbuz'
);
$iterator = new ArrayIterator($array);
$iterator = new RegexIterator($iterator, '/nas?/i');
foreach ($iterator as $string) {
    echo $string.PHP_EOL;
}

// Banan
// Ananas



 ●   Jest w stanie wykonywać replace, split
Wespół w zespół –
       przeszukiwanie katalogów
$iterator = new RecursiveDirectoryIterator('PHPUnit/Extensions');
$iterator = new RecursiveIteratorIterator($iterator);
$iterator = new RegexIterator($iterator, '/_coverage/i');
foreach ($iterator as $file) {
    echo $file->getPathName();
}

// PHPUnit/Extensions/SeleniumTestCase/phpunit_coverage.php
SPL – InfiniteIterator – Tasks
class TaskDownloader extends ArrayIterator {
    public function __construct() {
        // lock constructor
    }
    public function rewind() {
        $iteration = 0;
        do {
             $tasks = $this->fetch();
             if ($iteration > 0) {
                 usleep(1000);
             }
             $iteration++;
        } while ($tasks === array());
        parent::__construct($tasks);
    }
    public function fetch() {
        // fetch tasks from tasks repository
    }
}

$iterator = new InfiniteIterator(new TaskDownloader());
foreach ($iterator as $task) {
    echo $task;
}
Iteratory oszczędzają pamięć

●
    Nie potrzebują wszystkich danych od
    samego początku
●
    Są w stanie generować, pobierać dane
Pobieranie dużej ilości rekordów
class PDODataPartition extends Iterator {
    public function rewind() {
        $this->_loadPartition(0);
        $this->_position = 0;
    }
    public function valid() {
        if (isset($this->_data[$this->_position])) { return true; }
        if ($this->_position < $this->_partitionSize) { return false; }
        if ($this->_loadPartition(++$this->_partitionNum)) {
            $this->_position = 0;
            return true;
        }
        return false;
    }
    protected function _loadPartition($numOfPartition) {
        $this->_partitionNum = (int)$numOfPartition;
        $query = $this->_getPartitionQuery();
        $stmt = $this->_pdo->query($query);
        if ($stmt) { $this->_data = $stmt->fetchAll(); }
        return (bool)$this->_data;
    }
    protected function _getPartitionQuery() {
        $offset = $this->_partitionNum * $this->_partitionSize;
        $limit = $this->_partitionSize;
        return $this->_query.' LIMIT '.$limit.' OFFSET '.$offset;
    }
}
Pobieranie dużej ilości rekordów
$records = $pdo->query('SELECT * FROM tabela')->fetchAll();
foreach ($records as $record) {}
// vs

$iterator = new PDODataPartition($pdo, 'SELECT * FROM tabela', 1000);
foreach ($iterator as $record) {}




                              PDO         PDODataPartition
                 Pamięć 562 552         25 896
                    Czas 0,231 s        0,930 s




   Więcej: http://bit.ly/uGQ0Vl
Iterator w php 5.4 - Trait

trait IteratorTrait {
    protected $_data = array();
    public function next() { next($this->_data); }
    public function current() { return current($this->_data); }
    public function valid() { return key($this->_data) !== null; }
    public function key() { return key($this->_data); }
    public function rewind() { reset($this->_data); }
}

class SomeOtherClass { }

class TestIterator extends SomeOtherClass implements Iterator {
    use IteratorTrait;
    public function __construct(array $data) { $this->_data = &$data; }
}

$o = new TestIterator(range(1, 5));
foreach ($o as $key => $value) {
    echo $key.' => '.$value.PHP_EOL;
}
Kontakt

Łukasz Kużyński
Twitter: @wookiebpl
www: http://wookieb.pl
FB: http://www.facebook.com/wookieb

More Related Content

TXT
With enter
PDF
Silex al límite
PDF
Analizador sintáctico de Pascal escrito en Bison
PDF
Jquery2
PPT
Wek14 mysql 2
DOCX
Simular un next del recordset en php de forma rudimentaria
PPT
Юнит тестирование в Zend Framework 2.0
PDF
Quiz Component For Joomla
With enter
Silex al límite
Analizador sintáctico de Pascal escrito en Bison
Jquery2
Wek14 mysql 2
Simular un next del recordset en php de forma rudimentaria
Юнит тестирование в Zend Framework 2.0
Quiz Component For Joomla

What's hot (20)

PDF
Sis quiz
PDF
Testování prakticky
DOCX
Documentacion edderson callpa_ortiz
DOC
Sumahexavector
PDF
Twig, los mejores trucos y técnicas avanzadas
PDF
Aller plus loin avec Doctrine2
PDF
Practical JavaScript Programming - Session 2/8
PDF
Секреты WP_Query
DOCX
Dennis zapana perez
TXT
Index2
PDF
RxSwift 예제로 감잡기
DOC
Sumahex
PDF
BABELで、ES2015(ES6)を学ぼう!
PDF
Practical JavaScript Programming - Session 3/8
PPTX
es6.concurrency()
PDF
Як досвід компанії перетворився на фреймворк
PDF
Templating WordPress
TXT
KvZ Web Tasarım Hizmetleri
DOC
DOCX
Php codigos interfaces fredy guzman cusihunca
Sis quiz
Testování prakticky
Documentacion edderson callpa_ortiz
Sumahexavector
Twig, los mejores trucos y técnicas avanzadas
Aller plus loin avec Doctrine2
Practical JavaScript Programming - Session 2/8
Секреты WP_Query
Dennis zapana perez
Index2
RxSwift 예제로 감잡기
Sumahex
BABELで、ES2015(ES6)を学ぼう!
Practical JavaScript Programming - Session 3/8
es6.concurrency()
Як досвід компанії перетворився на фреймворк
Templating WordPress
KvZ Web Tasarım Hizmetleri
Php codigos interfaces fredy guzman cusihunca
Ad

Viewers also liked (8)

PDF
PDF
Wzorce projektowe
PDF
BDD in PHP - Behat
PDF
Callbacks, promises, generators - asynchronous javascript
PPT
React js
PPTX
React + Redux Introduction
PDF
React JS and why it's awesome
Wzorce projektowe
BDD in PHP - Behat
Callbacks, promises, generators - asynchronous javascript
React js
React + Redux Introduction
React JS and why it's awesome
Ad

Iteratory

  • 2. Iteracja po tablicach $array = range(1, 5); // generuje tablicę z wartościami od 1 do 5 foreach ($array as $key => $value) { echo $key.' => '.$value.PHP_EOL; } /* wynik 0 => 1 1 => 2 2 => 3 3 => 4 4 => 5 */
  • 3. Iteracja po tablicach – wewnętrzny kursor $array = range(1, 5); current($array); // 1 next($array); // 2 current($array); // 2 next($array); each($array); // array(2, 3) end($array); // 5 current($array); // 5 while (list($key, $value) = each($array)) { echo $key .' => '.$value.PHP_EOL; } // 4 => 5
  • 4. Iteracja po obiekcie $object = new stdClass; $object->key = 'value'; $object->key_2 = 'value_2'; foreach ($object as $key=>$value) { echo $key.' => '.$value.PHP_EOL; } // key => value // key_2 => value_2
  • 5. Iteracja po obiekcie – tylko właściwości publiczne class foo { public $key = 'value'; protected $key_2 = 'value_2'; private $key_3 = 'value_3'; static public $staticKey = 'value'; static protected $staticKey_2 = 'value_2'; static private $staticKey_3 = 'value_3'; } $object = new foo; foreach ($object as $key=>$value) { echo $key.' => '.$value.PHP_EOL; } // key => value
  • 6. Zachowanie iteracji wg obiektu class MyIterator implements Iterator { private $_tab = array(); public function __construct(array $tab){ $this->_tab = $tab; } public function current() { $object = new MyIterator(range(1,3)); return current($this->_tab).'_MyIteration'; foreach ($object as $key=>$value) { } echo $key.' => '.$value.PHP_EOL; public function next() { } next($this->_tab); // rewind } // check_valid public function key() { // 0 => 1_MyIteration return key($this->_tab); // check_valid } // 1 => 2_MyIteration public function valid() { // check_valid echo 'check_valid' . PHP_EOL; // 2 => 3_MyIteration return key($this->_tab) !== null; // check_valid } public function rewind() { echo 'rewind' . PHP_EOL; reset($this->_tab); } }
  • 7. Iterator, IteratorAggregate oraz Traversable interface Iterator implements Traversable { // definicja interfejsu } interface IteratorAggregate implements Traversable { // definicja interfejsu } • Grupuje dwa rodzaje iteratorów w jedno • Nie może być implementowany bez Iteratora lub IteratorAggregate
  • 8. Traversable jako typowany argument function foo(Traversable $object) { } class Foo implements IteratorAggregate { public function getIterator() { return new EmptyIterator(); } } foo(new ArrayIterator()); // przykładowa implementacja Iterator foo(new Foo()); // implementacja IteratorAggregate
  • 9. Kiedy używać interfejsu Iterator? ● Uzyskanie całkowitej kontroli nad zwracanymi wartościami ● Definiowanie własnych ścieżek poruszania po danych ● Generowanie danych
  • 10. Kiedy używać interfejsu Iterator? class PaginationIterator implements Iterator { // definicja prywatnych właściwości public function __construct($entriesLength, $entriesPerPage = 20, $activePage = 1) { $this->_entriesLength = (int)$entriesLength; $this->_entriesPerPage = (int)$entriesPerPage; $this->_activePage = (int)$activePage; $this->_maxPages = (int)ceil($this->_entriesLength / $this->_entriesPerPage); } public function current() { $object = new stdClass(); $key = $this->_iterationIndex; $object->page = $key + 1; $object->isActive = $key === ($this->_activePage - 1); return $object; } public function next() { $this->_iterationIndex++; } public function key() { return $this->_iterationIndex; } public function valid() { return $this->_iterationIndex < $this->_maxPages; } public function rewind() { $this->_iterationIndex = 0; } }
  • 11. Kiedy używać interfejsu Iterator? $iterator = new PaginationIterator(100, 30, 1); foreach ($iterator as $page) { echo 'Page: '.$page->page; echo ' isActive: '.var_export($page->isActive, true).PHP_EOL; } // Page: 1 isActive: true // Page: 2 isActive: false // Page: 3 isActive: false // Page: 4 isActive: false
  • 12. Kiedy używać interfejsu IteratorAggregate? ● Szybkie zwrócenie danych do iteracji ● Idealne we wszelkiego rodzaju klasach agregujących listy wartości ● Brak konieczności obróbki danych
  • 13. Kiedy używać interfejsu IteratorAggregate? class Form implements IteratorAggregate { private $_elements = array(); public function addElement(FormElement $element) { $this->_elements[] = $element; } public function getIterator() { return new ArrayIterator($this->_elements); } } class FormElement { public function __construct($type, $name) { $this->type = $type; $this->name = $name; } }
  • 14. Kiedy używać interfejsu IteratorAggregate? $form = new Form(); $form->addElement(new FormElement('text', 'name')); $form->addElement(new FormElement('test', 'surname')); foreach ($form as $element) { echo 'Type: '.$element->type; echo ' Name: '.$element->name.PHP_EOL; } // Type: text Name: name // Type: test Name: surname
  • 15. SPL – Dodatkowe interfejsy iteratorów SeekableIterator $iterator = new ArrayIterator(range(1, 5)); $seekAlready = false; foreach ($iterator as $key => $value) { echo $key.' => '.$value.PHP_EOL; if (!$seekAlready && $key === 3) { $iterator->seek(1); $seekAlready = true; echo 'seek'.PHP_EOL; } } // 0 => 1 // 1 => 2 // 2 => 3 // 3 => 4 // seek // 2 => 3 // 3 => 4 // 4 => 5
  • 16. SPL – Dodatkowe interfejsy iteratorów OuterIterator $iterator = new AppendIterator(); $iterator->append(new ArrayIterator(range(1, 2))); $iterator->append(new ArrayIterator(range(3, 6))); foreach ($iterator as $key => $value) { echo $key.' => '.$value.' : '; echo $iterator->getInnerIterator()->count().PHP_EOL; } // 0 => 1 : 2 // 1 => 2 : 2 // 0 => 3 : 4 // 1 => 4 : 4 // 2 => 5 : 4 // 3 => 6 : 4
  • 17. SPL – Dodatkowe interfejsy iteratorów RecursiveIterator $array = array( 1, 2, array(3, 4, 5) ); $iterator = new RecursiveArrayIterator($array); foreach ($iterator as $key=>$value) { if ($iterator->hasChildren()) { echo 'children'.PHP_EOL; foreach ($iterator->getChildren() as $key => $value) { echo $key.' => '.$value.PHP_EOL; } } else { echo 'no children'.PHP_EOL; } } // no children // no children // children // 0 => 3 // 1 => 4 // 2 => 5
  • 18. SPL – ArrayIterator ● Wszystkie możliwości sortowania (natsort, usort, ksort) ● Dostęp do wartości za pomocą [] ● Zliczanie ilości elementów ● Dodawanie kolejnych elementów ● Serializacja, deserializacja
  • 19. SPL – RecursiveIteratorIterator ● Iteruje rekursywnie po RecursiveIterator ● Niezwykle potężne narzędzie do obsługi struktur drzewiastych oraz wszelkich zagnieżdżeń ● 3 tryby iteracji ● LEAVES_ONLY ● SELF_FIRST ● CHILD_FIRST
  • 20. SPL – RecursiveIteratorIterator $array = array( 1, 2, array(3, 4, array( 5, array(6, 7) , 8) , 9) ); // domyślnie RecursiveIteratorIterator::LEAVES_ONLY $iterator = new RecursiveArrayIterator($array); $iterator = new RecursiveIteratorIterator($iterator); foreach ($iterator as $key => $value) { echo $key.' => '.$value.' : '; echo $iterator->getDepth().PHP_EOL; } // 0 => 1 : 0 // 1 => 2 : 0 // 0 => 3 : 1 // 1 => 4 : 1 // 0 => 5 : 2 // 0 => 6 : 3 // 1 => 7 : 3 // 2 => 8 : 2 // 3 => 9 : 1
  • 21. SPL – RecursiveIteratorIterator // LEAVES_ONLY // SELF_FIRST // CHILD_FIRST // 0 => 1 : 0 // 0 => 1 : 0 // 0 => 1 : 0 // 1 => 2 : 0 // 1 => 2 : 0 // 1 => 2 : 0 // 0 => 3 : 1 // 2 => Array : 0 // 0 => 3 : 1 // 1 => 4 : 1 // 0 => 3 : 1 // 1 => 4 : 1 // 0 => 5 : 2 // 1 => 4 : 1 // 0 => 5 : 2 // 0 => 6 : 3 // 2 => Array : 1 // 0 => 6 : 3 // 1 => 7 : 3 // 0 => 5 : 2 // 1 => 7 : 3 // 2 => 8 : 2 // 1 => Array : 2 // 1 => Array : 2 // 3 => 9 : 1 // 0 => 6 : 3 // 2 => 8 : 2 // 1 => 7 : 3 // 2 => Array : 1 // 2 => 8 : 2 // 3 => 9 : 1 // 3 => 9 : 1 // 2 => Array : 0
  • 22. SPL – CallbackFilterIterator – od PHP 5.4 class CallbackFilterIterator extends FilterIterator { private $_callback; public function __construct(Iterator $iterator, Closure $callback) { parent::__construct($iterator); $this->_callback = $callback; } public function accept() { return call_user_func( $this->_callback, $this->current(), $this->key(), $this->getInnerIterator()); } }
  • 23. SPL – CallbackFilterIterator class Form implements IteratorAggregate { public function getElementsByType($type) { return new CallbackFilterIterator( $this->getIterator(), function($element) use ($type) { return $type === $element->type; }); } } $form = new Form(); $form->addElement(new FormElement('text', 'name')); $form->addElement(new FormElement('number', 'age')); $form->addElement(new FormELement('range', 'weight')); foreach ($form->getElementsByType('text') as $element) { echo 'Type: '.$element->type; echo ' Name: '.$element->name.PHP_EOL; } // Type: text Name: name
  • 24. SPL - AppendIterator $form = new Form(); $form->addElement(new FormElement('text', 'name')); $form->addElement(new FormElement('number', 'age')); $form->addElement(new FormELement('range', 'weight')); $iterator = new AppendIterator(); $iterator->append($form->getElementsByType('text')); $iterator->append($form->getElementsByType('range')); foreach ($iterator as $element) { echo 'Type: '.$element->type; echo ' Name: '.$element->name.PHP_EOL; } // Type: text Name: name // Type: range Name: weight
  • 25. SPL - DirectoryIterator ● Rozszerza SplFileInfo – cała masa dobrodziejstw $iterator = new DirectoryIterator('some_dir'); foreach ($iterator as $file) { echo $file->getPathName().PHP_EOL; } // some_dir. // some_dir.. // some_dirtest_file.txt // some_dirtest_file_2.txt
  • 26. SPL - RegexIterator $array = array( 'Jabłko', 'Banan', 'Ananas', 'Wiśnia', 'Arbuz' ); $iterator = new ArrayIterator($array); $iterator = new RegexIterator($iterator, '/nas?/i'); foreach ($iterator as $string) { echo $string.PHP_EOL; } // Banan // Ananas ● Jest w stanie wykonywać replace, split
  • 27. Wespół w zespół – przeszukiwanie katalogów $iterator = new RecursiveDirectoryIterator('PHPUnit/Extensions'); $iterator = new RecursiveIteratorIterator($iterator); $iterator = new RegexIterator($iterator, '/_coverage/i'); foreach ($iterator as $file) { echo $file->getPathName(); } // PHPUnit/Extensions/SeleniumTestCase/phpunit_coverage.php
  • 28. SPL – InfiniteIterator – Tasks class TaskDownloader extends ArrayIterator { public function __construct() { // lock constructor } public function rewind() { $iteration = 0; do { $tasks = $this->fetch(); if ($iteration > 0) { usleep(1000); } $iteration++; } while ($tasks === array()); parent::__construct($tasks); } public function fetch() { // fetch tasks from tasks repository } } $iterator = new InfiniteIterator(new TaskDownloader()); foreach ($iterator as $task) { echo $task; }
  • 29. Iteratory oszczędzają pamięć ● Nie potrzebują wszystkich danych od samego początku ● Są w stanie generować, pobierać dane
  • 30. Pobieranie dużej ilości rekordów class PDODataPartition extends Iterator { public function rewind() { $this->_loadPartition(0); $this->_position = 0; } public function valid() { if (isset($this->_data[$this->_position])) { return true; } if ($this->_position < $this->_partitionSize) { return false; } if ($this->_loadPartition(++$this->_partitionNum)) { $this->_position = 0; return true; } return false; } protected function _loadPartition($numOfPartition) { $this->_partitionNum = (int)$numOfPartition; $query = $this->_getPartitionQuery(); $stmt = $this->_pdo->query($query); if ($stmt) { $this->_data = $stmt->fetchAll(); } return (bool)$this->_data; } protected function _getPartitionQuery() { $offset = $this->_partitionNum * $this->_partitionSize; $limit = $this->_partitionSize; return $this->_query.' LIMIT '.$limit.' OFFSET '.$offset; } }
  • 31. Pobieranie dużej ilości rekordów $records = $pdo->query('SELECT * FROM tabela')->fetchAll(); foreach ($records as $record) {} // vs $iterator = new PDODataPartition($pdo, 'SELECT * FROM tabela', 1000); foreach ($iterator as $record) {} PDO PDODataPartition Pamięć 562 552 25 896 Czas 0,231 s 0,930 s Więcej: http://bit.ly/uGQ0Vl
  • 32. Iterator w php 5.4 - Trait trait IteratorTrait { protected $_data = array(); public function next() { next($this->_data); } public function current() { return current($this->_data); } public function valid() { return key($this->_data) !== null; } public function key() { return key($this->_data); } public function rewind() { reset($this->_data); } } class SomeOtherClass { } class TestIterator extends SomeOtherClass implements Iterator { use IteratorTrait; public function __construct(array $data) { $this->_data = &$data; } } $o = new TestIterator(range(1, 5)); foreach ($o as $key => $value) { echo $key.' => '.$value.PHP_EOL; }
  • 33. Kontakt Łukasz Kużyński Twitter: @wookiebpl www: http://wookieb.pl FB: http://www.facebook.com/wookieb