Playing With PHP 5.3

78
Jouons avec PHP 5.3 Fabien Potencier

description

 

Transcript of Playing With PHP 5.3

Page 1: Playing With PHP 5.3

Jouons avec PHP 5.3

Fabien Potencier

Page 2: Playing With PHP 5.3

Fabien Potencier •  Serial entrepreneur et développeur par passion •  Fondateur de Sensio (1998)

–  Société de conseil autour des technologies Open-Source (France and USA)

–  70 personnes –  Clients grands comptes –  Sponsor de projets Open-Source

comme Symfony, Doctrine ou Swift Mailer

Page 3: Playing With PHP 5.3

Fabien Potencier

•  Mon blog technique : http://fabien.potencier.org/

•  Sur Twitter : http://www.twitter.com/fabpot

•  Mon code sur Github: http://github.com/fabpot/

Page 4: Playing With PHP 5.3

Migrer vers PHP 5.3 Des raisons techniques

Page 5: Playing With PHP 5.3

Migrer vers PHP 5.3 ?

•  Pourquoi ? –  Plus rapide – Moins de mémoire

•  Quand ? –  PHP 5.3.0 est déjà stable depuis quelques mois –  PHP 5.3.1 va bientôt être disponible –  La migration est simple

Page 6: Playing With PHP 5.3

PHP 5.3 Beaucoup plus rapide ?

Page 7: Playing With PHP 5.3
Page 8: Playing With PHP 5.3

Dmitry Stogov a fait quelques tests de performance pour des applications PHP connues

Drupal 20% faster

Typo3 30% faster

Wordpress 15% faster

Xoops 10% faster

http://news.php.net/php.internals/36484

Page 9: Playing With PHP 5.3

Doctrine 1.X and 2.0

Significativement plus rapide avec PHP 5.3

30% de mémoire en moins

20% plus rapide

Page 10: Playing With PHP 5.3

symfony 1.X

symfony project running on PHP 5.2 vs PHP 5.3 profiled with XHPROF (run 4aeeb7d54b732 is PHP 5.3)

-47%

Page 11: Playing With PHP 5.3

Migrer vers PHP 5.3 Des raisons fonctionnelles

Page 12: Playing With PHP 5.3

Migrer vers PHP 5.3, frameworks 2.0

•  Prochaines versions des principaux frameworks/bibliothèques seront basés sur PHP 5.3

–  Symfony 2.0 –  Doctrine 2.0 –  Zend Framework 2.0

•  Interopérabilité améliorée entre ces bibliothèques, grâce aux namespaces

Fin 2010

Page 13: Playing With PHP 5.3

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/final-proposal

Page 14: Playing With PHP 5.3

Pourquoi ?

•  Les bibliothèques respectant cette spécification simple –  seront techniquement 100% interopérable –  pourront partager un seul autoloader optimisé

•  Par exemple pour utiliser Symfony 2.0 + Doctrine 2.0 + Zend Framework 2.0 dans un même projet

–  Un unique autoloader pour les 3 bibliothèques –  Exemple d’implémentation: http://gist.github.com/221634 –  Sera certainement implémenté en C une fois le standard définitif

Page 15: Playing With PHP 5.3

Les namespaces dans Symfony 2

Symfony\Components Symfony\Foundation Symfony\Framework

Symfony\Components\EventDispatcher\Event Symfony\Foundation\ClassLoader

Page 16: Playing With PHP 5.3

Symfony\Components\EventDispatcher\Event

vs

sfEvent

Le nom des classes

n’est pas plus court !

Page 17: Playing With PHP 5.3

Les namespaces dans Symfony 2

$classLoader = new ClassLoader('Symfony', __DIR__.'/lib'); $classLoader->register();

$container = new Builder(); $loader = new XmlFileLoader($container, __DIR__); $loader->load('services.xml');

$dumper = new PhpDumper($container); echo $dumper->dump();

