SlideShare a Scribd company logo
1 of 33
Download to read offline
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

What's hot

Documentacion edderson callpa_ortiz
Documentacion edderson callpa_ortizDocumentacion edderson callpa_ortiz
Documentacion edderson callpa_ortizEdderson J. Ortiz
 
Sumahexavector
SumahexavectorSumahexavector
Sumahexavectorjbersosa
 
Twig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasTwig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasJavier Eguiluz
 
Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2André Tapia
 
Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8Wilson Su
 
Dennis zapana perez
Dennis zapana perezDennis zapana perez
Dennis zapana perezdennis_elvis
 
RxSwift 예제로 감잡기
RxSwift 예제로 감잡기RxSwift 예제로 감잡기
RxSwift 예제로 감잡기Yongha Yoo
 
BABELで、ES2015(ES6)を学ぼう!
BABELで、ES2015(ES6)を学ぼう!BABELで、ES2015(ES6)を学ぼう!
BABELで、ES2015(ES6)を学ぼう!Toshio Ehara
 
Practical JavaScript Programming - Session 3/8
Practical JavaScript Programming - Session 3/8Practical JavaScript Programming - Session 3/8
Practical JavaScript Programming - Session 3/8Wilson Su
 
Як досвід компанії перетворився на фреймворк
Як досвід компанії перетворився на фреймворкЯк досвід компанії перетворився на фреймворк
Як досвід компанії перетворився на фреймворкShtrih Sruleg
 
KvZ Web Tasarım Hizmetleri
KvZ Web Tasarım HizmetleriKvZ Web Tasarım Hizmetleri
KvZ Web Tasarım HizmetleriAhmet Öztaş
 
Php codigos interfaces fredy guzman cusihunca
Php codigos interfaces   fredy guzman cusihuncaPhp codigos interfaces   fredy guzman cusihunca
Php codigos interfaces fredy guzman cusihuncaTigger_Fred
 

What's hot (20)

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

Viewers also liked

Viewers also liked (8)

React.js
React.jsReact.js
React.js
 
Wzorce projektowe
Wzorce projektowe Wzorce projektowe
Wzorce projektowe
 
BDD in PHP - Behat
BDD in PHP - BehatBDD in PHP - Behat
BDD in PHP - Behat
 
Callbacks, promises, generators - asynchronous javascript
Callbacks, promises, generators - asynchronous javascriptCallbacks, promises, generators - asynchronous javascript
Callbacks, promises, generators - asynchronous javascript
 
Flux
FluxFlux
Flux
 
React js
React jsReact js
React js
 
React + Redux Introduction
React + Redux IntroductionReact + Redux Introduction
React + Redux Introduction
 
React JS and why it's awesome
React JS and why it's awesomeReact JS and why it's awesome
React JS and why it's awesome
 

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