Slide 1

Slide 1 text

1 Joshua Thijssen jaytaph (Re)discovering the SPL

Slide 2

Slide 2 text

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 Tech nalyze WWW.TECHANALYZE.IO

Slide 3

Slide 3 text

3 Q: Have you ever used the SPL?

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

5 SPL Documentation

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

6

Slide 8

Slide 8 text

7

Slide 9

Slide 9 text

8

Slide 10

Slide 10 text

➡ Not enough documentation. 8

Slide 11

Slide 11 text

➡ Not enough documentation. ➡ Very few examples. 8

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

➡ Interfaces ➡ Iterators ➡ Data structures ➡ Exceptions ➡ Miscellaneous functionality 9 Every SPL talk available:

Slide 14

Slide 14 text

10 Don’t get scared! The SPL is awesomesauce!

Slide 15

Slide 15 text

11 INTERFACES

Slide 16

Slide 16 text

12 Traversable (not an “spl interface”)

Slide 17

Slide 17 text

13

Slide 18

Slide 18 text

➡ Traversable cannot be implemented* 13

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

14 Iterator (still not an “spl interface”)

Slide 22

Slide 22 text

Userland interface to make an object traversable 15

Slide 23

Slide 23 text

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 ) } 16 Iterator interface:

Slide 24

Slide 24 text

17

Slide 25

Slide 25 text

➡ Iterator 17

Slide 26

Slide 26 text

➡ Iterator ➡ FilterIterators 17

Slide 27

Slide 27 text

➡ Iterator ➡ FilterIterators ➡ “Chains” iterators together 17

Slide 28

Slide 28 text

➡ Iterator ➡ FilterIterators ➡ “Chains” iterators together ➡ IteratorAggregate 17

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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 } 19

Slide 33

Slide 33 text

➡ Filter all MP3 and all JPG files. 20

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

➡ 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. 20

Slide 37

Slide 37 text

➡ 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. 20

Slide 38

Slide 38 text

21

Slide 39

Slide 39 text

➡ How to test? (we can’t) 21

Slide 40

Slide 40 text

➡ How to test? (we can’t) ➡ How to maintain? (we can’t) 21

Slide 41

Slide 41 text

➡ How to test? (we can’t) ➡ How to maintain? (we can’t) ➡ How to reuse? (we can’t) 21

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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, 5, 3); 5 6 foreach ($it4 as $fi) { 7 print "File: ".$fi->getPathname()."\n"; 8 } 24

Slide 45

Slide 45 text

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, 5, 3); 5 6 foreach ($it4 as $fi) { 7 print "File: ".$fi->getPathname()."\n"; 8 } 24

Slide 46

Slide 46 text

25

Slide 47

Slide 47 text

✓ Reusable We can use iterators where ever we want. 25

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

26 Countable (hurrah! An “spl interface”!)

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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 27

Slide 53

Slide 53 text

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); 28

Slide 54

Slide 54 text

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 28

Slide 55

Slide 55 text

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); 29

Slide 56

Slide 56 text

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 29

Slide 57

Slide 57 text

30 ITERATORS

Slide 58

Slide 58 text

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 31

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

33

Slide 61

Slide 61 text

34

Slide 62

Slide 62 text

➡ IteratorIterator? 34

Slide 63

Slide 63 text

➡ IteratorIterator? ➡ RecursiveIterator? 34

Slide 64

Slide 64 text

➡ IteratorIterator? ➡ RecursiveIterator? ➡ RecursiveIteratorIterator? 34

Slide 65

Slide 65 text

➡ IteratorIterator? ➡ RecursiveIterator? ➡ RecursiveIteratorIterator? ➡ RecursiveCallbackFilterIterator? 34

Slide 66

Slide 66 text

➡ IteratorIterator? ➡ RecursiveIterator? ➡ RecursiveIteratorIterator? ➡ RecursiveCallbackFilterIterator? 34

Slide 67

Slide 67 text

35 IteratorIterator

Slide 68

Slide 68 text

36 Turns traversable “things” into an iterator

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

39 Recursive*Iterator

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

40 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

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

41 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

Slide 76

Slide 76 text

42 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 }

Slide 77

Slide 77 text

42 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

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

44 RecursiveCallbackFilterIterator

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

46 SPL Iterators,..

Slide 82

Slide 82 text

➡ 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! 47

Slide 83

Slide 83 text

48 DATA STRUCTURES

Slide 84

Slide 84 text

49 ➡ SplDoublyLinkedList ➡ SplStack ➡ SplQueue ➡ SplHeap ➡ SplMinHeap ➡ SplMaxHeap ➡ SplPriorityQueue ➡ SplFixedArray ➡ SplObjectStorage

Slide 85

Slide 85 text

50 ➡ 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.

Slide 86

Slide 86 text

51 PubQuiz

Slide 87

Slide 87 text

52 http://www.flickr.com/photos/sostark/26697448/

Slide 88

Slide 88 text

52 http://www.flickr.com/photos/sostark/26697448/ SplStack

Slide 89

Slide 89 text

53

Slide 90

Slide 90 text

53 SplQueue

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

55 http://www.flickr.com/photos/pediddle/54326823/

Slide 94

Slide 94 text

55 http://www.flickr.com/photos/pediddle/54326823/ SplObjectStorage

Slide 95

Slide 95 text

56

Slide 96

Slide 96 text

56 SplPriorityQueue

Slide 97

Slide 97 text

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

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

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

Slide 102

Slide 102 text

60 EXCEPTIONS

Slide 103

Slide 103 text

➡ BadFunctionCallException ➡ BadMethodCallException ➡ DomainException ➡ InvalidArgumentException ➡ LengthException ➡ LogicException ➡ OutOfBoundsException ➡ OutOfRangeException ➡ OverflowException ➡ RangeException ➡ RuntimeException ➡ UnderflowException ➡ UnexpectedValueException 61

Slide 104

Slide 104 text

➡ BadFunctionCallException ➡ BadMethodCallException ➡ DomainException ➡ InvalidArgumentException ➡ LengthException ➡ OutOfRangeException 62 Logic Exceptions Runtime Exceptions ➡ OutOfBoundsException ➡ OverflowException ➡ RangeException ➡ UnderflowException ➡ UnexpectedValueException

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

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

Slide 107

Slide 107 text

65 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 }

Slide 108

Slide 108 text

66 Never throw “\Exception” Always catch “\Exception”

Slide 109

Slide 109 text

67 MISC

Slide 110

Slide 110 text

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

Slide 111

Slide 111 text

69 Autoloader

Slide 112

Slide 112 text

70 spl_autoload_register("spl_autoload_call");

Slide 113

Slide 113 text

70 spl_autoload_register("spl_autoload_call"); Throws logicException

Slide 114

Slide 114 text

71 spl_autoload_unregister("spl_autoload_call");

Slide 115

Slide 115 text

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

Slide 116

Slide 116 text

72 ArrayObject

Slide 117

Slide 117 text

73 ArrayObjects are not objects that acts like arrays ArrayObjects are objects that acts like arrays

Slide 118

Slide 118 text

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

Slide 119

Slide 119 text

74 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 )

Slide 120

Slide 120 text

75 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));

Slide 121

Slide 121 text

75 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 )

Slide 122

Slide 122 text

76 How can we make using the SPL easier?

Slide 123

Slide 123 text

77 ➡ 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)

Slide 124

Slide 124 text

78

Slide 125

Slide 125 text

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

Slide 126

Slide 126 text

➡ 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. 78

Slide 127

Slide 127 text

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

Slide 128

Slide 128 text

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

Slide 129

Slide 129 text

81 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