Practical PHP 5.3

11,710 views
11,522 views

Published on

PHP 5.3 has many new features that allow very different paradigms of software development, that may be unfamiliar to many PHP developers. If you want to learn more about functional or aspect-oriented programming, or how to organize your PHP libraries according to the new de facto PHP namespacing standard, don't miss this talk.

Published in: Technology
0 Comments
11 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
11,710
On SlideShare
0
From Embeds
0
Number of Embeds
873
Actions
Shares
0
Downloads
119
Comments
0
Likes
11
Embeds 0
No embeds

No notes for slide

Practical PHP 5.3

  1. 1. Practical PHP 5.3 Nate Abele 2.6.2010 IPC Berlin
  2. 2. Me • Former lead developer, CakePHP • Co-founder & current lead developer, Lithium • Developing on 5.3 for ~2 years • Twitter: @nateabele
  3. 3. PHP Renaissance • Long-awaited features finalized and committed • Resurgence of energy and interest in evolving the language • Trunk == iteration on latest stable release
  4. 4. Anyway...
  5. 5. Little Things • Performance • ext/fileinfo • Syntax • ext/sqlite3 • Phar • ext/intl • SPL classes • mysqlnd
  6. 6. Big Things • Late static binding • Namespaces • Lambdas / closures
  7. 7. Late-static binding (LSB) class Base { public static function foo() { $subclass = get_called_class(); // ...do some logic with $subclass... } } class Child extends Base { public static function bar() { return static::foo() + 1; } } class Grandchild extends Child { public static function foo() { $result = parent::foo(); // ...do some logic with $result... return $result; } }
  8. 8. Late-static binding (LSB) • static:: ~= $this-> • get_called_class() - the subclass that invoked the method • parent:: - same idea you’re used to • Always use static:: or parent::, self:: etc. breaks the chain
  9. 9. Late-static binding (LSB) • Attributes still a little “broken” class A { public static $message; } class B extends A {} class C extends A {} B::$message = 'WTF?'; echo C::$message; // echoes 'WTF?'
  10. 10. Late-static binding (LSB) • Attributes still a little “broken” class A { public static $message; } class B extends A {} class C extends A { public static $message = 'Overridden'; } B::$message = 'WTF?'; echo C::$message; // echoes 'Overridden'
  11. 11. Late-static binding (LSB) • Attributes still a little “broken” class A { public static $message; } class B extends A { public static $message = 'Overridden'; } class C extends A { } A::$message = 'WTF?'; echo C::$message; // echoes 'WTF?'
  12. 12. Why? • Properly architect stateless portions of apps • Utility classes • Immutable state
  13. 13. “Dynamic” statics • $foo->$bar() vs. Foo::bar() • $foo = 'Foo'; $bar = 'bar'; $foo::$bar(); • __callStatic()
  14. 14. “Dynamic” statics class Dispatcher { public function run($url) { $parameters = Router::match($url); // ... } }
  15. 15. “Dynamic” statics class Dispatcher { public $router = 'Router'; public function run($url) { $router = $this->router; $parameters = $router::match($url); // ... } }
  16. 16. Namespaces • Finally! • What’s up with the ? • Actually “packages”
  17. 17. Namespaces namespace foobar; class MyClass { // ... } $class = new foobarMyClass(); // -- or -- use foobarMyClass; $class = new MyClass();
  18. 18. Namespace use foobar; $class = new barMyClass(); namespace me; $list = new SplDoublyLinkedList(); namespace me; $list = new SplDoublyLinkedList(); namespace me; $class = 'foobarMyClass'; $object = new $class();
  19. 19. PSR-0 http://groups.google.com/group/php-standards/web/psr-0-final-proposal
  20. 20. PSR-0 • Maps top-level vendor package name to filesystem location • Maps file names 1:1 with class name
  21. 21. PSR-0 • lithiumcoreLibraries => /path/to/classes/lithium/core/Libraries.php • lithiumLibraries => /path/to/classes/lithium/Libraries.php • LithiumCoreLibraries => /path/to/classes/Lithium/Core/Libraries.php • Lithium_Core_Libraries => /path/to/classes/Lithium/Core/Libraries.php
  22. 22. Original (PEAR) Draft • Requires sub-packages • Namespaces must be lower-cased and underscored
  23. 23. Original (PEAR) Draft • LithiumCore: ? • lithiumcore: Obviously a namespace • Sub-packages promote reuse outside vendor libraries
  24. 24. SplClassLoader • Concrete implementation of PSR-0 • PHP version: http://gist.github.com/221634 • C version: http://github.com/metagoto/splclassloader
  25. 25. Intermission
  26. 26. Ternary Shortcut // Old: public function foo($parameter = null) { $parameter = $parameter ? $parameter : $this->_calculateDefault(); // ... } // New: public function foo($parameter = null) { $parameter = $parameter ?: $this->_calculateDefault(); // ... }
  27. 27. Phar • include 'phar:///path/to/file.phar/file.php'; • Redistributable apps • Plugins • Application templates
  28. 28. Phar $archive = new Phar("/path/new_file.phar"); $archive->buildFromDirectory( '/path/to/my/app', '/.(php|htaccess|jpg|png|gif|css|js|ico|json|ini)$/' ); $archive->compress(Phar::GZ);
  29. 29. Lambdas & Closures • Lambda: a function assigned to a variable • Closure: a lambda, but bound to variables in the current scope • This is an extremely big deal
  30. 30. Lambdas & Closures $names = array( 'Nate Abele', 'David Coallier', 'Cap'n Crunch' ); $split = array_map( function($name) { list($first, $last) = explode(' ', $name); return compact('first', 'last'); }, $names ); // Result: array( array('first' => 'Nate', 'last' => 'Abele'), array('first' => 'David', 'last' => 'Coallier'), array('first' => 'Cap'n', 'last' => 'Crunch') )
  31. 31. Lambdas & Closures $names = array('Nate Abele', 'David Coallier', /* ... */); $filter = array('Nate', 'David'); $mapper = function($name) use ($filter) { list($first, $last) = explode(' ', $name); if (!in_array($first, $filter)) { return null; } return compact('first', 'last'); }; $filtered = array_map($mapper, $names);
  32. 32. Lambdas & Closures $findActive = function($object) use (&$findActive) { if ($object->isActive) { return $object; } if ($object->children) { foreach ($object->children as $child) { return $findActive($child); } } };
  33. 33. Lambdas & Closures class SomeWebService { public function call($data) { $request = new HttpRequest(); // Configure $request... $result = $request->send(); // Do some processing... // Update $request for next operation... $final = $request->send(); // Post-process $final to extract some value return $someExtractedValue; } }
  34. 34. Lambdas & Closures class SomeWebService { public function call($data, $pre = null, $post = null) { $request = new HttpRequest(); // ... if ($pre) { $request = $pre($request); } $result = $request->send(); if ($post) { $result = $post($result); } // ... $final = $request->send(); // ... } }
  35. 35. Lambdas & Closures class Database { public $callThisOnEveryRead; public function read($query) { if ($callback = $this->callThisOnEveryRead) { $callback($query); } // ... } }
  36. 36. Lambdas & Closures class Database { public $callThisOnEveryRead; public function read($query) { if ($callback = $this->callThisOnEveryRead) { $result = $callback($query) if ($result !== null) { return $result; } } // ... } }
  37. 37. No $this
  38. 38. Referential Transparency • Only needs parameters to calculate a return value (i.e. no $_*, $this or date(), etc.) • Doesn’t produce any side-effects • No modifications outside current scope • No references • No , , etc. echo headers()
  39. 39. lithiumutilcollectionFilters
  40. 40. Method Filters class Database { public function read($query) { // ... run the query ... return $result; } }
  41. 41. Method Filters class Database { public function read($query) { $method = function() { // ... run the query ... return $result; }; } }
  42. 42. Method Filters class Database { public function read($query) { $method = function($query) { // ... run the query ... return $result; }; return $method($query); } }
  43. 43. Method Filters class Database extends lithiumcoreObject { public function read($query) { $method = function($self, $params) { // ... run the query ... return $result; }; return $this->_filter( __METHOD__, compact('query'), $method ); } }
  44. 44. Method Filters $database = new Database($connectionDetails); $database->applyFilter('read', function($self, $params, $chain) { $key = md5(serialize($params['query'])); if ($result = Cache::read($key)) { return $result; } $result = $chain->next($self, $params, $chain); Cache::write($key, $result); return $result; });
  45. 45. lithiumutilcollectionFilters outer inner read()
  46. 46. AOP in a Nutshell • Obliviousness • Eliminates boilerplate code per class relationship • Centralized configuration of concerns
  47. 47. Thanks! • nate.abele@gmail.com • @nateabele • http://lithify.me/

×