Slide 1

Slide 1 text

(re)discovering Web&PHP - San Jose - USA 16-18 september 2013 the Standard PHP Library 1

Slide 2

Slide 2 text

2 Joshua Thijssen Freelance consultant, developer and trainer @ NoxLogic Founder of the Dutch Web Alliance Development in PHP, Python, Perl, C, Java. Lead developer of Saffire. Blog: http://adayinthelifeof.nl Email: [email protected] Twitter: @jaytaph

Slide 3

Slide 3 text

3 Have you ever used the SPL?

Slide 4

Slide 4 text

4 Have you ever used the SPL, and not want to apply for a job as C# developer?

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

6

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

➡ 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. ➡ :( 8

Slide 9

Slide 9 text

➡ Interfaces ➡ Iterators ➡ Data structures ➡ Exceptions ➡ Miscellaneous functionality 9

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

11 INTERFACES

Slide 12

Slide 12 text

12

Slide 13

Slide 13 text

13 Traversable

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

15 Iterator

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 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. 18

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

$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"; } 22 Iterator chaining

Slide 23

Slide 23 text

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

Slide 24

Slide 24 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 ) } 24

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

26 Countable

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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 28

Slide 29

Slide 29 text

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 29

Slide 30

Slide 30 text

30 SeekableIterator

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

32 ITERATORS

Slide 33

Slide 33 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 33

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

➡ IteratorIterator? ➡ RecursiveIterator? ➡ RecursiveIteratorIterator? ➡ RecursiveCallbackFilterIterator? ➡ Really!?!? 35

Slide 36

Slide 36 text

36 IteratorIterator

Slide 37

Slide 37 text

37 Turns traversable “things” into an iterator

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

40 Recursive*Iterator

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

43 $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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

45 RecursiveCallbackFilterIterator

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

47 $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”; }

Slide 48

Slide 48 text

48 CachingIterator

Slide 49

Slide 49 text

49 2 for the price of 1

Slide 50

Slide 50 text

50 ➡ Lookahead iterator ➡ Caches values ➡ Powerful __tostring() functionality

Slide 51

Slide 51 text

51 $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

Slide 52

Slide 52 text

52 $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";

Slide 53

Slide 53 text

53 It doesn’t use the cached data!

Slide 54

Slide 54 text

54 DATA STRUCTURES

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

57 Quiz

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

59 SplQueue

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

62 SplPriorityQueue

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

66 SplObjectStorage

Slide 67

Slide 67 text

67 $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

Slide 68

Slide 68 text

68 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:

Slide 69

Slide 69 text

69 EXCEPTIONS

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

74 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); } ... }

Slide 75

Slide 75 text

75 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"); } .... } }

Slide 76

Slide 76 text

76 Never throw “Exception” Always catch “Exception”

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

78 MISC

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

80 Autoloader

Slide 81

Slide 81 text

81 spl_autoload_register(“spl_autoload_call”); Throws logicException

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

83 ArrayObject

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

85 $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 )

Slide 86

Slide 86 text

86 $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 )

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

88 ➡ The (first and only) book about the SPL. ➡ Written by me (so you know it’s good :P) ➡ Tries and fix the documentation problem of the SPL.

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

90 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