Upgrade to Pro — share decks privately, control downloads, hide ads and more …

(Re)discovering the SPL

Joshua Thijssen
October 13, 2014
140

(Re)discovering the SPL

Joshua Thijssen

October 13, 2014
Tweet

Transcript

  1. 1
    Joshua Thijssen
    jaytaph
    (Re)discovering the SPL

    View full-size slide

  2. 2
    Joshua Thijssen
    Freelance consultant and trainer @ TechAdemy
    Founder of TechAnalyze.io
    Founder of the Dutch Web Alliance
    Blog: http://adayinthelifeof.nl
    Email: [email protected]
    Twitter: @jaytaph

    View full-size slide

  3. 3
    Tech nalyze
    WWW.TECHANALYZE.IO
    Your free credit voucher code:
    ohthehorror

    View full-size slide

  4. 4
    Q: Have you ever used the SPL?

    View full-size slide

  5. 5
    Q: Have you ever used the SPL
    without going nuts?

    View full-size slide

  6. 6
    SPL Documentation

    View full-size slide

  7. 6
    SPL Documentation
    http://www.php.net/spl

    View full-size slide

  8. ➡ Not enough documentation.
    9

    View full-size slide

  9. ➡ Not enough documentation.
    ➡ Very few examples.
    9

    View full-size slide

  10. ➡ Not enough documentation.
    ➡ Very few examples.
    ➡ Wrong / missing in some cases.
    9

    View full-size slide

  11. ➡ Interfaces
    ➡ Iterators
    ➡ Data structures
    ➡ Exceptions
    ➡ Miscellaneous functionality
    10

    View full-size slide

  12. 11
    Don’t get scared!
    The SPL is awesomesauce!

    View full-size slide

  13. 12
    INTERFACES

    View full-size slide

  14. 13
    Traversable
    (not an “spl interface”)

    View full-size slide

  15. ➡ Traversable cannot be implemented*
    14

    View full-size slide

  16. ➡ Traversable cannot be implemented*
    ➡ Traversable can be detected (instanceof).
    14

    View full-size slide

  17. ➡ Traversable cannot be implemented*
    ➡ Traversable can be detected (instanceof).
    ➡ foreach() detects traversable interfaces and
    does magic things.
    14

    View full-size slide

  18. 15
    Iterator
    (still not an “spl interface”)

    View full-size slide

  19. Userland interface to make
    an object traversable
    16

    View full-size slide

  20. 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 )
    }
    17
    Iterator interface:

    View full-size slide

  21. ➡ Iterator
    18

    View full-size slide

  22. ➡ Iterator
    ➡ FilterIterators
    18

    View full-size slide

  23. ➡ Iterator
    ➡ FilterIterators
    ➡ “Chains” iterators together
    18

    View full-size slide

  24. ➡ Iterator
    ➡ FilterIterators
    ➡ “Chains” iterators together
    ➡ IteratorAggregate
    18

    View full-size slide

  25. ➡ Iterator
    ➡ FilterIterators
    ➡ “Chains” iterators together
    ➡ IteratorAggregate
    ➡ Is not an iterator, but HAS an iterator
    18

    View full-size slide

  26. 1 $dir = opendir(".");
    2 while (($file = readdir($dir)) !== false) {
    3
    4 # Business logic happens here
    5 print "file: $file\n";
    6
    7 }
    19

    View full-size slide

  27. 1 $dir = opendir(".");
    2 while (($file = readdir($dir)) !== false) {
    3
    4 # hack: filter only mp3 files
    5 if (! preg_match('|\.mp3$|i', $file)) {
    6 continue;
    7 }
    8
    9 # Business logic happens here
    10 print "file: $file\n";
    11 }
    20

    View full-size slide

  28. ➡ Filter all MP3 and all JPG files.
    21

    View full-size slide

  29. ➡ Filter all MP3 and all JPG files.
    ➡ Filter all MP3 files that are larger than
    6MB.
    21

    View full-size slide

  30. ➡ Filter all MP3 and all JPG files.
    ➡ Filter all MP3 files that are larger than
    6MB.
    ➡ Do not filter at all.
    21

    View full-size slide

  31. ➡ Filter all MP3 and all JPG files.
    ➡ Filter all MP3 files that are larger than
    6MB.
    ➡ Do not filter at all.
    ➡ Search sub-directories as well.
    21

    View full-size slide

  32. ➡ Filter all MP3 and all JPG files.
    ➡ Filter all MP3 files that are larger than
    6MB.
    ➡ Do not filter at all.
    ➡ Search sub-directories as well.
    ➡ Search multiple directories.
    21

    View full-size slide

  33. ➡ How to test? (we can’t)
    22

    View full-size slide

  34. ➡ How to test? (we can’t)
    ➡ How to maintain? (we can’t)
    22

    View full-size slide

  35. ➡ How to test? (we can’t)
    ➡ How to maintain? (we can’t)
    ➡ How to reuse? (we can’t)
    22

    View full-size slide

  36. 1 $it = new DirectoryIterator(".");
    2 foreach ($it as $fi) {
    3 print "File: ".$fi->getPathname()."\n";
    4 }
    23

    View full-size slide

  37. 1 $it = new DirectoryIterator(".");
    2 $it2 = new RegexIterator($it, "/\.mp3$/i");
    3 foreach ($it2 as $fi) {
    4 print "File: ".$fi->getPathname()."\n";
    5 }
    24

    View full-size slide

  38. 1 $it = new DirectoryIterator(".");
    2 $it2 = new RegexIterator($it, "/\.mp3$/i");
    3 $it3 = new FilesizeIterator($it2, 0, 6 * 1024 * 1024);
    4 $it4 = new LimitIterator($it3, 10, 5);
    5
    6 foreach ($it4 as $fi) {
    7 print "File: ".$fi->getPathname()."\n";
    8 }
    25

    View full-size slide

  39. 1 $it = new DirectoryIterator(".");
    2 $it2 = new RegexIterator($it, "/\.mp3$/i");
    3 $it3 = new FilesizeIterator($it2, 0, 6 * 1024 * 1024);
    4 $it4 = new LimitIterator($it3, 10, 5);
    5
    6 foreach ($it4 as $fi) {
    7 print "File: ".$fi->getPathname()."\n";
    8 }
    25

    View full-size slide

  40. ✓ Reusable
    We can use iterators where ever we want.
    26

    View full-size slide

  41. ✓ Reusable
    We can use iterators where ever we want.
    ✓ Testable
    Iterators can be tested separately.
    26

    View full-size slide

  42. ✓ Reusable
    We can use iterators where ever we want.
    ✓ Testable
    Iterators can be tested separately.
    ✓ Maintainable
    No need to adapt our business logic.
    26

    View full-size slide

  43. 27
    Countable
    (hurrah! An “spl interface”!)

    View full-size slide

  44. 1 class myIterator implements \Iterator {
    2 /* ... */
    3 }
    4
    5 $a = array(1, 2, 3);
    6 $it = new myIterator($a);
    7
    8 print count($it);
    28

    View full-size slide

  45. 1 class myIterator implements \Iterator {
    2 /* ... */
    3 }
    4
    5 $a = array(1, 2, 3);
    6 $it = new myIterator($a);
    7
    8 print count($it);
    1
    28

    View full-size slide

  46. 1 class myCountableIterator extends myIterator implements Countable {
    2 function count() {
    3 return count($this->_elements);
    4 }
    5 }
    6
    7 $a = array(1, 2, 3, 4, 5);
    8 $it = new myCountableIterator($a);
    9
    10 print count($it);
    29

    View full-size slide

  47. 1 class myCountableIterator extends myIterator implements Countable {
    2 function count() {
    3 return count($this->_elements);
    4 }
    5 }
    6
    7 $a = array(1, 2, 3, 4, 5);
    8 $it = new myCountableIterator($a);
    9
    10 print count($it);
    5
    29

    View full-size slide

  48. 1 class myCountableIterator extends myIterator implements Countable {
    2 function count() {
    3 return count($this->_arr);
    4 }
    5 }
    6
    7 $a = array(1, 2, 3, 4, 5);
    8 $it = new myCountableIterator($a);
    9 $it2 = new limitIterator($it, 0, 3);
    10
    11 print count($it2);
    30

    View full-size slide

  49. 1 class myCountableIterator extends myIterator implements Countable {
    2 function count() {
    3 return count($this->_arr);
    4 }
    5 }
    6
    7 $a = array(1, 2, 3, 4, 5);
    8 $it = new myCountableIterator($a);
    9 $it2 = new limitIterator($it, 0, 3);
    10
    11 print count($it2);
    1
    30

    View full-size slide

  50. SPL Iterators
    ➡ AppendIterator
    ➡ ArrayIterator
    ➡ CachingIterator
    ➡ CallbackFilterIterator
    ➡ DirectoryIterator
    ➡ EmptyIterator
    ➡ FilesystemIterator
    ➡ FilterIterator
    ➡ GlobIterator
    ➡ InfiniteIterator
    ➡ IteratorIterator
    ➡ LimitIterator
    ➡ MultipleIterator
    ➡ NoRewindIterator
    ➡ ParentIterator
    ➡ RecursiveArrayIterator
    ➡ RecursiveCachingIterator
    ➡ RecursiveCallbackFilterIterator
    ➡ RecursiveDirectoryIterator
    ➡ RecursiveFilterIterator
    ➡ RecursiveIteratorIterator
    ➡ RecursiveRegexIterator
    ➡ RecursiveTreeIterator
    ➡ RegexIterator
    ➡ SimpleXMLIterator
    32

    View full-size slide

  51. SPL Iterators
    33
    http://lxr.php.net/xref/PHP_5_5/ext/spl/internal/

    View full-size slide

  52. ➡ IteratorIterator?
    35

    View full-size slide

  53. ➡ IteratorIterator?
    ➡ RecursiveIterator?
    35

    View full-size slide

  54. ➡ IteratorIterator?
    ➡ RecursiveIterator?
    ➡ RecursiveIteratorIterator?
    35

    View full-size slide

  55. ➡ IteratorIterator?
    ➡ RecursiveIterator?
    ➡ RecursiveIteratorIterator?
    ➡ RecursiveCallbackFilterIterator?
    35

    View full-size slide

  56. ➡ IteratorIterator?
    ➡ RecursiveIterator?
    ➡ RecursiveIteratorIterator?
    ➡ RecursiveCallbackFilterIterator?
    35

    View full-size slide

  57. 36
    IteratorIterator

    View full-size slide

  58. 37
    Turns traversable “things” into an iterator

    View full-size slide

  59. 38
    1 $it = new myIterator();
    2 if ($it instanceof \IteratorAggregate) {
    3 $it = $it->getIterator();
    4 }
    5 $it2 = new \LimitIterator($it, 5, 10);

    View full-size slide

  60. 39
    1 $it = new myIterator();
    2 $it2 = new \IteratorIterator($it);
    3 $it3 = new \LimitIterator($it2, 5, 10);

    View full-size slide

  61. 40
    Recursive*Iterator

    View full-size slide

  62. 41
    1 $it = new ArrayIterator(
    2 array("foo", "bar", array("qux", "wox"), "baz"));
    3
    4 foreach ($it as $v) {
    5 print $v . "\n";
    6 }

    View full-size slide

  63. 41
    1 $it = new ArrayIterator(
    2 array("foo", "bar", array("qux", "wox"), "baz"));
    3
    4 foreach ($it as $v) {
    5 print $v . "\n";
    6 }
    foo
    bar
    Array
    baz

    View full-size slide

  64. 42
    1 $it = new RecursiveArrayIterator(
    2 array("foo", "bar", array("qux", "wox"), "baz"));
    3
    4 foreach ($it as $v) {
    5 print $v . "\n";
    6 }

    View full-size slide

  65. 42
    1 $it = new RecursiveArrayIterator(
    2 array("foo", "bar", array("qux", "wox"), "baz"));
    3
    4 foreach ($it as $v) {
    5 print $v . "\n";
    6 }
    foo
    bar
    Array
    baz

    View full-size slide

  66. 43
    1 $it = new RecursiveArrayIterator(
    2 array("foo", "bar", array("qux", "wox"), "baz"));
    3 $it2 = new RecursiveIteratorIterator($it);
    4
    5 foreach ($it2 as $v) {
    6 print $v . "\n";
    7 }

    View full-size slide

  67. 43
    1 $it = new RecursiveArrayIterator(
    2 array("foo", "bar", array("qux", "wox"), "baz"));
    3 $it2 = new RecursiveIteratorIterator($it);
    4
    5 foreach ($it2 as $v) {
    6 print $v . "\n";
    7 }
    foo
    bar
    qux
    wox
    baz

    View full-size slide

  68. 44
    “Recursive” iterators add the POSSIBILITY
    to recursively iterate over data.
    You still need to implement it!

    View full-size slide

  69. 45
    RecursiveCallbackFilterIterator

    View full-size slide

  70. ➡ Enables recursivity
    ➡ Is a filter iterator (does not necessarily
    return all the elements)
    ➡ Filters through a callback function.
    46

    View full-size slide

  71. 47
    SPL Iterators,..

    View full-size slide

  72. ➡ It has “quirks” that are easily solvable (but
    breaks BC)
    ➡ Documentation is not always up to date.
    ➡ Naming is VERY confusing (caching
    iterator, recursiveIterator, seekableIterator)
    ➡ But the iterators are worth it!
    48

    View full-size slide

  73. 49
    DATA STRUCTURES

    View full-size slide

  74. 50
    ➡ SplDoublyLinkedList
    ➡ SplStack
    ➡ SplQueue
    ➡ SplHeap
    ➡ SplMinHeap
    ➡ SplMaxHeap
    ➡ SplPriorityQueue
    ➡ SplFixedArray
    ➡ SplObjectStorage

    View full-size slide

  75. 51
    ➡ Every data structure has its strength and
    weaknesses.
    ➡ Big-Oh O(1), O(n), O(log n) etc...
    ➡ Balance between time (CPU) and space
    (memory)
    ➡ PHP arrays are quite good!
    ➡ But sometimes other data structures are
    better.

    View full-size slide

  76. 53
    http://www.flickr.com/photos/sostark/26697448/

    View full-size slide

  77. 53
    http://www.flickr.com/photos/sostark/26697448/
    SplStack

    View full-size slide

  78. 55
    http://www.flickr.com/photos/blogchef/4764248456/sizes/z/in/photostream/

    View full-size slide

  79. 55
    http://www.flickr.com/photos/blogchef/4764248456/sizes/z/in/photostream/
    Spl(Doubly)LinkedList

    View full-size slide

  80. 56
    http://www.flickr.com/photos/pediddle/54326823/

    View full-size slide

  81. 56
    http://www.flickr.com/photos/pediddle/54326823/
    SplObjectStorage

    View full-size slide

  82. 57
    SplPriorityQueue

    View full-size slide

  83. 58
    http://farm4.static.flickr.com/3224/3072017987_ee454536da.jpg

    View full-size slide

  84. 58
    http://farm4.static.flickr.com/3224/3072017987_ee454536da.jpg
    SplHeap

    View full-size slide

  85. 59
    http://en.wikipedia.org/wiki/File:USA.NM.VeryLargeArray.02.jpg

    View full-size slide

  86. 59
    http://en.wikipedia.org/wiki/File:USA.NM.VeryLargeArray.02.jpg
    SplFixedArray

    View full-size slide

  87. 60
    ➡ Use wisely:
    ➡ Don’t use SplStack / SplQueue for
    random reads.
    ➡ Don’t use FixedArrays when you need
    speed boosts.

    View full-size slide

  88. 61
    EXCEPTIONS

    View full-size slide

  89. ➡ BadFunctionCallException
    ➡ BadMethodCallException
    ➡ DomainException
    ➡ InvalidArgumentException
    ➡ LengthException
    ➡ LogicException
    ➡ OutOfBoundsException
    ➡ OutOfRangeException
    ➡ OverflowException
    ➡ RangeException
    ➡ RuntimeException
    ➡ UnderflowException
    ➡ UnexpectedValueException
    62

    View full-size slide

  90. ➡ BadFunctionCallException
    ➡ BadMethodCallException
    ➡ DomainException
    ➡ InvalidArgumentException
    ➡ LengthException
    ➡ OutOfRangeException
    63
    Logic Exceptions Runtime Exceptions
    ➡ OutOfBoundsException
    ➡ OverflowException
    ➡ RangeException
    ➡ UnderflowException
    ➡ UnexpectedValueException

    View full-size slide

  91. 64
    1 function foo($str) {
    2 if ($str == "The Spanish Inquisition") {
    3 throw new \UnexpectedValueException("Nobody expects ".$str);
    4 }
    5 /* ... */
    6 }

    View full-size slide

  92. 65
    1 function foo($str) {
    2 if ($str == "The Spanish Inquisition") {
    3 throw new \InvalidArgumentException("Nobody expects ".$str);
    4 }
    5 /* ... */
    6 }
    Logic, not runtime

    View full-size slide

  93. 66
    1 function foo($str) {
    2 if ($str == "The Spanish Inquisition") {
    3 /* logic */
    4 throw new \InvalidArgumentException("Nobody expects ".$str);
    5 }
    6
    7 try {
    8 $this->getDatabase()->saveRecord($str);
    9 } catch (\RuntimeException $e) {
    10 /* We could try again here */
    11 } catch (\Exception $e) {
    12 /* Sorry, something else occurred. */
    13 }
    14 }

    View full-size slide

  94. 67
    Never throw “\Exception”
    Always catch “\Exception”

    View full-size slide

  95. ➡ SPL Autoloading
    ➡ SplFileInfo class
    ➡ Spl(Temp)FileObject
    ➡ ArrayObject
    ➡ SplObserver / SplSubject
    69

    View full-size slide

  96. 70
    Autoloader

    View full-size slide

  97. 71
    spl_autoload_register("spl_autoload_call");

    View full-size slide

  98. 71
    spl_autoload_register("spl_autoload_call");
    Throws logicException

    View full-size slide

  99. 72
    spl_autoload_unregister("spl_autoload_call");

    View full-size slide

  100. 72
    spl_autoload_unregister("spl_autoload_call");
    - Removes ALL the autoloaders!
    - Destroys the autoload stack.
    - Set your house on fire.

    View full-size slide

  101. 73
    ArrayObject

    View full-size slide

  102. 74
    ArrayObjects are not objects that acts like arrays
    ArrayObjects are objects that acts like arrays

    View full-size slide

  103. 75
    1 $a = array("foo", "bar");
    2 $b = $a;
    3 $b[] = "baz";
    4
    5 print_r ($a);
    6 print_r ($b);

    View full-size slide

  104. 75
    1 $a = array("foo", "bar");
    2 $b = $a;
    3 $b[] = "baz";
    4
    5 print_r ($a);
    6 print_r ($b);
    Array
    (
    [0] => foo
    [1] => bar
    )
    Array
    (
    [0] => foo
    [1] => bar
    [2] => baz
    )

    View full-size slide

  105. 76
    1 $a = new ArrayObject();
    2 $a[] = "foo";
    3 $a[] = "bar";
    4
    5 $b = $a;
    6 $b[] = "baz";
    7
    8 print_r (iterator_to_array($a));
    9 print_r (iterator_to_array($b));

    View full-size slide

  106. 76
    1 $a = new ArrayObject();
    2 $a[] = "foo";
    3 $a[] = "bar";
    4
    5 $b = $a;
    6 $b[] = "baz";
    7
    8 print_r (iterator_to_array($a));
    9 print_r (iterator_to_array($b));
    Array
    (
    [0] => foo
    [1] => bar
    [2] => baz
    )
    Array
    (
    [0] => foo
    [1] => bar
    [2] => baz
    )

    View full-size slide

  107. 77
    How about the SPL & Drupal ?

    View full-size slide

  108. ➡ Not all that bad!
    ➡ Makes heavy use of iterators
    ➡ Exceptions are ok
    ➡ Too many new \Exceptions() (129)
    ➡ Datastructures not really
    78

    View full-size slide

  109. 79
    How can we make using the SPL easier?

    View full-size slide

  110. 80
    ➡ The (first and only)
    book about the SPL.
    ➡ Written by me (so you
    know it’s good :P)
    ➡ Fixes the
    documentation problem
    of the SPL (or a wobbly
    table)

    View full-size slide

  111. ➡ Adaption of the SPL will only happen
    when developers can become familiar
    with it.
    81

    View full-size slide

  112. ➡ Adaption of the SPL will only happen
    when developers can become familiar
    with it.
    ➡ There is currently no real way to
    familiarize yourself with the SPL.
    81

    View full-size slide

  113. ➡ BLOG!
    ➡ Update documentation.
    ➡ Find the quirks,
    and maybe even solve them.
    82

    View full-size slide

  114. http://farm1.static.flickr.com/73/163450213_18478d3aa6_d.jpg 83

    View full-size slide

  115. 84
    Find me on twitter: @jaytaph
    Find me for development and training: www.noxlogic.nl
    Find me on email: [email protected]
    Find me for blogs: www.adayinthelifeof.nl
    Symfony2 Webinar

    View full-size slide