[FR] Injection de dépendances, Containers & PHP-DI

432 views
338 views

Published on

[French]
Présentation du principe d'injection de dépendances, des containers et de PHP-DI.

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
432
On SlideShare
0
From Embeds
0
Number of Embeds
20
Actions
Shares
0
Downloads
12
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

[FR] Injection de dépendances, Containers & PHP-DI

  1. 1. INJECTION DE DÉPENDANCES, CONTAINERS & PHP-DI
  2. 2. BONJOUR MATTHIEU NAPOLI My C-Sense ( myclabs ), Lyon mnapoli.fr / @matthieunapoli github.com/mnapoli PHP-DI Container d'injection de dépendances depuis Mars 2012
  3. 3. DI ≠ DIC
  4. 4. INJECTION DE DÉPENDANCES Construire son code pour ne plus créer ses dépendances => méthode CONTAINER Construit des objets et injecte les dépendances => outil
  5. 5. INJECTION DE DÉPENDANCES
  6. 6. WORKFLOW D'UN CODE CLASSIQUE Application : $foo = new FooController(); $foo->loginAction(); Classe FooController : public function loginAction() { $bar = new Bar(); // ou $bar = Bar::getInstance() $bar->doSomething(); } Classe Bar : public function doSomething() { $bim = new Bim(); // ou $bim = Bim::getInstance() $bim->doSomethingElse(); }
  7. 7. WORKFLOW D'UN CODE CLASSIQUE => dépendances choisies lors de l'écriture du code (hard-coded) Tests : tester du code qui utilise un service web, des fichiers, une BDD, du cache, … Extensibilité : mon système de log loggue dans un fichier, j'aimerai qu'il écrive en BDD et les envoie par email… Coupling : je veux changer de système de cache (ou sa config) -> je dois changer le code partout…
  8. 8. TRANSFORMATION
  9. 9. TRANSFORMATION Avant : class FooController { public function loginAction() { $bar = new Bar(); // ou $bar = Bar::getInstance() $bar->doSomething(); } } Après : class FooController { private $bar; public function __construct(Bar $bar) { $this->bar = $bar; } public function loginAction() { $this->bar->doSomething(); } }
  10. 10. WORKFLOW D'UN CODE UTILISANT L'INJECTION DE DÉPENDANCES Application : $bim = new Bim(); $bar = new Bar($bim); $foo = new FooController($bar); $foo->loginAction(); Classe FooController : public function loginAction() { $this->bar->doSomething(); } Classe Bar : public function doSomething() { $this->bim->doSomethingElse(); }
  11. 11. INVERSION OF CONTROL => dépendances choisies lors de l'exécution Possibilité de remplacer les dépendances injectées Dans les classes, on ne gère plus les dépendances, leurs configurations… Code plus générique : code against interfaces
  12. 12. CODE AGAINST INTERFACES class StoreService { public function __construct(GeolocationService $geolocationService) { … } } interface GeolocationService { public function getCoordinates($address); } class GoogleMaps implements GeolocationService { … } class OpenStreetMap implements GeolocationService { … }
  13. 13. MAIS Nécessite de gérer les dépendances dans l'application $bim = new Bim(); $bar = new Bar($bim); $foo = new FooController($bar);
  14. 14. CONTAINER
  15. 15. WORKFLOW D'UN CODE UTILISANT UN CONTAINER Application : $foo = $container->get('FooController'); $foo->doSomething(); Classe FooController : public function loginAction() { $this->bar->doSomething(); } Classe Bar : public function doSomething() { $this->bim->doSomethingElse(); }
  16. 16. $foo = $container->get('FooController'); = $bim = new Bim(); $bar = new Bar($bim); $foo = new FooController($bar);
  17. 17. Le container fait les injections, et aide à construire les graphes d'objets
  18. 18. ATTENTION ! $foo = $container->get('FooController'); Service Locator : anti-pattern
  19. 19. CONFIGURATION DU CONTAINER Nécessite de configurer le container pour qu'il injecte les bons objets Chaque container se configure différement
  20. 20. EXEMPLE SIMPLE $container = new Container(); $bim = new Bim(); $bar = new Bar($bim); $container->set('Bim', $bim); $container->set('Bar', $bar); Problème : initialise tous les objets à chaque requête
  21. 21. CALLBACKS $container = new Container(); $container->set('Bim', function() { return new Bim(); }); $container->set('Bar', function() use ($container) { return new Bar($bim); }); Verbeux, mais efficace
  22. 22. FICHIERS DE CONFIGURATION Tableau PHP YAML XML … Formats différents pour chaque librairie
  23. 23. Symfony DI ZendDi (+ tous les autres) Pimple Aura DI Laravel Mouf Orno PPI …
  24. 24. PHP-DI
  25. 25. POURQUOI ? Pratique Volontairement copieur Framework-agnostic
  26. 26. PHP-DI v1.0 (août 2012) : injections via annotations (PC) v2.0 (décembre 2012) : refactoring, version stable v3.0 (avril 2013) : annotations, config PHP, YAML, … … v3.5 (octobre 2013)
  27. 27. REFLECTION Résolution de dépendances intelligente class Foo { public function __construct(Bar $param1) { } } ~ 90% des cas -> 0 configuration
  28. 28. ANNOTATIONS Inspiré de Java/Spring use DIAnnotationInject; class UserController { /** * @Inject */ private $userRepository; public function loginAction($email, $password) { $user = $this->userRepository->login($email, $password); // ... } } Pas la solution à tout, mais très pratique dans les contrôleurs
  29. 29. CONFIGURATION PHP $container->set('Bar'); $container->set('Foo') ->withConstructor(array('Bar')); $container->set('MyInterface') ->bindTo('MyImplementation');
  30. 30. YAML Bar: Foo: constructor: [ Bar ] MyInterface: class: MyImplementation
  31. 31. FUTUR PHP-DI : v4.0, intégration avec d'autres frameworks PHP-FIG : collaboration pour une PSR ContainerInterface Communauté : diffusion, meilleure doc et best-practices dans ZF2 et Symfony 2…
  32. 32. MERCI Site officiel : php-di.org GitHub : mnapoli/PHP-DI Twitter : @PHPDI

×