Page 18: Playing With PHP 5.3

Les namespaces dans Symfony 2 require __DIR__.'/lib/Symfony/Core/ClassLoader.php';

use Symfony\Foundation\ClassLoader; use Symfony\Components\DependencyInjection\Builder; use Symfony\Components\DependencyInjection\Reference; use Symfony\Components\DependencyInjection\Loader\XmlFileLoader; use Symfony\Components\DependencyInjection\Dumper\PhpDumper;

Bonne pratique

Page 19: Playing With PHP 5.3

PHP 5.3 L’apport pour les entreprises

Page 20: Playing With PHP 5.3

PHP 5 dans les entreprises

Depuis 2005 et l’arrivée de PHP 5.0 et surtout PHP 5.2

Adoption plus rapide dans les entreprises que dans la communauté

Rupture technologique qui a entraîné une révolution des usages

Page 21: Playing With PHP 5.3

PHP 5, une rupture technologique

•  Arrivée de frameworks matures : symfony, Zend Framework, CakePHP, Prado, …

•  Professionnalisation des développements –  Prise en compte des bonnes pratiques : tests, design patterns, sécurité, …

•  Professionnalisation des développeurs –  Passage d’une communauté de bidouilleurs à une communauté de

développeurs PHP professionnels –  Une communauté qui se scinde en deux

Page 22: Playing With PHP 5.3

L’adoption de PHP 5.3 devrait être rapide dans les entreprises

– Migration facile

–  Support Windows amélioré (rapidité, intégration, fonctionnalités)

– Meilleures performances (for free)

–  Apport technique limité…

– … mais les usages vont une nouvelle fois évoluer

Page 23: Playing With PHP 5.3

PHP 5.3 dans les entreprises en 2010/2011

•  Une évolution technologique qui va permettre de continuer le changement des usages et accélérer l’adoption massive de PHP dans les entreprises

•  Ce changement devrait être une fois encore mené par les frameworks

Page 24: Playing With PHP 5.3

PHP 5.3 Parlons technique…

Page 25: Playing With PHP 5.3

PHP 5.3

•  Beaucoup de nouveautés

–  Cosmétiques : __DIR__, ?:, NOWDOC, …

–  Fonctionnelles : i18n, SPL, gestion des dates, mysqlnd, …

–  Structurelles : namespaces, fonctions anonymes, closures, late static binding, phar, support Windows, …

Page 26: Playing With PHP 5.3

PHP 5.3 Le singleton

Page 27: Playing With PHP 5.3

Le singleton nuit gravement à la santé de votre code

Page 28: Playing With PHP 5.3

sfContext dans symfony est “juste” l’exception qui confirme la règle ;)

Page 29: Playing With PHP 5.3

Le Singleton à travers les âges

Page 30: Playing With PHP 5.3

Le Singleton en PHP 4

Pas vraiment possible à cause des limitations du language class Singleton { function &getInstance() { static $instance;

if (!$instance) { $instance = new Singleton(); }

return $instance; } }

$obj =& singleton::getInstance();

on peut toujours

instancier la classe

directement

Page 31: Playing With PHP 5.3

Le Singleton en 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; }

final private function __clone() {} }

$obj = Singleton::getInstance();

ne pas oublier la

méthode __clone()

Page 32: Playing With PHP 5.3

Le Singleton en 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() {} }

Page 33: Playing With PHP 5.3

Le Singleton en PHP 5.3

class Foo extends Singleton {} class Bar extends Singleton {}

$a = Foo::getInstance(); $b = Bar::getInstance();

Page 34: Playing With PHP 5.3

Late Static Binding

__callStatic()

User::find(1)

User::findByUsername('fabien');

Page 35: Playing With PHP 5.3

Fonctions anonymes

Page 36: Playing With PHP 5.3

Fonctions Anonymes

Une fonction anonyme est une fonction déclarée à la volée (sans nom)

