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