SlideShare une entreprise Scribd logo
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 ?
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
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




                                                                                                   -47%


symfony project running on PHP 5.2 vs PHP 5.3 profiled with XHPROF (run 4aeeb7d54b732 is PHP 5.3)
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
                                   Fin 2010
   –  Zend Framework 2.0


•  Interopérabilité améliorée entre ces bibliothèques,
   grâce aux namespaces
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
SymfonyComponents
SymfonyFoundation
SymfonyFramework

SymfonyComponentsEventDispatcherEvent
SymfonyFoundationClassLoader
SymfonyComponentsEventDispatcherEvent


                   vs


                sfEvent

                           L e nom des classes
                           n’es t 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 SymfonyFoundationClassLoader;
use SymfonyComponentsDependencyInjectionBuilder;
use SymfonyComponentsDependencyInjectionReference;
use SymfonyComponentsDependencyInjectionLoader
XmlFileLoader;
use SymfonyComponentsDependencyInjectionDumperPhpDumper;




                                              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();
        }
                                                        on peut toujours
        return $instance;                              in stancier la classe
}
    }
                                                            directement
$obj =& singleton::getInstance();
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;
    }                                            ne pas oublier la
    final private function __clone() {}         mé thode __clone()
}

$obj = Singleton::getInstance();
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);

                                                                            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

      mémoire       rapidité
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%s033[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;                                                                      40 LOC pour un
          if (is_null($object))
          {
            $object = $callable($c);
                                                                                          co ntainer DI complet
          }
          return $object;
        };
    }
}
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); }
}

                                  witte e.org
                                t
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);
      }
    }
}
symfony-live.com
           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
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/

Contenu connexe

PDF
PHP 7 et Symfony 3
PDF
Javascript ne se limite pas à jquery
PPTX
Introduction à Python
PPTX
Symfony2 - Un Framework PHP 5 Performant
PPTX
Formation python 3
PDF
PPT
.php1 : les fondamentaux du PHP
PDF
Communications Réseaux et HTTP avec PHP
PHP 7 et Symfony 3
Javascript ne se limite pas à jquery
Introduction à Python
Symfony2 - Un Framework PHP 5 Performant
Formation python 3
.php1 : les fondamentaux du PHP
Communications Réseaux et HTTP avec PHP

Tendances (18)

PDF
Ce bon vieux propel
PDF
PHP 1 - Apprendre les bases
PDF
Atoum, le framework de tests unitaires pour PHP 5.3 simple, moderne et intuit...
PPT
Cours php
PPTX
JavaScript prise en main et fondamentaux
PPTX
cpp1 : Quelques elements de base du C++
PPTX
php2 : formulaire-session-PDO
PPTX
Introduction au Jquery
PPT
Php cours
PDF
Programmation Orientée Objet et les Traits en PHP 5.4
PDF
Programmation orientée objet en PHP 5
PDF
Les listes en Python
PDF
Programmation orientée objet : Object, classe et encapsulation
KEY
Exploiter php 5
PDF
Notions de base de JavaScript
PPTX
Introduction à jQuery
PPTX
Initiation à l'algorithmique
PDF
Nouveautés php 7
Ce bon vieux propel
PHP 1 - Apprendre les bases
Atoum, le framework de tests unitaires pour PHP 5.3 simple, moderne et intuit...
Cours php
JavaScript prise en main et fondamentaux
cpp1 : Quelques elements de base du C++
php2 : formulaire-session-PDO
Introduction au Jquery
Php cours
Programmation Orientée Objet et les Traits en PHP 5.4
Programmation orientée objet en PHP 5
Les listes en Python
Programmation orientée objet : Object, classe et encapsulation
Exploiter php 5
Notions de base de JavaScript
Introduction à jQuery
Initiation à l'algorithmique
Nouveautés php 7
Publicité

Similaire à Playing With PHP 5.3 (20)

