Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Spl Not A Bridge Too Far phpNW09

6,398 views

Published on

SPL provides a lot of classes and interfaces to make your code more readable, maintainable and testable.

Published in: Technology, Education

Spl Not A Bridge Too Far phpNW09

  1. 1. SPL, not a bridge too far phpNW 2009 - Manchester
  2. 2. Who am I ? Michelangelo van Dam Independent Enterprise PHP consultant Co-founder PHPBenelux UG @dragonbe http://dragonbe.com 2
  3. 3. Who are you ? Are you familiar with php.net ? Are you familiar with arrays ? Are you familiar with OOP ? Are you familiar with Design Patterns ? 3
  4. 4. What is SPL ? Standard PHP Library interfaces, classes and methods solve common development challenges Available since PHP 5.0 !!! As of 5.3 SPL cannot be turned off from the source ! 4
  5. 5. SPL by Marcus Börger Ittteerrrattor 5
  6. 6. Definition of SPL SPL provides a huge toolkit that assists you to easily iterate over a diversity of data structures in a standardized way 6
  7. 7. What does it provide ? • ArrayObject - approach arrays as objects • Iterators - various iterators • Interfaces - iterator interfaces for your objects • Exceptions - exceptions to streamline error handling • SPL Functions - extra functions and autoloader func • SplFileInfo - tools for filesystem access • Data structures - structuring data sequences 7
  8. 8. <?php phpinfo(); ?> 8
  9. 9. ArrayObject • provides an interface - treat arrays as objects - elements are iteratable - provides serializing and deserializing of arrays - sorting elements (w/ or w/o callback methods) - exchange elements with other arrays or objects 9
  10. 10. <?php ArrayObject Example $myArray = array ( 'time' => 'Derick Rethans', 'test' => 'Sebastian Bergmann', 'iterate' => 'Marcus Börger', ); $obj = new ArrayObject($myArray); print_r($obj); $obj->uasort(function ($a, $b) { if ($a == $b) { return 0; } return ($a < $b) ? -1 : 1; }); print_r($obj); 10
  11. 11. ArrayObject output ArrayObject Object ( [storage:ArrayObject:private] => Array ( [time] => Derick Rethans [test] => Sebastian Bergmann [iterate] => Marcus Börger ) ) ArrayObject Object ( [storage:ArrayObject:private] => Array ( [time] => Derick Rethans [iterate] => Marcus Börger [test] => Sebastian Bergmann ) ) 11
  12. 12. … More of ArrayObject // serializing object for caching, sessions, … $obj->serialize(); // adding more key/value elements to the stack $obj->offsetSet('enterprise', 'Ivo Jansch'); // removing by key $obj->offsetUnset('time'); … 12
  13. 13. Iterator • provides a common interface • to iterate over “things” - xml data - database data - arrays • move back and forth in a stack • distinct methods to access keys and values • specific iterators for different purposes 13
  14. 14. Advantage ? • Reusable code - data structures can change - object oriented ✓ extending ✓ refactoring ✓ overloading 14
  15. 15. Example • retrieve data in an array • with items filtered out 15
  16. 16. <?php FilterIterator Example class filterOut extends FilterIterator { private $_filter; public function __construct(Iterator $it, $filter) { parent::__construct($it); $this->_filter = $filter; } public function accept() { $key = $this->getInnerIterator()->key(); return ($key == $this->_filter) ? false : true; } } 16
  17. 17. <?php FilterIterator output $myArray = array ( 'time' => 'Derick Rethans', 'test' => 'Sebastian Bergmann', 'iterate' => 'Marcus Börger', ); $obj = new ArrayObject($myArray); $iterator = new filterOut($obj->getIterator(), 'time'); foreach ($iterator as $item) { var_dump($item); } //ouputs string(18) "Sebastian Bergmann" string(13) "Marcus Börger" 17
  18. 18. DirectoryIterator • dealing with files and directories • looping back and forth between files • sorting files w/ or w/o custom sorting algorithms 18
  19. 19. Example • show an list of archive files • ordered with last archive first 19
  20. 20. Directory contents $ ls archives/ datafile-20090901.csv datafile-20090906.csv datafile-20090911.csv datafile-20090916.csv datafile-20090921.csv datafile-20090926.csv datafile-20090902.csv datafile-20090907.csv datafile-20090912.csv datafile-20090917.csv datafile-20090922.csv datafile-20090927.csv datafile-20090903.csv datafile-20090908.csv datafile-20090913.csv datafile-20090918.csv datafile-20090923.csv datafile-20090928.csv datafile-20090904.csv datafile-20090909.csv datafile-20090914.csv datafile-20090919.csv datafile-20090924.csv datafile-20090929.csv datafile-20090905.csv datafile-20090910.csv datafile-20090915.csv datafile-20090920.csv datafile-20090925.csv datafile-20090930.csv 20
  21. 21. SortableDirectorIterator <?php class SortableDirectoryIterator extends DirectoryIterator { public function sortUp() { $storage = $this->_getStorage(); $storage->uksort(function ($a, $b) { if ($a == $b) return 0; return ($a < $b) ? -1 : 1; }); return $storage; } public function sortDown() { $storage = $this->_getStorage(); $storage->uksort(function ($a, $b) { if ($a == $b) return 0; return ($a < $b) ? 1 : -1; }); return $storage; } 21
  22. 22. … Our Storage Container protected function _getStorage() { $obj = new ArrayObject(); foreach ($this as $file) { if ($file->isDot()) continue; $obj->offsetSet($file->getFileName(), $file->getFileInfo()); } return $obj; } } $dir = new SortableDirectoryIterator('./archives'); $sortObj = $dir->sortDown(); $iterator = $sortObj->getIterator(); while ($iterator->valid()) { echo $iterator->current()->getPathName() . PHP_EOL; $iterator->next(); } 22
  23. 23. Voila ! Descending filenames ./archives/datafile-20090930.csv ./archives/datafile-20090915.csv ./archives/datafile-20090929.csv ./archives/datafile-20090914.csv ./archives/datafile-20090928.csv ./archives/datafile-20090913.csv ./archives/datafile-20090927.csv ./archives/datafile-20090912.csv ./archives/datafile-20090926.csv ./archives/datafile-20090911.csv ./archives/datafile-20090925.csv ./archives/datafile-20090910.csv ./archives/datafile-20090924.csv ./archives/datafile-20090909.csv ./archives/datafile-20090923.csv ./archives/datafile-20090908.csv ./archives/datafile-20090922.csv ./archives/datafile-20090907.csv ./archives/datafile-20090921.csv ./archives/datafile-20090906.csv ./archives/datafile-20090920.csv ./archives/datafile-20090905.csv ./archives/datafile-20090919.csv ./archives/datafile-20090904.csv ./archives/datafile-20090918.csv ./archives/datafile-20090903.csv ./archives/datafile-20090917.csv ./archives/datafile-20090902.csv ./archives/datafile-20090916.csv ./archives/datafile-20090901.csv 23
  24. 24. RecursiveIteratorIterator • iterates over existing iterator • over multiple levels • easy to flatten out nested array structures • controlling recursive interactions 24
  25. 25. Example Chuck Norris Account Manager Jane Doe John Doe Project Manager Project Manager Cinderella Shrek Developer Graphical Designer 25
  26. 26. RecursiveIteratorIterator <?php $company = array ( array ( 'name' => 'Chuck Norris','position' => 'Account Manager', 'manages' => array ( array ( 'name' => 'Jane Doe','position' => 'Project Manager', 'manages' => array ( array ( 'name' => 'Cinderella','position' => 'Developer', 'manages' => array (), ), array ( 'name' => 'Shrek','position' => 'Graphical Designer', 'manages' => array (), ), ), ), array ( 'name' => 'John Doe','position' => 'Project Manager', 'manages' => array (), ), ), ), ); 26
  27. 27. Flattened Array output $iterator = new RecursiveArrayIterator(new ArrayObject($company)); $ritit = new RecursiveIteratorIterator($iterator); foreach ($ritit as $key => $value) { echo $key . ' = ' . $value . PHP_EOL; } // outputs name = Chuck Norris position = Account Manager name = Jane Doe position = Project Manager name = Cinderella position = Developer name = Shrek position = Graphical Designer name = John Doe position = Project Manager 27
  28. 28. Interfaces • Countable: an internal counter • OuterIterator: iteration over inner iterators • RecursiveIterator: iterating in an recursive way • SeekableIterator: an internal stack seeker • SplObserver: implements observer pattern • SplSubject: implements observer pattern 28
  29. 29. <?php Interface example // file: Order.php class Order implements Countable, SplSubject { protected $_orders; protected $_count; public function __construct() { $this->_count = 0; $this->_orders = array (); } public function placeOrder() { $this->_count++; } public function attach(SplObserver $observer) { $this->_orders[] = $observer; } public function detach(SplObserver $observer) { // not used in this case } 29
  30. 30. Interface Example (2) public function notify() { foreach ($this->_orders as $obj) { $obj->update($this); } } public function count() { return $this->_count; } } <?php // file: PlaceOrder.php class PlaceOrder implements SplObserver { public function update(SplSubject $order) { echo 'We have ' . count($order) . ' orders now' . PHP_EOL; } } 30
  31. 31. Running Interface Example <?php require_once 'Order.php'; require_once 'PlaceOrder.php'; $order = new Order(); $placeOrder = new PlaceOrder(); $order->attach($placeOrder); $order->notify(); $order->placeOrder(); $order->notify(); $order->placeOrder(); $order->notify(); $ php ./spl_observer.php We have 0 orders now We have 1 orders now We have 2 orders now 31
  32. 32. SPL Exceptions • SPL Exceptions - templates - throw exceptions - common issues • Types of exceptions - LogicExceptions - RuntimeExceptions 32
  33. 33. SPL LogicException Tree 33
  34. 34. SPL RuntimeException Tree 34
  35. 35. <?php Exceptions Example //file: spl_exception01.php class MyClass { public function giveANumberFromOneToTen($number) { if($number < 1 || $number > 10) { throw new OutOfBoundsException('Number should be between 1 and 10'); } echo $number . PHP_EOL; } } $my = new MyClass(); try { $my->giveANumberFromOneToTen(5); $my->giveANumberFromOneToTen(20); } catch (OutOfBoundsException $e) { echo $e->getMessage() . PHP_EOL; } Output: $ /usr/bin/php ./spl_exception01.php 5 Number should be between 1 and 10 35
  36. 36. SplFunctions • functions for PHP and SPL in particular • often dealing with auto loading • some for internal referencing 36
  37. 37. <?php SplFunctions Example interface foo {} interface bar {} class baz implements foo, bar {} class example extends baz {} var_dump(class_implements(new baz)); var_dump(class_implements(new example)); 37
  38. 38. Output of SplFunctions array(2) { ["foo"]=> string(3) "foo" ["bar"]=> string(3) "bar" } array(2) { ["bar"]=> string(3) "bar" ["foo"]=> string(3) "foo" } 38
  39. 39. SPLFileInfo The SplFileInfo class offers a high-level object oriented interface to information for an individual file. 39
  40. 40. <?php SplFileInfo Example // use the current file to get information from $file = new SplFileInfo(dirname(__FILE__)); var_dump($file->isFile()); var_dump($file->getMTime()); var_dump($file->getSize()); var_dump($file->getFileInfo()); var_dump($file->getOwner()); //output bool(false) int(1244760945) int(408) object(SplFileInfo)#2 (0) { } int(501) 40
  41. 41. Processing CSV with SPL Consider the following data.csv Derick Rethans;time Sebastian Bergmann;test Marcus Börger;iterate Ivo Jansch;enterprise Matthew Weier O'Phinney;extend Michelangelo van Dam;elephpant 41
  42. 42. <?php SPL usage on CSV $info = new SplFileInfo('data.csv'); if ($info->isReadable()) { $file = $info->openFile(); $file->setFlags(SplFileObject::READ_CSV); $file->setCsvControl(';','"'); foreach ($file as $row) { list ($user, $term) = $row; if (null !== $user && null !== $term) { echo $user . ' is known for ' . $term . PHP_EOL; } } } //outputs Derick Rethans is known for time Sebastian Bergmann is known for test Marcus Börger is known for iterate Ivo Jansch is known for enterprise Matthew Weier O'Phinney is known for extend Michelangelo van Dam is known for elephpant 42
  43. 43. Data Structures • Available in PHP 5.3.x - SplDoublyLinkedList ✓ SplStack ✓ SplQueue ✓ SplHeap ✓ SplMaxHeap ✓ SplMinHeap ✓ SplPriorityQueue 43
  44. 44. Data Structures Example <?php // file: spl_stack01.php $stack = new SplStack(); $stack->push('Message 1'); $stack->push('Message 2'); $stack->push('Message 3'); echo $stack->pop() . PHP_EOL; echo $stack->pop() . PHP_EOL; echo $stack->pop() . PHP_EOL; Outputs: $ /usr/bin/php ./spl_stack01.php Message 3 Message 2 Message 1 44
  45. 45. SplHeap • SplHeap is an abstract class - SplMinHeap implements SplHeap (low » high) - SplMaxHeap implements SplHeap (high » low) • stacking values w/o FIFO, FILO order 45
  46. 46. Simple SplHeap example <?php $heap = new SplMinHeap; $heap->insert(5); $heap->insert(2); $heap->insert(8); $heap->insert(6); $heap->top(); while ($heap->valid()) { echo $heap->key() . ': ' . $heap->current() . PHP_EOL; $heap->next(); } //outputs 3: 2 2: 5 1: 6 0: 8 46
  47. 47. JupilerLeague with SplHeap <?php class JupilerLeague extends SplHeap { public function compare($array1, $array2) { $values1 = array_values($array1); $values2 = array_values($array2); if ($values1[0] === $values2[0]) return 0; return $values1[0] < $values2[0] ? -1 : 1; } } $heap = new JupilerLeague(); $heap->insert(array ('AA Gent' => 15)); $heap->insert(array ('Anderlecht' => 20)); $heap->insert(array ('Cercle Brugge' => 11)); $heap->insert(array ('Charleroi' => 12)); $heap->insert(array ('Club Brugge' => 21)); $heap->insert(array ('G. Beerschot' => 15)); $heap->insert(array ('Kortrijk' => 10)); $heap->insert(array ('KV Mechelen' => 18)); $heap->insert(array ('Lokeren' => 10)); $heap->insert(array ('Moeskroen' => 7)); $heap->insert(array ('Racing Genk' => 11)); $heap->insert(array ('Roeselare' => 6)); $heap->insert(array ('Standard' => 20)); $heap->insert(array ('STVV' => 17)); $heap->insert(array ('Westerlo' => 10)); $heap->insert(array ('Zulte Waregem' => 15)); $heap->top(); while ($heap->valid()) { list ($team, $score) = each ($heap->current()); echo $team . ': ' . $score . PHP_EOL; $heap->next(); } 47
  48. 48. JupilerLeague Scoreboard Club Brugge: 21 Anderlecht: 20 Standard: 20 KV Mechelen: 18 STVV: 17 Zulte Waregem: 15 AA Gent: 15 G. Beerschot: 15 Charleroi: 12 Racing Genk: 11 Cercle Brugge: 11 Kortrijk: 10 Lokeren: 10 Westerlo: 10 Moeskroen: 7 Roeselare: 6 48
  49. 49. Conclusion SPL can help you solve common PHP issues it’s built-in, so why not use it it requires no “advanced skills” to use 49
  50. 50. SPL is not all good • Matthew “Elazar” Turland pointed out: - Performance could be better (SPLStack) - ArrayObject doesn’t support all array functions • See his presentation: http://ishouldbecoding.com/publications 50
  51. 51. Not a bridge too far... 51
  52. 52. Only one minor thing... 52
  53. 53. Documentation problem • php.net/spl needs more documentation ! • you can help on that part: - see http://elizabethmariesmith.com/2009/02/setting-up-phd-on-windows - you can set up phpdoc on each platform ! - Efnet: #php.doc channel - http://doc.php.net - phpdoc@php.net 53
  54. 54. More about SPL... • main SPL documentation: http://php.net/spl • PHPro Tutorials on SPL: http://www.phpro.org/tutorials/Introduction-to-SPL.html • Lorenzo Alberton’s blog: http://www.alberton.info/php_5.3_spl_data_structures.html • http://www.colder.ch/news/01-08-2009/34/splobjectstorage-for- a-fa.html 54
  55. 55. License This presentation is released under the Creative Commons Attribution-Share Alike 3.0 Unported License You are free: - to share : to copy, distribute and transmit the work - to remix : to adapt the work Under the following conditions: - attribution : You must attribute the work in the manner specified by the author or licensor - share alike : If you alter, transform, or build upon this work, you may distribute the resulting work only under the same, similar or a compatible license See: http://creativecommons.org/licenses/by-sa/3.0/ 55
  56. 56. Photo credits Marcus Boerger - Sebastian Bergmann http://www.flickr.com/photos/sebastian_bergmann/173891817 Golden Gate Bridge - Felix De Vliegher http://www.flickr.com/photos/felixdv/2883471022/ 56
  57. 57. Thank you Find my slides on http://slideshare.net/DragonBe Don’t forget to vote ! http://joind.in/613 57

×