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

(re)discovering the SPL - PHP|Tek 12

(re)discovering the SPL - PHP|Tek 12

Joshua Thijssen

May 24, 2012
Tweet

More Decks by Joshua Thijssen

Other Decks in Technology

Transcript

  1. (re)discovering
    PHP|Tek - Chicago - USA
    May 24, 2012
    the Standard PHP Library

    View Slide

  2. Joshua Thijssen
    Freelance consultant, developer and
    trainer @ NoxLogic / Techademy
    Development in PHP, Python, Perl,
    C, Java....
    Blog: http://adayinthelifeof.nl
    Email: [email protected]
    Twitter: @jaytaph
    2
    Oh hai!

    View Slide

  3. 3
    History

    View Slide

  4. ➡ Interfaces
    ➡ Iterators
    ➡ Data structures
    ➡ Exceptions
    ➡ Miscellaneous functionality
    4
    Standard PHP Library

    View Slide

  5. 5
    Let’s not talk about that.

    View Slide

  6. 6
    Let’s talk about the fun and freaky stuff!

    View Slide

  7. 7
    Don’t get scared!
    The SPL is awesomesauce!

    View Slide

  8. 8
    SPL Documentation
    http://www.php.net/spl

    View Slide

  9. 9

    View Slide

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

    View Slide

  11. ➡ Adaption of the SPL will only occur when
    developers can become familiar with it.
    ➡ There is currently no real way to familiarize
    yourself with the SPL.
    ➡ :(
    11

    View Slide

  12. 12
    INTERFACES

    View Slide

  13. ➡ Predefined interfaces
    ➡ “SPL” interfaces
    ➡ Some interfaces will “hook” into the PHP
    core.
    13

    View Slide

  14. 14
    Traversable

    View Slide

  15. ➡ Traversable cannot be implemented.
    ➡ Traversable can be detected (instanceof).
    ➡ foreach() will use traversable interfaces.
    15

    View Slide

  16. 16
    Countable

    View Slide

  17. countable
    $a = array(1, 2, 3);
    $it = new myIterator($a);
    print count($it);
    1
    17

    View Slide

  18. countable
    class myCountableIterator extends myIterator implements Countable
    {
    function count() {
    return count($this->_arr);
    }
    }
    $a = array(1, 2, 3, 4, 5);
    $it = new myCountableIterator($a);
    print count($it);
    5
    18

    View Slide

  19. countable
    class myCountableIterator extends myIterator implements Countable
    {
    function count() {
    return count($this->_arr);
    }
    }
    $a = array(1, 2, 3, 4, 5);
    $it = new myCountableIterator($a);
    $it = new limitIterator($it, 0, 3);
    print count($it);
    1
    19

    View Slide

  20. 20
    SeekableIterator

    View Slide

  21. ➡ It’s not an iterator, it’s an interface.
    ➡ seek()
    ➡ Implementing “seekableIterator” can speed up
    other iterators.
    ➡ LimitIterator makes use of “seekableIterator”
    21

    View Slide

  22. 22
    Iterator

    View Slide

  23. Iterators
    $dir = opendir(".");
    while (($file = readdir($dir)) !== false) {
    print "file: $file\n";
    }
    Let’s read directory content
    23

    View Slide

  24. Iterators
    $dir = opendir(".");
    while (($file = readdir($dir)) !== false) {
    if (! preg_match('|\.mp3$|i', $file)) {
    continue;
    }
    print "file: $file\n";
    }
    24
    Filter on *.mp3

    View Slide

  25. Iterators
    ➡ 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.
    25

    View Slide

  26. Iterators
    ➡ How to test?
    ➡ How to maintain?
    ➡ How to reuse?
    26
    $dir = opendir(".");
    while (($file = readdir($dir)) !== false) {
    if (! preg_match('|\.mp3$|i', $file)) {
    continue;
    }
    print "file: $file\n";
    }

    View Slide

  27. Iterators
    $it = new DirectoryIterator(".");
    foreach ($it as $fi) {
    print "File: ".$fi->getPathname()."\n";
    }
    27
    Directory Iterator

    View Slide

  28. Iterators
    $it = new DirectoryIterator(".");
    $it = new RegexIterator($it, "/\.mp3$/i");
    foreach ($it as $fi) {
    print "File: ".$fi->getPathname()."\n";
    }
    28
    Directory Iterator + filtering

    View Slide

  29. Iterators
    $it = new DirectoryIterator(".");
    $it = new RegexIterator($it, "/\.mp3$/i");
    $it = new FilesizeIterator($it, 6 * 1024 * 1024);
    $it = new LimitIterator($it, 10, 5);
    foreach ($it as $fi) {
    print "File: ".$fi->getPathname()."\n";
    }
    29
    Iterator chaining

    View Slide

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

    View Slide

  31. Iterators
    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 )
    }
    31

    View Slide

  32. Iterators
    reset($a);
    while (current($a) !== false) {
    $key = key($a);
    $current = current($a);
    print “K: $key C: $current\n”;
    next($a);
    }
    Rewind()
    valid()
    32

    View Slide

  33. 33
    ITERATORS

    View Slide

  34. 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
    34

    View Slide

  35. SPL Iterators
    35
    http://lxr.php.net/xref/PHP_5_3/ext/spl/internal/

    View Slide

  36. ➡ IteratorIterator?
    ➡ RecursiveIterator?
    ➡ RecursiveIteratorIterator?
    ➡ RecursiveCallbackFilterIterator?
    ➡ Really!?!?
    36

    View Slide

  37. 37
    IteratorIterator

    View Slide

  38. 38
    Turns traversable “things” into an iterator

    View Slide

  39. 39
    $it = new myIterator();
    if ($it instanceof IteratorAggregate) {
    $it = $it->getIterator();
    }
    $it = new LimitIterator($it, 5, 10);

    View Slide

  40. 40
    $it = new myIterator();
    $it = new IteratorIterator($it);
    $it = new LimitIterator($it, 5, 10);

    View Slide

  41. 41
    Recursive*Iterator

    View Slide

  42. 42
    $it = new ArrayIterator(
    array(“foo”, “bar”, array(“qux”, “wox”), “baz”));
    foreach ($it as $v) {
    print $v . “\n”;
    }
    foo
    bar
    Array
    baz

    View Slide

  43. 43
    $it = new RecursiveArrayIterator(
    array(“foo”, “bar”, array(“qux”, “wox”), “baz”));
    foreach ($it as $v) {
    print $v . “\n”;
    }
    foo
    bar
    Array
    baz

    View Slide

  44. 44
    $it = new RecursiveArrayIterator(
    array(“foo”, “bar”, array(“qux”, “wox”), “baz”));
    $it = new RecursiveIteratorIterator($it);
    foreach ($it as $v) {
    print $v . “\n”;
    }
    foo
    bar
    qux
    wox
    baz

    View Slide

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

    View Slide

  46. 46
    RecursiveCallbackFilterIterator

    View Slide

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

    View Slide

  48. 48
    $it = new RecursiveDirectoryIterator(“/”);
    $it = new RecursiveCallbackFilterIterator($it,
    function ($value, $key, $it) {
    if ($value->isDir()) {
    return true;
    }
    return ($value->getSize() < 1024);
    });
    $it = new RecursiveIteratorIterator($it);
    foreach ($it as $item) {
    print $item->getSize() . “ “ . $item->getPathName().”\n”;
    }

    View Slide

  49. 49
    CachingIterator

    View Slide

  50. 50
    2 for the price of 1

    View Slide

  51. 51
    ➡ Lookahead iterator
    ➡ Caches values
    ➡ Powerful __tostring() functionality

    View Slide

  52. 52
    $alphaIterator = new ArrayIterator(range("A", "Z"));
    $it = new CachingIterator($alphaIterator);
    foreach ($it as $v) {
    if (! $it->hasNext()) {
    print "last letter: ";
    }
    print $v . "\n";
    }
    // A
    // ...
    // Y
    // last letter: Z

    View Slide

  53. 53
    $alphaIterator = new ArrayIterator(range("A", "Z"));
    $it = new CachingIterator($alphaIterator);
    foreach ($it as $v) {
    if (! $it->hasNext()) {
    print "last letter: ";
    }
    print $v . "\n";
    }
    print "The fourth letter of the alphabet is: ".$it[3]."\n";

    View Slide

  54. 54
    It doesn’t use the cached data!

    View Slide

  55. 55
    DATA STRUCTURES

    View Slide

  56. SPL Data Structures
    56
    ➡ SplDoublyLinkedList
    ➡ SplStack
    ➡ SplQueue
    ➡ SplHeap
    ➡ SplMinHeap
    ➡ SplMaxHeap
    ➡ SplPriorityQueue
    ➡ SplFixedArray
    ➡ SplObjectStorage

    View Slide

  57. SPL Data Structures
    57
    ➡ 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 aren’t bad!
    ➡ But sometimes other data structures are
    better.

    View Slide

  58. SPL Data Structures
    58
    Quiz

    View Slide

  59. SPL Data Structures
    59
    http://www.flickr.com/photos/sostark/26697448/
    SplStack

    View Slide

  60. SPL Data Structures
    60
    SplQueue

    View Slide

  61. SPL Data Structures
    61
    http://www.flickr.com/photos/blogchef/4764248456/sizes/z/in/photostream/
    Spl(Doubly)LinkedList

    View Slide

  62. SPL Data Structures
    62
    http://www.flickr.com/photos/pediddle/54326823/
    SplObjectStorage

    View Slide

  63. 63
    SplPriorityQueue

    View Slide

  64. SPL Data Structures
    64
    http://farm4.static.flickr.com/3224/3072017987_ee454536da.jpg
    SplHeap

    View Slide

  65. SPL Data Structures
    65
    http://en.wikipedia.org/wiki/File:USA.NM.VeryLargeArray.02.jpg
    SplFixedArray

    View Slide

  66. SPL Data Structures
    66
    ➡ Use wisely:
    ➡ Don’t use SplStack / SplQueue for
    random reads.
    ➡ Don’t use FixedArrays when you need
    speed boosts

    View Slide

  67. 67
    SplObjectStorage

    View Slide

  68. 68
    $map = new SplObjectStorage();
    $map[$obj1] = $info1;
    $map[$obj2] = $info2;
    print_r ($map[$obj2]);
    $set = new SplObjectStorage();
    $set->attach($obj1);
    print_r ($set->contains($obj1));
    splObjectStorage as a set
    splObjectStorage as a map

    View Slide

  69. 69
    class MyStorage extends SplObjectStorage {
    function getHash($object) {
    return $object->type;
    }
    }
    $obj1 = new StdClass(); $obj1->type = “foo”;
    $obj2 = new StdClass(); $obj2->type = “bar”;
    $obj3 = new StdClass(); $obj3->type = “foo”;
    $store = new MyStorage();
    $store->attach($obj1); // Added
    $store->attach($obj2); // Added
    $store->attach($obj3); // Not added:same type (thus hash) already present!
    Defining what to store:

    View Slide

  70. 70
    EXCEPTIONS

    View Slide

  71. SPL Exceptions
    ➡ BadFunctionCallException
    ➡ BadMethodCallException
    ➡ DomainException
    ➡ InvalidArgumentException
    ➡ LengthException
    ➡ LogicException
    ➡ OutOfBoundsException
    ➡ OutOfRangeException
    ➡ OverflowException
    ➡ RangeException
    ➡ RuntimeException
    ➡ UnderflowException
    ➡ UnexpectedValueException
    71

    View Slide

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

    View Slide

  73. 73
    function foo($str) {
    if ($str == “The Spanish Inquisition”) {
    throw new \UnexpectedValueException(“Nobody expects ”.$str);
    }
    ...
    }

    View Slide

  74. 74
    function foo($str) {
    if ($str == “The Spanish Inquisition”) {
    throw new \InvalidArgumentException(“Nobody expects ”.$str);
    }
    ...
    }
    Logic, not runtime

    View Slide

  75. 75
    function foo($str, $int) {
    if (! is_string($str)) {
    throw new \InvalidArgumentException(“Invalid type”);
    }
    if ($int < 0 || $int > 10) {
    throw new \OutOfRangeException(“should be between 0 and 10);
    }
    ...
    }

    View Slide

  76. 76
    class InvalidDateException extends DomainException { }
    class ChristmasException extends DomainException { }
    class Calendar {
    function addAppointment(DateTime $date, $appointment) {
    if ($date->format("dm") == "2512") {
    throw new \ChristmasException(
    "Cannot add appointment on christmas day");
    }
    $weekday = $date->format("N");
    if ($weekday >= 6) {
    throw new \InvalidDateException(
    "Cannot add appointment in the weekend");
    }
    ....
    }
    }

    View Slide

  77. 77
    Never throw “Exception”
    Always catch “Exception”

    View Slide

  78. 78
    Exceptions should not be
    part of your flow...
    They’re: exceptions

    View Slide

  79. 79
    MISC

    View Slide

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

    View Slide

  81. 81
    Autoloader

    View Slide

  82. 82
    spl_autoload_register(“spl_autoload_call”);
    Throws logicException

    View Slide

  83. 83
    spl_autoload_unregister(“spl_autoload_call”);
    Removes ALL the autoloaders!

    View Slide

  84. 84
    ArrayObject

    View Slide

  85. 85
    ArrayObjects are not objects that acts like arrays
    ArrayObjects are objects that acts like arrays

    View Slide

  86. 86
    $a = array("foo", "bar");
    $b = $a;
    $b[] = "baz";
    print_r ($a);
    print_r ($b);
    Array
    (
    [0] => foo
    [1] => bar
    )
    Array
    (
    [0] => foo
    [1] => bar
    [2] => baz
    )

    View Slide

  87. 87
    $a = new ArrayObject();
    $a[] = "foo";
    $a[] = "bar";
    $b = $a;
    $b[] = "baz";
    print_r (iterator_to_array($a));
    print_r (iterator_to_array($b));
    Array
    (
    [0] => foo
    [1] => bar
    [2] => baz
    )
    Array
    (
    [0] => foo
    [1] => bar
    [2] => baz
    )

    View Slide

  88. 88
    How can we make using the SPL easier?
    http://noscope.com/photostream/albums/various/I_Want_To_Believe_01.jpg

    View Slide

  89. ➡ PHP|Architect’s “guide into the SPL”
    ➡ Written by me!
    ➡ Talks about the SPL and
    how to use it (properly).
    ➡ Available soon...
    89

    View Slide

  90. http://farm1.static.flickr.com/73/163450213_18478d3aa6_d.jpg
    Questions?
    90

    View Slide

  91. Please rate my talk on joind.in:
    http://joind.in/6481
    Thank you
    91
    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

    View Slide