function () { echo 'Hello world!'; };

Page 37: Playing With PHP 5.3

Fonctions Anonymes

Pour être affectée à une variable

$hello = function () { echo 'Hello world!'; };

Page 38: Playing With PHP 5.3

Fonctions Anonymes

Puis être utilisée

$hello();

call_user_func($hello);

Page 39: Playing With PHP 5.3

Fonctions Anonymes

et/ou être passé en argument d’une fonction

function foo(Closure $func) { $func(); }

foo($hello);

Page 40: Playing With PHP 5.3

Fonctions anonymes $hello = function ($name) { echo 'Hello '.$name; };

$hello('Fabien');

call_user_func($hello, 'Fabien');

function foo(Closure $func, $name) { $func($name); }

foo($hello, 'Fabien');

Page 41: Playing With PHP 5.3

Que faire avec des fonctions anonymes ?

Page 42: Playing With PHP 5.3

array_*

Simplification de l’usage de

array_map()

array_reduce()

array_filter()

Page 43: Playing With PHP 5.3

Comment récupérer un tableau avec les titres des objets ?

class Article { public function __construct($title) { $this->title = $title; }

public function getTitle() { return $this->title; } }

$articles = array( new Article('Forum PHP 2009 - part 1'), new Article('Forum PHP 2009 - part 2'), new Article('Vivement Noël !'), );

Page 44: Playing With PHP 5.3

$titles = array(); foreach ($articles as $article) { $titles[] = $article->getTitle(); }

100 100

$titles = array_map(create_function('$article', 'return $article->getTitle();'), $articles);

1800 300

$titles = array_map(function ($article) { return $article->getTitle(); }, $articles);

200 100

mémoire rapidité

$mapper = function ($article) { return $article->getTitle(); }; $titles = array_map($mapper, $articles);

180 100

Page 45: Playing With PHP 5.3

Une closure est une fonction anonyme qui se souvient du contexte

dans laquelle elle a été crée…

Page 46: Playing With PHP 5.3

$method = 'getTitle';

$mapper = function ($article) use($method) { return $article->$method(); };

$titles = array_map($mapper, $articles);

Page 47: Playing With PHP 5.3

$mapper = function ($method) { return function ($article) use($method) { return $article->$method(); }; };

$titles = array_map($mapper('getTitle'), $articles);

Page 48: Playing With PHP 5.3

Questions ?

Page 49: Playing With PHP 5.3

Injection de Dépendance

Page 50: Playing With PHP 5.3

« Dependency Injection is where components are given their dependencies through their

constructors, methods, or directly into fields. »

http://www.picocontainer.org/injection.html

Page 51: Playing With PHP 5.3

class Message { public function __construct(array $options) { $this->output = new FancyOutput();

// ... }

// ... }

Impossible de changer la classe FancyOutput par une autre

Page 52: Playing With PHP 5.3

class Message { public function __construct(OutputInterface $output, array $options) { $this->output = $output; $this->options = array_merge(array('with_newline' => false), $options); }

public function say($msg) { $this->output->render($msg.($this->options['with_newline'] ? "\n" : '')); } }

Page 53: Playing With PHP 5.3

interface OutputInterface { public function render($msg); }

class Output implements OutputInterface { public function render($msg) { echo $msg; } }

class FancyOutput implements OutputInterface { public function render($msg) { echo sprintf("\033[33m%s\033[0m", $msg); } }

Page 54: Playing With PHP 5.3

$output = new FancyOutput(); $message = new Message($output, array('with_newline' => true)); $message->say('Hello World');

Page 55: Playing With PHP 5.3

Un container DI permet

de décrire les objets et leurs relations

de les configurer

de les créer

Page 56: Playing With PHP 5.3

class DIContainer { protected $values = array();

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

Page 57: Playing With PHP 5.3

// define the parameters $container->output_class = 'FancyOutput'; $container->with_newline = true;

// defined the objects $container->message = function ($c) { return new Message($c->output, array('with_newline' => $c->with_newline)); };

$container->output = function ($c) { return new $c->output_class(); };

// get the message object $container->message->say('Hello World');

Page 58: Playing With PHP 5.3

spl_object_hash($container->message)

!== spl_object_hash($container->message)

Page 59: Playing With PHP 5.3

$container->message = function ($c) { static $object;

if (is_null($object)) { $object = new Message($c->output, array('with_newline' => $c->with_newline)); }

return $object; };

Page 60: Playing With PHP 5.3

spl_object_hash($container->message)

=== spl_object_hash($container->message)

Page 61: Playing With PHP 5.3

function asShared($callable) { return function ($c) use ($callable) { static $object;

if (is_null($object)) { $object = $callable($c); } return $object; }; }

Page 62: Playing With PHP 5.3

$container->message = $container->asShared(function ($c) { return new Message(

$c->output,

array('with_newline' => $c->with_newline)

); });

Page 63: Playing With PHP 5.3

class DIContainer { 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]; } } }

