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




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

Playing With PHP 5.3

  • 1.
    Jouons avec PHP5.3 Fabien Potencier
  • 2.
    Fabien Potencier •  Serialentrepreneur 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 •  Monblog technique : http://fabien.potencier.org/ •  Sur Twitter : http://www.twitter.com/fabpot •  Mon code sur Github: http://github.com/fabpot/
  • 4.
    Migrer vers PHP5.3 Des raisons techniques
  • 5.
    Migrer vers PHP5.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
  • 6.
  • 8.
    Dmitry Stogov a faitquelques 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 and2.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 PHP5.3 Des raisons fonctionnelles
  • 12.
    Migrer vers PHP5.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 technicalinteroperability 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 ? •  Lesbibliothè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 dansSymfony 2 SymfonyComponents SymfonyFoundation SymfonyFramework SymfonyComponentsEventDispatcherEvent SymfonyFoundationClassLoader
  • 16.
    SymfonyComponentsEventDispatcherEvent vs sfEvent L e nom des classes n’es t pas plus court !
  • 17.
    Les namespaces dansSymfony 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 dansSymfony 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 pourles entreprises
  • 20.
    PHP 5 dansles 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, unerupture 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 PHP5.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 dansles 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
  • 24.
  • 25.
    PHP 5.3 •  Beaucoupde nouveautés –  Cosmétiques : __DIR__, ?:, NOWDOC, … –  Fonctionnelles : i18n, SPL, gestion des dates, mysqlnd, … –  Structurelles : namespaces, fonctions anonymes, closures, late static binding, phar, support Windows, …
  • 26.
  • 27.
    Le singleton nuitgravement à 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 enPHP 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 enPHP 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 enPHP 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 enPHP 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');
  • 35.
  • 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 desfonctions anonymes ?
  • 42.
    array_* Simplification de l’usagede array_map() array_reduce() array_filter()
  • 43.
    Comment récupérer untableau 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 estune 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);
  • 48.
  • 49.
  • 50.
    « Dependency Injection iswhere 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 = newFancyOutput(); $message = new Message($output, array('with_newline' => true)); $message->say('Hello World');
  • 55.
    Un container DIpermet 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 theparameters $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; }; } }
  • 65.
  • 66.
    Twittee: A DependencyInjection 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
  • 67.
  • 68.
  • 69.
    Un objet (sujet) maintientune liste d’observateurs et les informe automatiquement des changements intervenus en appelant une méthode
  • 70.
    Un dispatcher estun point central permettant de gérer les connections entre les sujets et les observateurs
  • 71.
    // an anonymouslistener $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 plusieursobservateurs ? $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
  • 77.
  • 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/