Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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!

Slide 3

Slide 3 text

3 History

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

5 Let’s not talk about that.

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

9

Slide 10

Slide 10 text

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

Slide 11

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

Slide 12

Slide 12 text

12 INTERFACES

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

14 Traversable

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

16 Countable

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

20 SeekableIterator

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

22 Iterator

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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"; }

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

33 ITERATORS

Slide 34

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

37 IteratorIterator

Slide 38

Slide 38 text

38 Turns traversable “things” into an iterator

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

41 Recursive*Iterator

Slide 42

Slide 42 text

42 $it = new ArrayIterator( 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”)); foreach ($it as $v) { print $v . “\n”; } foo bar Array baz

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

46 RecursiveCallbackFilterIterator

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

49 CachingIterator

Slide 50

Slide 50 text

50 2 for the price of 1

Slide 51

Slide 51 text

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

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"; } // A // ... // Y // last letter: Z

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

54 It doesn’t use the cached data!

Slide 55

Slide 55 text

55 DATA STRUCTURES

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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.

Slide 58

Slide 58 text

SPL Data Structures 58 Quiz

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

SPL Data Structures 60 SplQueue

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

63 SplPriorityQueue

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

67 SplObjectStorage

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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:

Slide 70

Slide 70 text

70 EXCEPTIONS

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

77 Never throw “Exception” Always catch “Exception”

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

79 MISC

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

81 Autoloader

Slide 82

Slide 82 text

82 spl_autoload_register(“spl_autoload_call”); Throws logicException

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

84 ArrayObject

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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 )

Slide 87

Slide 87 text

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 )

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

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