Share
Embed
(re)discovering the SPL - PHP|Tek 12
Joshua Thijssen
May 24, 2012
Transcript
91 slides
-
(re)discovering PHP|Tek - Chicago - USA May 24, 2012 the
Standard PHP Library -
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! -
➡ Interfaces ➡ Iterators ➡ Data structures ➡ Exceptions ➡
Miscellaneous functionality 4 Standard PHP Library -
➡ Not enough documentation. ➡ Very few examples. ➡ Wrong
/ missing in some cases. 10 -
➡ 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 -
➡ Predefined interfaces ➡ “SPL” interfaces ➡ Some interfaces will
“hook” into the PHP core. 13 -
➡ Traversable cannot be implemented. ➡ Traversable can be detected
(instanceof). ➡ foreach() will use traversable interfaces. 15 -
countable $a = array(1, 2, 3); $it = new myIterator($a);
print count($it); 1 17 -
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 -
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 -
➡ It’s not an iterator, it’s an interface. ➡ seek()
➡ Implementing “seekableIterator” can speed up other iterators. ➡ LimitIterator makes use of “seekableIterator” 21 -
Iterators $dir = opendir("."); while (($file = readdir($dir)) !== false)
{ print "file: $file\n"; } Let’s read directory content 23 -
Iterators $dir = opendir("."); while (($file = readdir($dir)) !== false)
{ if (! preg_match('|\.mp3$|i', $file)) { continue; } print "file: $file\n"; } 24 Filter on *.mp3 -
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 -
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"; } -
Iterators $it = new DirectoryIterator("."); foreach ($it as $fi) {
print "File: ".$fi->getPathname()."\n"; } 27 Directory Iterator -
Iterators $it = new DirectoryIterator("."); $it = new RegexIterator($it, "/\.mp3$/i");
foreach ($it as $fi) { print "File: ".$fi->getPathname()."\n"; } 28 Directory Iterator + filtering -
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 -
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 -
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 -
Iterators reset($a); while (current($a) !== false) { $key = key($a);
$current = current($a); print “K: $key C: $current\n”; next($a); } Rewind() valid() 32 -
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 -
39 $it = new myIterator(); if ($it instanceof IteratorAggregate) {
$it = $it->getIterator(); } $it = new LimitIterator($it, 5, 10); -
40 $it = new myIterator(); $it = new IteratorIterator($it); $it
= new LimitIterator($it, 5, 10); -
42 $it = new ArrayIterator( array(“foo”, “bar”, array(“qux”, “wox”), “baz”));
foreach ($it as $v) { print $v . “\n”; } foo bar Array baz -
43 $it = new RecursiveArrayIterator( array(“foo”, “bar”, array(“qux”, “wox”), “baz”));
foreach ($it as $v) { print $v . “\n”; } foo bar Array baz -
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 -
45 “Recursive” iterators add the POSSIBILITY to recursively iterate over
data. You still need to implement it! -
➡ Enables recursivity ➡ Is a filter iterator (does not
necessarily return all the elements) ➡ Filters through a callback function. 47 -
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”; } -
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 -
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"; -
SPL Data Structures 56 ➡ SplDoublyLinkedList ➡ SplStack ➡ SplQueue
➡ SplHeap ➡ SplMinHeap ➡ SplMaxHeap ➡ SplPriorityQueue ➡ SplFixedArray ➡ SplObjectStorage -
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. -
SPL Data Structures 66 ➡ Use wisely: ➡ Don’t use
SplStack / SplQueue for random reads. ➡ Don’t use FixedArrays when you need speed boosts -
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 -
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: -
SPL Exceptions ➡ BadFunctionCallException ➡ BadMethodCallException ➡ DomainException ➡ InvalidArgumentException
➡ LengthException ➡ LogicException ➡ OutOfBoundsException ➡ OutOfRangeException ➡ OverflowException ➡ RangeException ➡ RuntimeException ➡ UnderflowException ➡ UnexpectedValueException 71 -
SPL Exceptions ➡ BadFunctionCallException ➡ BadMethodCallException ➡ DomainException ➡ InvalidArgumentException
➡ LengthException ➡ OutOfRangeException 72 Logic Exceptions Runtime Exceptions ➡ OutOfBoundsException ➡ OverflowException ➡ RangeException ➡ UnderflowException ➡ UnexpectedValueException -
73 function foo($str) { if ($str == “The Spanish Inquisition”)
{ throw new \UnexpectedValueException(“Nobody expects ”.$str); } ... } -
74 function foo($str) { if ($str == “The Spanish Inquisition”)
{ throw new \InvalidArgumentException(“Nobody expects ”.$str); } ... } Logic, not runtime -
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); } ... } -
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"); } .... } } -
➡ SPL Autoloading ➡ SplFileInfo class ➡ Spl(Temp)FileObject ➡ ArrayObject
➡ SplObserver / SplSubject 80 -
85 ArrayObjects are not objects that acts like arrays ArrayObjects
are objects that acts like arrays -
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 ) -
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 ) -
➡ PHP|Architect’s “guide into the SPL” ➡ Written by me!
➡ Talks about the SPL and how to use it (properly). ➡ Available soon... 89 -
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