PPTX
Php 5.3
ODP
Présentation de PHP 5.4 [FR]
ODP
Migration PHP4-PHP5
PPT
PHP 5.3, PHP Next
PDF
Php 7.4 2020-01-28 - afup
PDF
PHP 5.3 : les nouveautés du futur si proche
PDF
Objets patterns et genie logiciel , par Julien Pauli
ODP
Patterns and OOP in PHP
PPT
PHP5 et Zend Framework
PDF
PHP : retour vers le futur !
PDF
Chapitre5_Cours_TechProgWeb_LI2 mr Malek .pdf
PPT
Soutenance Zend Framework vs Symfony
PPT
Introduction au langage PHP (1ere partie) élaborée par Marouan OMEZZINE
PDF
Utiliser le Zend Framework avec Symfony
PDF
Etes vous-pret pour php8 ?
ODP
Formation PHP avancé - Cake PHP
PPTX
La première partie de la présentation PHP
PPTX
PHP_S4.pptx
PDF
Mieux Développer en PHP avec Symfony
PPTX
S2-01-PHP.pptx
Php 5.3
Présentation de PHP 5.4 [FR]
Migration PHP4-PHP5
PHP 5.3, PHP Next
Php 7.4 2020-01-28 - afup
PHP 5.3 : les nouveautés du futur si proche
Objets patterns et genie logiciel , par Julien Pauli
Patterns and OOP in PHP
PHP5 et Zend Framework
PHP : retour vers le futur !
Chapitre5_Cours_TechProgWeb_LI2 mr Malek .pdf
Soutenance Zend Framework vs Symfony
Introduction au langage PHP (1ere partie) élaborée par Marouan OMEZZINE
Utiliser le Zend Framework avec Symfony
Etes vous-pret pour php8 ?
Formation PHP avancé - Cake PHP
La première partie de la présentation PHP
PHP_S4.pptx
Mieux Développer en PHP avec Symfony
S2-01-PHP.pptx
Publicité

Plus de Fabien Potencier (20)

PDF
PDF
Look beyond PHP
PDF
Dependency injection in PHP 5.3/5.4
PDF
Dependency injection-zendcon-2010
PDF
Caching on the Edge
PDF
Design patterns revisited with PHP 5.3
PDF
The state of Symfony2 - SymfonyDay 2010
PDF
PhpBB meets Symfony2
PDF
Dependency injection - phpday 2010
PDF
Symfony2 - WebExpo 2010
PDF
Symfony2 - WebExpo 2010
PDF
Symfony2 - OSIDays 2010
PDF
Dependency Injection IPC 201
PDF
Caching on the Edge with Symfony2
PDF
Unit and Functional Testing with Symfony2
PDF
News of the Symfony2 World
PDF
Dependency Injection - ConFoo 2010
PDF
Dependency Injection
PDF
Symfony Components
PDF
PHP 5.3 in practice
Look beyond PHP
Dependency injection in PHP 5.3/5.4
Dependency injection-zendcon-2010
Caching on the Edge
Design patterns revisited with PHP 5.3
The state of Symfony2 - SymfonyDay 2010
PhpBB meets Symfony2
Dependency injection - phpday 2010
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
Symfony2 - OSIDays 2010
Dependency Injection IPC 201
Caching on the Edge with Symfony2
Unit and Functional Testing with Symfony2
News of the Symfony2 World
Dependency Injection - ConFoo 2010
Dependency Injection
Symfony Components
PHP 5.3 in practice

