Advertisement
Advertisement

More Related Content

Advertisement
Advertisement

Looping the Loop with SPL Iterators

  1. Looping the Loop with SPL Iterators
  2. Looping the Loop with SPL Iterators What is an Iterator? An Iterator is an object that enables a programmer to traverse a container, particularly lists.
  3. Looping the Loop with SPL Iterators What is an Iterator? $dataSet = ['A', 'B', 'C']; foreach($dataSet as $key => $value) { echo "{$key} => {$value}", PHP_EOL; }
  4. Looping the Loop with SPL Iterators What is an Iterator? 0 => A 1 => B 2 => C
  5. Looping the Loop with SPL Iterators What is an Iterator? $data = ['A', 'B', 'C']; $dataSet = new ArrayIterator($data); foreach($dataSet as $key => $value) { echo "{$key} => {$value}", PHP_EOL; }
  6. Looping the Loop with SPL Iterators What is an Iterator? 0 => A 1 => B 2 => C
  7. Looping the Loop with SPL Iterators What is an Iterator? interface Iterator extends Traversable { /* Methods */ abstract public current ( void ) : mixed abstract public key ( void ) : scalar abstract public next ( void ) : void abstract public rewind ( void ) : void abstract public valid ( void ) : bool }
  8. Looping the Loop with SPL Iterators What is an Iterator? $data = ['A', 'B', 'C’]; $iterator = new ArrayIterator($data); $iterator->rewind(); while ($iterator->valid()) { $key = $iterator->key(); $value = $iterator->current(); echo "{$key} => {$value}", PHP_EOL; $iterator->next(); }
  9. Looping the Loop with SPL Iterators What is an Iterator? 0 => A 1 => B 2 => C
  10. Looping the Loop with SPL Iterators The Iterable Tree iterable array Traversable Iterator Generator IteratorAggregate
  11. Looping the Loop with SPL Iterators The Iterable Tree Not all iterables are equal You can count the elements in an array ! Can you count the elements in an Iterator?
  12. Looping the Loop with SPL Iterators The Iterable Tree Not all iterables are equal You can access the elements of an array by their index ! Can you access the elements of an Iterator by index ?
  13. Looping the Loop with SPL Iterators The Iterable Tree Not all iterables are equal You can rewind an Iterator ! Can you rewind a Generator ?
  14. Looping the Loop with SPL Iterators The Iterable Tree Not all iterables are equal Iterator_* functions (e.g. iterator_to_array) work on Iterators ? Can you use iterator_* functions on an IteratorAggregate ?
  15. Looping the Loop with SPL Iterators
  16. Looping the Loop with SPL Iterators class UserRepository { // ... public function all(): array { $userQuery = 'SELECT * FROM `users` ...'; $statement = $this->pdo->prepare($userQuery); $statement->execute(); $users = $statement->fetchAll(); return array_map(fn(array $user): User => User::fromArray($user), $users); } }
  17. Looping the Loop with SPL Iterators class UserRepository { // ... /** * @return User[] */ public function all(): array { $userQuery = 'SELECT * FROM `users` ...'; $statement = $this->pdo->prepare($userQuery); $statement->execute(); $users = $statement->fetchAll(); return array_map(fn(array $user): User => User::fromArray($user), $users); } }
  18. Looping the Loop with SPL Iterators class UserList extends ArrayIterator { }
  19. Looping the Loop with SPL Iterators ArrayIterator Implements: Countable ArrayAccess Serializable SeekableIterator (which entends Iterator)
  20. Looping the Loop with SPL Iterators class UserRepository { // ... public function all(): UserList { $userQuery = 'SELECT * FROM `users` ...'; $statement = $this->pdo->prepare($userQuery); $statement->execute(); $users = $statement->fetchAll(); return new UserList( array_map(fn(array $user): User => User::fromArray($user), $users) ); } }
  21. Looping the Loop with SPL Iterators ArrayIterator Implements: Countable
  22. Looping the Loop with SPL Iterators ArrayIterator – Countable $userData = ['user1', 'user2', 'user3', 'user4']; $userList = new UserList($userData); $userCount = count($userList); echo "There are {$userCount} users in this list", PHP_EOL;
  23. Looping the Loop with SPL Iterators ArrayIterator – Countable $userData = ['user1', 'user2', 'user3', 'user4']; $userList = new UserList($userData); echo "There are {$userList->count()} users in this list", PHP_EOL;
  24. Looping the Loop with SPL Iterators ArrayIterator – Countable There are 4 users in this list
  25. Looping the Loop with SPL Iterators ArrayIterator Implements: Countable ArrayAccess
  26. Looping the Loop with SPL Iterators ArrayIterator – ArrayAccess $userData = ['user1', 'user2', 'user3', 'user4']; $userList = new UserList($userData); echo "The 3rd entry in the list is {$userList[2]}", PHP_EOL;
  27. Looping the Loop with SPL Iterators ArrayIterator – ArrayAccess The 3rd entry in the list is user3
  28. Looping the Loop with SPL Iterators ArrayIterator Implements: Countable ArrayAccess Serializable
  29. Looping the Loop with SPL Iterators ArrayIterator – Serializable $userData = ['user1', 'user2', 'user3', 'user4']; $userList = new UserList($userData); var_dump(serialize($userList));
  30. Looping the Loop with SPL Iterators ArrayIterator – Serializable string(117) "O:8:"UserList":4:{i:0;i:0;i:1;a:4:{i:0;s:5:"user1"; i:1;s:5:"user2";i:2;s:5:"user3";i:3;s:5:"user4";}i:2; a:0:{}i:3;N;}"
  31. Looping the Loop with SPL Iterators ArrayIterator Implements: Countable ArrayAccess Serializable SeekableIterator (which entends Iterator)
  32. Looping the Loop with SPL Iterators ArrayIterator – SeekableIterator $userData = ['user1', 'user2', 'user3', 'user4']; $userList = new UserList($userData); $userList->seek(2); while ($userList->valid()) { echo $userList->current(), PHP_EOL; $userList->next(); }
  33. Looping the Loop with SPL Iterators ArrayIterator – SeekableIterator user3 user4
  34. Looping the Loop with SPL Iterators ArrayIterator Implements: Countable ArrayAccess Serializable SeekableIterator (which entends Iterator) Also provides methods for sorting Doesn’t work with array_* functions
  35. Looping the Loop with SPL Iterators
  36. Looping the Loop with SPL Iterators
  37. Looping the Loop with SPL Iterators LimitIterator $userData = ['user1', 'user2', 'user3', 'user4']; $userList = new LimitIterator( new UserList($userData), 2 ); foreach($userList as $value) { echo $value, PHP_EOL; }
  38. Looping the Loop with SPL Iterators LimitIterator user3 user4
  39. Looping the Loop with SPL Iterators InfiniteIterator $weekdayNames = ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat']; $todayOffset = (int) (new DateTime('2020-09-08'))->format('w'); $workdayList = new LimitIterator( new InfiniteIterator( new ArrayIterator($weekdayNames) ), $todayOffset ); $counter = 0; foreach($workdayList as $dayOfWeek) { echo $dayOfWeek, PHP_EOL; if (++$counter === 14) break; }
  40. Looping the Loop with SPL Iterators InfiniteIterator Tues Wed Thurs Fri Sat Sun Mon Tues Wed Thurs Fri Sat Sun Mon
  41. Looping the Loop with SPL Iterators CallbackFilterIterator $weekdayNames = ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat']; $todayOffset = (int) (new DateTime('2020-09-08'))->format('w'); $workdayList = new LimitIterator( new CallbackFilterIterator( new InfiniteIterator( new ArrayIterator($weekdayNames) ), fn($dayName): bool => $dayName !== 'Sat' && $dayName !== 'Sun' ), $todayOffset – 1 ); $counter = 0; foreach($workdayList as $dayOfWeek) { echo $dayOfWeek, PHP_EOL; if (++$counter === 10) break; }
  42. Looping the Loop with SPL Iterators CallbackFilterIterator Tues Wed Thurs Fri Mon Tues Wed Thurs Fri Mon
  43. Looping the Loop with SPL Iterators
  44. Looping the Loop with SPL Iterators class UserRepository { // ... public function all(): UserList { $userQuery = 'SELECT * FROM `users` ...'; $statement = $this->pdo->prepare($userQuery); $statement->execute(); $users = $statement->fetchAll(); return new UserList( array_map(fn(array $user): User => User::fromArray($user), $users) ); } }
  45. Looping the Loop with SPL Iterators class UserRepository { // ... public function all(): Generator { $userQuery = 'SELECT * FROM `users` ...'; $statement = $this->pdo->prepare($userQuery); $statement->execute(); while ($user = $statement->fetch()) { yield User::fromArray($user); } } }
  46. Looping the Loop with SPL Iterators class UserRepository { // ... /** * @return Generator|User[] */ public function all(): Generator { $userQuery = 'SELECT * FROM `users` ...'; $statement = $this->pdo->prepare($userQuery); $statement->execute(); while ($user = $statement->fetch()) { yield User::fromArray($user); } } }
  47. Looping the Loop with SPL Iterators class UserList implements IteratorAggregate { private PDOStatement $pdoStatement; public function __construct(PDOStatement $pdoStatement) { $this->pdoStatement = $pdoStatement; } public function getIterator(): Traversable { $statement->execute(); while ($user = $this->pdoStatement->fetch()) { yield User::fromArray($user); } } }
  48. Looping the Loop with SPL Iterators class UserRepository { // ... public function all(): UserList { $userQuery = 'SELECT * FROM `users` ...'; $statement = $this->pdo->prepare($userQuery); return new UserList($statement); } }
  49. Looping the Loop with SPL Iterators
  50. Looping the Loop with SPL Iterators A Functional Guide to Cat Herding with PHP Generators https://markbakeruk.net/2016/01/19/a-functional-guide-to-cat- herding-with-php-generators/
  51. Looping the Loop with SPL Iterators Filtering and Mapping with SPL Iterators https://markbakeruk.net/2020/01/05/filtering-and-mapping-with- spl-iterators/
  52. Looping the Loop with SPL Iterators Parallel Looping in PHP with SPL’s MultipleIterator https://markbakeruk.net/2019/12/31/parallel-looping-in-php-with- spls-multipleiterator/
  53. Looping the Loop with SPL Iterators Iterating PHP Iterators By Cal Evans https://leanpub.com/iteratingphpiterators
  54. Looping the Loop with SPL Iterators Mastering the SPL Library by Joshua Thijssen https://www.phparch.com/books/mastering-the-spl-library/
  55. Who am I? Mark Baker Senior Software Engineer MessageBird BV, Amsterdam Coordinator and Developer of: Open Source PHPOffice library PHPExcel, PHPWord, PHPPowerPoint, PHPProject, PHPVisio Minor contributor to PHP core (SPL Datastructures) Other small open source libraries available on github @Mark_Baker https://github.com/MarkBaker http://uk.linkedin.com/pub/mark-baker/b/572/171 http://markbakeruk.net
Advertisement