PHP 5.3 in practice
Upcoming SlideShare
Loading in...5
×
 

PHP 5.3 in practice

on

  • 11,534 views

 

Statistics

Views

Total Views
11,534
Views on SlideShare
11,378
Embed Views
156

Actions

Likes
16
Downloads
245
Comments
0

11 Embeds 156

http://coderwall.com 65
http://www.slideshare.net 55
https://intranet.netformic.net 14
http://www.westworld.be 12
http://paper.li 3
http://www.linkedin.com 2
http://www.sfexception.com 1
http://us-w1.rockmelt.com 1
http://srukwebdev01.totemic.local 1
http://www.techgig.com 1
http://symfony2developer.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

PHP 5.3 in practice PHP 5.3 in practice Presentation Transcript

  • PHP 5.3 in practice Fabien Potencier PHP 5.3 in practice – Fabien Potencier
  • Fabien Potencier •  Serial entrepreneur and developer by passion •  Founder of Sensio (in 1998) –  A services and consulting company specialized in Web technologies and Internet marketing (France and USA) –  70 people –  Open-Source specialists –  Big corporate customers –  Consulting, training, development, web design, … and more –  Sponsor of a lot of Open-Source projects like symfony and Doctrine PHP 5.3 in practice – Fabien Potencier
  • Fabien Potencier •  Creator and lead developer of symfony… •  and creator and lead developer of some more OSS: –  Symfony components –  Swift Mailer : Powerful component based mailing library for PHP –  Twig : Fexible, fast, and secure template language for PHP –  Pirum : Simple PEAR Channel Server Manager –  Sismo : PHP continuous integration server –  Lime : Easy to use unit testing library for PHP –  Twitto : A web framework in a tweet –  Twittee : A Dependency Injection injector in a tweet –  Pimple : A small PHP 5.3 dependency injection injector PHP 5.3 in practice – Fabien Potencier
  • Fabien Potencier •  Read my technical blog: http://fabien.potencier.org/ •  Follow me on Twitter: @fabpot •  Fork my code on Github: http://github.com/fabpot/ PHP 5.3 in practice – Fabien Potencier
  • Migrating to PHP 5.3 … for technical reasons PHP 5.3 in practice – Fabien Potencier
  • Migrating to PHP 5.3? •  Why? – Much faster – Less memory •  When? – PHP 5.3.1 is available – PHP 5.3.2 is about to be released and stable – Migration is simple enough PHP 5.3 in practice – Fabien Potencier
  • Migrating to PHP 5.3 … for speed PHP 5.3 in practice – Fabien Potencier
  • Dmitry Stogov did some benchmarks for popular PHP applications Drupal 20% faster Typo3 30% faster Wordpress 15% faster Xoops 10% faster http://news.php.net/php.internals/36484 PHP 5.3 in practice – Fabien Potencier
  • Doctrine 1.X and 2.0 Faster with PHP 5.3 and less memory consumption 30% less memory 20% faster PHP 5.3 in practice – Fabien Potencier
  • symfony 1 -47% symfony project running on PHP 5.2 vs PHP 5.3 profiled with XHPROF (run 4aeeb7d54b732 is PHP 5.3) PHP 5.3 in practice – Fabien Potencier
  • Migrating to PHP 5.3 … for the ecosystem PHP 5.3 in practice – Fabien Potencier
  • Second generation of PHP frameworks •  The next major versions of the most popular frameworks and libraries will use PHP 5.3 –  Symfony 2.0 –  Doctrine 2.0 Late 2010 –  Zend Framework 2.0 •  Better interoperability between these libraries, thanks to namespaces PHP 5.3 in practice – Fabien Potencier
  • Namespaces and Symfony 2 SymfonyComponents SymfonyFoundation SymfonyFramework SymfonyComponentsEventDispatcherEvent SymfonyFoundationUniversalClassLoader PHP 5.3 in practice – Fabien Potencier
  • SymfonyComponentsEventDispatcherEvent vs sfEvent Class names are NOT shorter PHP 5.3 in practice – Fabien Potencier
  • Namespaces and Symfony 2 require __DIR__.'/lib/Symfony/Core/ClassLoader.php'; use SymfonyFoundationClassLoader; use SymfonyComponentsEventDispatcherEvent; $loader = new ClassLoader('Symfony', __DIR__.'/lib'); $loader->register(); $event = new Event(); PHP 5.3 in practice – Fabien Potencier
  • Namespaces and Symfony 2 require __DIR__.'/lib/Symfony/Core/ClassLoader.php'; use SymfonyFoundationClassLoader; use SymfonyComponentsEventDispatcherEvent; $loader = new ClassLoader('Symfony', __DIR__.'/lib'); $loader->register(); $event = new Event(); PHP 5.3 in practice – Fabien Potencier
  • PHP 5.3 technical interoperability standards « … describes the mandatory requirements that must be adhered to for autoloader interoperability » http://groups.google.com/group/php-standards/web/psr-0-final-proposal PHP 5.3 in practice – Fabien Potencier
  • Why? •  Libraries following the specification are interoperable •  For instance, if you use Symfony 2.0, Doctrine 2.0, and Zend Framework 2.0 in the same project –  They can all share the same autoloader –  Symfony 2.0 provides an enhanced autoloader (with PEAR support) –  A native C extension has been created PHP 5.3 in practice – Fabien Potencier
  • Let’s dive into PHP 5.3 PHP 5.3 in practice – Fabien Potencier
  • PHP 5.3 •  A lot of changes –  Convenient changes: __DIR__, ?:, NOWDOC, … –  New features: i18n, SPL, Date management, mysqlnd, … –  Language enhancements: namespaces, anonymous functions, closures, late static binding, phar, Windows support, … PHP 5.3 in practice – Fabien Potencier
  • PHP 5.3 How does it change the implementation of some well-known Design Pattern? PHP 5.3 in practice – Fabien Potencier
  • PHP 5.3 … and the Singleton PHP 5.3 in practice – Fabien Potencier
  • The Singleton may cause serious damage to your code PHP 5.3 in practice – Fabien Potencier
  • History of the Singleton PHP 5.3 in practice – Fabien Potencier
  • The Singleton in PHP 4 class Singleton { function &getInstance() { static $instance; if (!$instance) { $instance = new Singleton(); } } return $instance; You can still } ins tantiate the class $obj =& Singleton::getInstance(); directly PHP 5.3 in practice – Fabien Potencier
  • The Singleton in PHP 5.0/5.1/5.2 class Singleton { static private $instance; private function __construct() {} static public function getInstance() { if (null === self::$instance) { self::$instance = new self(); } return self::$instance; do not forget to } } final private function __clone() {} ove rride __clone() $obj = Singleton::getInstance(); PHP 5.3 in practice – Fabien Potencier
  • The Singleton in PHP 5.3 abstract class Singleton { private static $instances = array(); final private function __construct() { if (isset(self::$instances[get_called_class()])) { throw new Exception("An instance of ".get_called_class()." already exists."); } static::initialize(); } protected function initialize() {} final public static function getInstance() { $class = get_called_class(); if (!isset(self::$instances[$class])) { self::$instances[$class] = new static(); } return self::$instances[$class]; } final private function __clone() {} } PHP 5.3 in practice – Fabien Potencier
  • The Singleton in PHP 5.3 class Foo extends Singleton {} class Bar extends Singleton {} $a = Foo::getInstance(); $b = Bar::getInstance(); PHP 5.3 in practice – Fabien Potencier
  • PHP 5.3 …Late Static Binding The ORM problem PHP 5.3 in practice – Fabien Potencier
  • class Model { static public function getMe() { return __CLASS__; } } class Article extends Model {} echo Article::getMe(); PHP 5.3 in practice – Fabien Potencier
  • <?php class Model { static public function getMe() { return get_called_class(); as of PHP 5.3 } } class Article extends Model {} echo Article::getMe(); PHP 5.3 in practice – Fabien Potencier
  • class Model { static public function findByPk($id) { $table = strtolower(get_called_class()); return $db->get( sprintf('SELECT * FROM %s WHERE id = %d', $table, $id) ); } } class Article extends Model {} $article = Article::findByPk(1); PHP 5.3 in practice – Fabien Potencier
  • class Model { static public function __callStatic($method, $arguments) { $table = strtolower(get_called_class()); $column = strtolower(substr($method, 6)); $value = $arguments[0]; $sql = sprintf('SELECT * FROM %s WHERE %s = ?', $table, $column); return $db->get($sql, $value); } } class Article extends Model {} $article = Article::findByTitle('foo'); PHP 5.3 in practice – Fabien Potencier
  • PHP 5.3 …interlude Anonymous functions Lambdas PHP 5.3 in practice – Fabien Potencier
  • An anonymous function is a function defined on the fly (no name) function () { echo 'Hello world!'; }; PHP 5.3 in practice – Fabien Potencier
  • Can be stored in a variable $hello = function () { echo 'Hello world!'; }; PHP 5.3 in practice – Fabien Potencier
  • … to be used later on $hello(); call_user_func($hello); PHP 5.3 in practice – Fabien Potencier
  • … or can be passed as a function argument function foo(Closure $func) { $func(); } foo($hello); PHP 5.3 in practice – Fabien Potencier
  • Fonctions anonymes Can take arguments $hello = function ($name) { echo 'Hello '.$name; }; $hello('Fabien'); call_user_func($hello, 'Fabien'); PHP 5.3 in practice – Fabien Potencier
  • Fonctions anonymes function foo(Closure $func, $name) { $func($name); } foo($hello, 'Fabien'); PHP 5.3 in practice – Fabien Potencier
  • When is it useful? PHP 5.3 in practice – Fabien Potencier
  • array_* Greatly simplify usage of some array_* functions array_map() array_reduce() array_filter() PHP 5.3 in practice – Fabien Potencier
  • class Article { public function __construct($title) { $this->title = $title; } public function getTitle() { return $this->title; } } PHP 5.3 in practice – Fabien Potencier
  • How to get an array of all article titles? $articles = array( new Article('PHP UK - part 1'), new Article('PHP UK - part 2'), new Article('See you next year!'), ); PHP 5.3 in practice – Fabien Potencier
  • $titles = array(); foreach ($articles as $article) { $titles[] = $article->getTitle(); } PHP 5.3 in practice – Fabien Potencier
  • $titles = array_map( create_function('$article', 'return $article->getTitle();'), $articles ); PHP 5.3 in practice – Fabien Potencier
  • $titles = array_map( function ($article) { return $article->getTitle(); }, $articles ); PHP 5.3 in practice – Fabien Potencier
  • $titles = array(); foreach ($articles as $article) { $titles[] = $article->getTitle(); } 100 100 $titles = array_map(create_function('$article', 'return $article->getTitle();'), $articles); 300 1800 $titles = array_map(function ($article) { return $article->getTitle(); }, $articles); 100 200 $mapper = function ($article) { return $article->getTitle(); }; $titles = array_map($mapper, $articles); 100 180 memory speed PHP 5.3 in practice – Fabien Potencier
  • $mapper = function ($article) { return $article->getTitle(); }; $titles = array_map($mapper, $articles); $mapper = function ($article) { return $article->getAuthor(); }; $authors = array_map($mapper, $articles); PHP 5.3 in practice – Fabien Potencier
  • A closure is a lambda that remembers the context of its creation… PHP 5.3 in practice – Fabien Potencier
  • $mapper = function ($method) { return function ($article) use($method) { return $article->$method(); }; }; PHP 5.3 in practice – Fabien Potencier
  • $method = 'getTitle'; $mapper = function ($article) use($method) { return $article->$method(); }; $method = 'getAuthor'; $titles = array_map($mapper, $articles); PHP 5.3 in practice – Fabien Potencier
  • $titleMapper = $mapper('getTitle'); $titles = array_map($titleMapper, $articles); $authorMapper = $mapper('getAuthor'); $authors = array_map($authorMapper, $articles); PHP 5.3 in practice – Fabien Potencier
  • $titles = array_map($mapper('getTitle'), $articles); $authors = array_map($mapper('getAuthor'), $articles); PHP 5.3 in practice – Fabien Potencier
  • Dependency Injector PHP 5.3 in practice – Fabien Potencier
  • « Dependency Injection is where components are given their dependencies through their constructors, methods, or directly into fields. » http://www.picoinjector.org/injection.html PHP 5.3 in practice – Fabien Potencier
  • Dependency Injection A real world « web » example PHP 5.3 in practice – Fabien Potencier
  • In most web applications, you need to manage the user preferences –  The user language –  Whether the user is authenticated or not –  The user credentials –  … PHP 5.3 in practice – Fabien Potencier
  • This can be done with a User object –  setLanguage(), getLanguage() –  setAuthenticated(), isAuthenticated() –  addCredential(), hasCredential() –  ... PHP 5.3 in practice – Fabien Potencier
  • The User information need to be persisted between HTTP requests We use the PHP session for the Storage PHP 5.3 in practice – Fabien Potencier
  • class SessionStorage { function __construct($cookieName = 'PHP_SESS_ID') { session_name($cookieName); session_start(); } function set($key, $value) { $_SESSION[$key] = $value; } // ... } PHP 5.3 in practice – Fabien Potencier
  • class User { protected $storage; function __construct() Very hard to { customize $this->storage = new SessionStorage(); } function setLanguage($language) { $this->storage->set('language', $language); } // ... } Very easy to use $user = new User(); PHP 5.3 in practice – Fabien Potencier
  • class User { protected $storage; Very easy to customize function __construct($storage) { $this->storage = $storage; } } $storage = new SessionStorage(); $user = new User($storage); Slightly more difficult to use PHP 5.3 in practice – Fabien Potencier
  • That’s Dependency Injection Nothing more PHP 5.3 in practice – Fabien Potencier
  • Instead of harcoding the Storage dependency inside the User class constructor Inject the Storage dependency in the User object PHP 5.3 in practice – Fabien Potencier
  • A Dependency Injector Describes objects and their dependencies Instantiates and configures objects on-demand PHP 5.3 in practice – Fabien Potencier
  • An injector SHOULD be able to manage ANY PHP object (POPO) The objects MUST not know that they are managed by the injector PHP 5.3 in practice – Fabien Potencier
  • •  Parameters –  The SessionStorage implementation we want to use (the class name) –  The session name •  Objects –  SessionStorage –  User •  Dependencies –  User depends on a SessionStorage implementation PHP 5.3 in practice – Fabien Potencier
  • Let’s build a simple injector with PHP 5.3 PHP 5.3 in practice – Fabien Potencier
  • Dependency Injector Managing parameters PHP 5.3 in practice – Fabien Potencier
  • class Injector { protected $parameters = array(); public function setParameter($key, $value) { $this->parameters[$key] = $value; } public function getParameter($key) { return $this->parameters[$key]; } } PHP 5.3 in practice – Fabien Potencier
  • Decoupling $injector = new Injector(); Customization $injector->setParameter('session_name', 'SESSION_ID'); $injector->setParameter('storage_class', 'SessionStorage'); $class = $injector->getParameter('storage_class'); $sessionStorage = new $class($injector->getParameter('session_name')); $user = new User($sessionStorage); Objects creation PHP 5.3 in practice – Fabien Potencier
  • class Injector Using PHP { magic methods protected $parameters = array(); public function __set($key, $value) { $this->parameters[$key] = $value; } public function __get($key) { return $this->parameters[$key]; } } PHP 5.3 in practice – Fabien Potencier
  • Interface is cleaner $injector = new Injector(); $injector->session_name = 'SESSION_ID'; $injector->storage_class = 'SessionStorage'; $sessionStorage = new $injector->storage_class($injector->session_name); $user = new User($sessionStorage); PHP 5.3 in practice – Fabien Potencier
  • Dependency Injector Managing objects PHP 5.3 in practice – Fabien Potencier
  • We need a way to describe how to create objects, without actually instantiating anything! Anonymous functions to the rescue! PHP 5.3 in practice – Fabien Potencier
  • class Injector { protected $parameters = array(); protected $objects = array(); public function __set($key, $value) { $this->parameters[$key] = $value; } public function __get($key) Store a lambda { return $this->parameters[$key]; able to create the object on-demand } public function setService($key, Closure $service) { $this->objects[$key] = $service; } public function getService($key) Ask the closure to create { return $this->objects[$key]($this); th e object and pass the } } current injector PHP 5.3 in practice – Fabien Potencier
  • $injector = new Injector(); $injector->session_name = 'SESSION_ID'; Description $injector->storage_class = 'SessionStorage'; $injector->setService('user', function ($c) { return new User($c->getService('storage')); }); $injector->setService('storage', function ($c) { return new $c->storage_class($c->session_name); }); Creating the User is now as easy as before $user = $injector->getService('user'); PHP 5.3 in practice – Fabien Potencier
  • class Injector { protected $values = array(); Simplify the code function __set($id, $value) { $this->values[$id] = $value; } function __get($id) { if (is_callable($this->values[$id])) { return $this->values[$id]($this); } else { return $this->values[$id]; } } } PHP 5.3 in practice – Fabien Potencier
  • $injector = new Injector(); Unified interface $injector->session_name = 'SESSION_ID'; $injector->storage_class = 'SessionStorage'; $injector->user = function ($c) { return new User($c->storage); }; $injector->storage = function ($c) { return new $c->storage_class($c->session_name); }; $user = $injector->user; PHP 5.3 in practice – Fabien Potencier
  • Dependency Injector Scope PHP 5.3 in practice – Fabien Potencier
  • For some objects, like the user, the injector must always return the same instance PHP 5.3 in practice – Fabien Potencier
  • spl_object_hash($injector->user) !== spl_object_hash($injector->user) PHP 5.3 in practice – Fabien Potencier
  • $injector->user = function ($c) { static $user; if (is_null($user)) { $user = new User($c->storage); } return $user; }; PHP 5.3 in practice – Fabien Potencier
  • spl_object_hash($injector->user) === spl_object_hash($injector->user) PHP 5.3 in practice – Fabien Potencier
  • $injector->user = $injector->asShared(function ($c) { return new User($c->storage); }); PHP 5.3 in practice – Fabien Potencier
  • function asShared(Closure $lambda) { return function ($injector) use ($lambda) { static $object; if (is_null($object)) { $object = $lambda($injector); } return $object; }; } PHP 5.3 in practice – Fabien Potencier
  • class Injector { protected $values = array(); function __set($id, $value) { $this->values[$id] = $value; } function __get($id) { Error management if (!isset($this->values[$id])) { throw new InvalidArgumentException(sprintf('Value "%s" is not defined.', $id)); } if (is_callable($this->values[$id])) { return $this->values[$id]($this); } else { return $this->values[$id]; } } } PHP 5.3 in practice – Fabien Potencier
  • class injector { protected $values = array(); function __set($id, $value) { $this->values[$id] = $value; } function __get($id) { if (!isset($this->values[$id])) { throw new InvalidArgumentException(sprintf('Value "%s" is not defined.', $id)); } if (is_callable($this->values[$id])) { return $this->values[$id]($this); } else { return $this->values[$id]; } } function asShared($callable) { 40 LOC for a fully- return function ($c) use ($callable) { static $object; if (is_null($object)) { $object = $callable($c); featured injector } return $object; }; } } PHP 5.3 in practice – Fabien Potencier
  • I’m NOT advocating the usage of lambdas everywhere This presentation was about showing how they work on practical examples PHP 5.3 in practice – Fabien Potencier
  • Questions? PHP 5.3 in practice – Fabien Potencier
  • Sensio S.A. 92-98, boulevard Victor Hugo 92 115 Clichy Cedex FRANCE Tél. : +33 1 40 99 80 80 Contact Fabien Potencier fabien.potencier at sensio.com http://www.sensiolabs.com/ http://www.symfony-project.org/ http://fabien.potencier.org/ PHP 5.3 in practice – Fabien Potencier