Playing With PHP 5.3

  • 1. Jouons avec PHP 5.3 Fabien Potencier
  • 2. 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
  • 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/
  • 4. Migrer vers PHP 5.3 Des raisons techniques
  • 5. 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
  • 8. 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
  • 9. Doctrine 1.X and 2.0 Significativement plus rapide avec PHP 5.3 30% de mémoire en moins 20% plus rapide
  • 10. symfony 1.X -47% symfony project running on PHP 5.2 vs PHP 5.3 profiled with XHPROF (run 4aeeb7d54b732 is PHP 5.3)
  • 11. Migrer vers PHP 5.3 Des raisons fonctionnelles
  • 12. 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 Fin 2010 –  Zend Framework 2.0 •  Interopérabilité améliorée entre ces bibliothèques, grâce aux namespaces
  • 13. 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
  • 14. 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
  • 15. Les namespaces dans Symfony 2 SymfonyComponents SymfonyFoundation SymfonyFramework SymfonyComponentsEventDispatcherEvent SymfonyFoundationClassLoader
  • 16. SymfonyComponentsEventDispatcherEvent vs sfEvent L e nom des classes n’es t pas plus court !
  • 17. 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();
  • 18. Les namespaces dans Symfony 2 require __DIR__.'/lib/Symfony/Core/ClassLoader.php'; use SymfonyFoundationClassLoader; use SymfonyComponentsDependencyInjectionBuilder; use SymfonyComponentsDependencyInjectionReference; use SymfonyComponentsDependencyInjectionLoader XmlFileLoader; use SymfonyComponentsDependencyInjectionDumperPhpDumper; Bonne pratique
  • 19. PHP 5.3 L’apport pour les entreprises
  • 20. 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
  • 21. 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
  • 22. 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
  • 23. 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
  • 25. 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, …
  • 27. Le singleton nuit gravement à la santé de votre code
  • 28. sfContext dans symfony est “juste” l’exception qui confirme la règle ;)
  • 29. Le Singleton à travers les âges
  • 30. Le Singleton en PHP 4 Pas vraiment possible à cause des limitations du language class Singleton { function &getInstance() { static $instance; if (!$instance) { $instance = new Singleton(); } on peut toujours return $instance; in stancier la classe } } directement $obj =& singleton::getInstance();
  • 31. 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; } ne pas oublier la final private function __clone() {} mé thode __clone() } $obj = Singleton::getInstance();
  • 32. 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() {} }
  • 33. Le Singleton en PHP 5.3 class Foo extends Singleton {} class Bar extends Singleton {} $a = Foo::getInstance(); $b = Bar::getInstance();
  • 34. Late Static Binding __callStatic() User::find(1) User::findByUsername('fabien');
  • 36. Fonctions Anonymes Une fonction anonyme est une fonction déclarée à la volée (sans nom) function () { echo 'Hello world!'; };
  • 37. Fonctions Anonymes Pour être affectée à une variable $hello = function () { echo 'Hello world!'; };
  • 38. Fonctions Anonymes Puis être utilisée $hello(); call_user_func($hello);
  • 39. Fonctions Anonymes et/ou être passé en argument d’une fonction function foo(Closure $func) { $func(); } foo($hello);
  • 40. 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');
  • 41. Que faire avec des fonctions anonymes ?
  • 42. array_* Simplification de l’usage de array_map() array_reduce() array_filter()
  • 43. 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 !'), );
  • 44. $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 mémoire rapidité
  • 45. Une closure est une fonction anonyme qui se souvient du contexte dans laquelle elle a été crée…
  • 46. $method = 'getTitle'; $mapper = function ($article) use($method) { return $article->$method(); }; $titles = array_map($mapper, $articles);
  • 47. $mapper = function ($method) { return function ($article) use($method) { return $article->$method(); }; }; $titles = array_map($mapper('getTitle'), $articles);
  • 50. « Dependency Injection is where components are given their dependencies through their constructors, methods, or directly into fields. » http://www.picocontainer.org/injection.html
  • 51. class Message { public function __construct(array $options) { $this->output = new FancyOutput(); // ... } // ... } Impossible de changer la classe FancyOutput par une autre
  • 52. 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" : '')); } }
  • 53. 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%s033[0m", $msg); } }
  • 54. $output = new FancyOutput(); $message = new Message($output, array('with_newline' => true)); $message->say('Hello World');
  • 55. Un container DI permet de décrire les objets et leurs relations de les configurer de les créer
  • 56. 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]; } } }
  • 57. // 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');
  • 58. spl_object_hash($container->message) !== spl_object_hash($container->message)
  • 59. $container->message = function ($c) { static $object; if (is_null($object)) { $object = new Message($c->output, array('with_newline' => $c->with_newline)); } return $object; };
  • 60. spl_object_hash($container->message) === spl_object_hash($container->message)
  • 61. function asShared($callable) { return function ($c) use ($callable) { static $object; if (is_null($object)) { $object = $callable($c); } return $object; }; }
  • 62. $container->message = $container->asShared(function ($c) { return new Message( $c->output, array('with_newline' => $c->with_newline) ); });
  • 63. 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]; } } }
  • 64. 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; 40 LOC pour un if (is_null($object)) { $object = $callable($c); co ntainer DI complet } return $object; }; } }
  • 66. 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); } } witte e.org t
  • 69. Un objet (sujet) maintient une liste d’observateurs et les informe automatiquement des changements intervenus en appelant une méthode
  • 70. Un dispatcher est un point central permettant de gérer les connections entre les sujets et les observateurs
  • 71. // 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'));
  • 72. class EventDispatcher { function __construct($listeners) { $this->listeners = $listeners; } function notify($name, $parameters = array()) { $this->listeners[$name]($parameters); } }
  • 73. 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'));
  • 74. class EventListeners { function __construct() { $this->listeners = func_get_args(); } function __invoke($parameters = array()) { foreach ($this->listeners as $listener) { $listener($parameters); } } }
  • 75. symfony-live.com with Matthew Weier O’Pheinney I will reveal the first alpha release of Symfony 2.0!
  • 76. symfony-live.com with Matthew Weier O’Pheinney … with Matthew Weier O'Phinney as a special guest
  • 78. 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/