playing with php 5.3

Post on 15-Jan-2015

6.624 Views

Category:

Technology

3 Downloads

Preview:

Click to see full reader

DESCRIPTION

 

TRANSCRIPT

Jouons avec PHP 5.3

Fabien Potencier

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

Fabien Potencier

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

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

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

Migrer vers PHP 5.3 Des raisons techniques

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

PHP 5.3 Beaucoup plus rapide ?

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

Doctrine 1.X and 2.0

Significativement plus rapide avec PHP 5.3

30% de mémoire en moins

20% plus rapide

symfony 1.X

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

-47%

Migrer vers PHP 5.3 Des raisons fonctionnelles

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

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

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

Les namespaces dans Symfony 2

Symfony\Components Symfony\Foundation Symfony\Framework

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

Symfony\Components\EventDispatcher\Event

vs

sfEvent

Le nom des classes

n’est pas plus court !

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();

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

PHP 5.3 L’apport pour les entreprises

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

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

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

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

PHP 5.3 Parlons technique…

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, …

PHP 5.3 Le singleton

Le singleton nuit gravement à la santé de votre code

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

Le Singleton à travers les âges

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

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()

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

Le Singleton en PHP 5.3

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

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

Late Static Binding

__callStatic()

User::find(1)

User::findByUsername('fabien');

Fonctions anonymes

Fonctions Anonymes

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

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

Fonctions Anonymes

Pour être affectée à une variable

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

Fonctions Anonymes

Puis être utilisée

$hello();

call_user_func($hello);

Fonctions Anonymes

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

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

foo($hello);

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');

Que faire avec des fonctions anonymes ?

array_*

Simplification de l’usage de

array_map()

array_reduce()

array_filter()

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 !'), );

$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

Une closure est une fonction anonyme qui se souvient du contexte

dans laquelle elle a été crée…

$method = 'getTitle';

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

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

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

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

Questions ?

Injection de Dépendance

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

constructors, methods, or directly into fields. »

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

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

// ... }

// ... }

Impossible de changer la classe FancyOutput par une autre

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" : '')); } }

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

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

Un container DI permet

de décrire les objets et leurs relations

de les configurer

de les créer

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

// 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');

spl_object_hash($container->message)

!== spl_object_hash($container->message)

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

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

return $object; };

spl_object_hash($container->message)

=== spl_object_hash($container->message)

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

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

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

$c->output,

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

); });

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

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

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/

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

Questions ?

Observateur

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

des changements intervenus en appelant une méthode

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

// 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'));

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

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

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'));

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

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

with Matthew Weier O’Pheinney

I will reveal the first alpha release of Symfony 2.0!

symfony-live.com

with Matthew Weier O’Pheinney

… with Matthew Weier O'Phinney as a special guest

symfony-live.com

Questions?

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/

top related