Page 64: Playing With PHP 5.3

class DIContainer { 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) { return function ($c) use ($callable) { static $object;

if (is_null($object)) { $object = $callable($c); } return $object; }; } }

40 LOC pour un

container DI complet

Page 65: Playing With PHP 5.3

plus d’infos…

http://fabien.potencier.org/article/17/on-php-5-3-lambda-functions-and-closures

http://components.symfony-project.org/dependency-injection/

http://github.com/fabpot/pimple

http://twittee.org/

Page 66: Playing With PHP 5.3

Twittee: A Dependency Injection Container in a tweet

•  Implementation does not use PHP 5.3 •  Its usage needs PHP 5.3

class Container { protected $s=array(); function __set($k, $c) { $this->s[$k]=$c; } function __get($k) { return $this->s[$k]($this); } }

twittee.org

Page 67: Playing With PHP 5.3

Questions ?

Page 68: Playing With PHP 5.3

Observateur

Page 69: Playing With PHP 5.3

Un objet (sujet) maintient une liste d’observateurs et les informe automatiquement

des changements intervenus en appelant une méthode

Page 70: Playing With PHP 5.3

Un dispatcher est un point central permettant de gérer les connections entre les sujets et les observateurs

Page 71: Playing With PHP 5.3

// an anonymous listener $listener = function ($parameters) { echo "Hello {$parameters['name']}\n"; };

// register the listener with the dispatcher $dispatcher = new EventDispatcher(array( 'foo' => $listener, ));

// notify the event somewhere $dispatcher->notify('foo', array('name' => 'Fabien'));

Page 72: Playing With PHP 5.3

class EventDispatcher { function __construct($listeners) { $this->listeners = $listeners; }

function notify($name, $parameters = array()) { $this->listeners[$name]($parameters); } }

Page 73: Playing With PHP 5.3

Comment enregistrer plusieurs observateurs ?

$listener = new EventListeners( function ($parameters) { echo "Hello {$parameters['name']}?\n"; }, function ($parameters) { echo "Hello {$parameters['name']}!\n"; } );

$dispatcher = new EventDispatcher(array( 'foo' => $listener ));

$dispatcher->notify('foo', array('name' => 'Fabien'));

Page 74: Playing With PHP 5.3

class EventListeners { function __construct() { $this->listeners = func_get_args(); }

function __invoke($parameters = array()) { foreach ($this->listeners as $listener) { $listener($parameters); } } }

Page 75: Playing With PHP 5.3

with Matthew Weier O’Pheinney

I will reveal the first alpha release of Symfony 2.0!

symfony-live.com

Page 76: Playing With PHP 5.3

with Matthew Weier O’Pheinney

… with Matthew Weier O'Phinney as a special guest

symfony-live.com

Page 77: Playing With PHP 5.3

Questions?

Page 78: Playing With PHP 5.3

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/