Dependency Injection in PHP

1,935,050 views
1,936,597 views

Published on

Slides from my talk during PHPCon Poland.
Szczyrk 25/10/2013

3 Comments
20 Likes
Statistics
Notes
No Downloads
Views
Total views
1,935,050
On SlideShare
0
From Embeds
0
Number of Embeds
2,632
Actions
Shares
0
Downloads
109
Comments
3
Likes
20
Embeds 0
No embeds

No notes for slide

Dependency Injection in PHP

  1. Dependency Injection in PHP PHPCon Poland Szczyrk 25/10/13 ! by @cakper flickr.com/limowreck666/223731385/
  2. Kacper Gunia // @cakper Software Engineer @SensioLabsUK Symfony Certified Developer #Symfony-PL // SymfonyLab.pl Silesian PHP User Group // SPUG.pl
  3. Inversion of Control Dependency Injection Events Aspect Oriented Programming flickr.com/goetter/4559773791/
  4. Diving into Dependency Injection flickr.com/haniamir/651043585/
  5. Dependency Injection ! ! class  DvdPlayer   {          public  function  playDisc(Disc  $disc)          {                  echo  'Now  playing:  '.$disc-­‐>getMovieTitle();   !                $tv  =  new  Tv('Samsung  40"');                  $tv-­‐>sendToOutput($disc-­‐>getResource());          }   }
  6. Dependency Injection class  DvdPlayer   {          private  $tv;   !        public  function  __construct()          {                  $this-­‐>tv  =  new  Tv('Samsung  40"');;          }   !        public  function  playDisc(Disc  $disc)          {                  echo  'Now  playing:  '  .  $disc-­‐>getMovieTitle();                  $this-­‐>tv-­‐>sendToOutput($disc-­‐>getResource());          }   }
  7. Dependency Injection class  DvdPlayer   {          private  $tv;   !        public  function  __construct(Tv  $tv)          {                  $this-­‐>tv  =  $tv;          }  //  (...)   }   ! $tv  =  new  Tv('Samsung  40"');   $dvdPlayer  =  new  DvdPlayer($tv);
  8. Dependency Injection class  DvdPlayer   {          private  $device;   !        public  function  __construct(HdmiDevice  $device)          {                  $this-­‐>device  =  $device;          }  //  (...)   }   ! $projector  =  new  Projector('Epson  EB');   $dvdPlayer  =  new  DvdPlayer($tv);
  9. Nailed it!
  10. “Dependency Injection 
 is where components are given their dependencies through their constructors, methods, or directly into fields.” ! “(...) it is a 25-dollar term for a 5-cent concept” source: picocontainer.codehaus.org jamesshore.com
  11. Types of Injection Constructor Setter Property Reflection flickr.com/jensfinke/4417602702/
  12. Constructor Injection class  Tv  implements  HdmiDevice{}   class  DvdPlayer   {          private  $device;   !        public  function  __construct(HdmiDevice  $device)          {                  $this-­‐>device  =  $device;          }   }   ! $tv  =  new  Tv('Samsung  40"');   $dvdPlayer  =  new  DvdPlayer($tv);
  13. Setter Injection class  BlurayDisc  implements  Disc{}   class  DvdPlayer   {          private  $disc;   !        public  function  setDisc(Disc  $disc)          {                  $this-­‐>disc  =  $disc;          }   }   ! $disc  =  new  BlurayDisc('Pulp  Fiction');   $dvdPlayer  =  new  DvdPlayer();   $dvdPlayer-­‐>setDisc($disc);
  14. Property Injection class  DvdPlayer   {          public  $remote;   }   ! $dvdPlayer  =  new  DvdPlayer();   $dvdPlayer-­‐>remote  =  new  Remote();
  15. Reflection Injection class  DvdPlayer   {          private  $powerSupply;   }   ! $dvdPlayer  =  new  DvdPlayer();   $reflector  =  new  ReflectionClass($dvdPlayer);   $powerSupply  =  $reflector-­‐>getProperty('powerSupply');   $powerSupply-­‐>setAccessible(true);   ! $powerSupply-­‐>setValue($dvdPlayer,  new  PowerSupply());
  16. Pros & Cons flickr.com/paperpariah/3589690234/
  17. Advantage #1 Decoupling flickr.com/roonster/3387705446/
  18. Advantage #2 Dependency Inversion Principle flickr.com/antonsiniorg/1876733029/
  19. Advantage #3 Reusability flickr.com/ejpphoto/2314610838/
  20. Advantage #4 Clean code flickr.com/38659937@N06/4020413080/
  21. Advantage #5 Easier testing flickr.com/nattu/895220635/
  22. Advantage #6 Instance management flickr.com/34094515@N00/3817086937/
  23. Advantage #7 IDE support flickr.com/gavin_fordham/9407339641/
  24. Disadvantage Complex initialisation flickr.com/toniblay/52445415/
  25. Simple Solution Factory flickr.com/lenscrack/5577431429/
  26. Proper Solution Dependency Injection Container flickr.com/thomashawk/24089964/
  27. “Dependency Injection Container is simply a PHP object that manages the instantiation of other objects” ! We call them “Services” source: symfony.com
  28. Our DvdPlayer ! ! $tv  =  new  Tv('Samsung  40"');   $dvdPlayer  =  new  DvdPlayer($tv);   ! $disc  =  new  Disc('Pulp  Fiction');   $dvdPlayer-­‐>playDisc($disc);
  29. Simple Container class class  Container   {          public  function  getTv()          {                  return  new  Tv('Samsung  40"');          }   !        public  function  getDvdPlayer()          {                  return  new  DvdPlayer($this-­‐>getTv());          }   }
  30. Container use ! ! $container  =  new  Container();   ! $dvdPlayer  =  $container-­‐>getDvdPlayer();   ! $disc  =  new  Disc('Pulp  Fiction');   $dvdPlayer-­‐>playDisc($disc);
  31. DIC Implementations Twittee Pimple PHP-DI  ZendDi IlluminateContainer OrnoDi LeagueDi SymfonyDependencyInjection  flickr.com/smb_flickr/313116995/
  32. DI & DIC Patterns flickr.com/thelearningcurvedotca/8645721482/
  33. Pattern #1 Expect Interfaces, not Implementations flickr.com/deapeajay/2969264395/
  34. Pattern #2 Don’t check null values flickr.com/g-ratphotos/3328593629/
  35. class  DvdPlayer   {          public  $disc;   !        public  function  play()          {                  if  (!is_null($this-­‐>disc))  {                          $this-­‐>sendToOutput($this-­‐>disc-­‐>getResource());                  }          }   !        public  function  play()          {                  if  ($this-­‐>disc  instanceof  Disc)  {                          $this-­‐>sendToOutput($this-­‐>disc-­‐>getResource());                  }          }   }
  36. Pattern #3 Avoid ‘Service Locator’ flickr.com/mateus27_24-25/2224073271/
  37. class  DvdPlayer   {          private  $locator;   !        public  function  __construct()          {                  $this-­‐>locator  =  ServiceLocator::getInstance();          }   ! !        public  function  playDisc(Disc  $disc)          {                  $this-­‐>locator                            -­‐>getTv()                            -­‐>sendToOutput($disc-­‐>getResource());          }   }
  38. Pattern #4 Don’t inject whole container flickr.com/ucumari/580865728/
  39. Pattern #5 In DIC store Services and Properties, but not Entities flickr.com/madlyinlovewithlife/8674850717/
  40. Pattern #6 Don’t be afraid to create plenty of small Classes flickr.com/geoki/2691420977/
  41. Symfony DIC in action
  42. Services new  Tv('Samsung  40”’)   ! services:      tv:          class:            Tv          arguments:    [“Samsung  40"”]  
  43. Parameters new  Tv('Samsung  40”’)   ! parameters:      tv_name:    Samsung  40"  
  44. Parameters & Services new  Tv('Samsung  40”’)   ! parameters:      tv_name:    Samsung  40"   ! services:      tv:          class:            Tv          arguments:    [“%tv_name%”]   ! $container-­‐>get('tv');
  45. Compiled Container ! ! ! ! protected  function  getTvService()   {          return  $this-­‐>services['tv']  =  new  Tv('Samsung');   }  
  46. Static Factory services:          tv                  class:                    Tv                    factory_class:    TvFactory                  factory_method:  get
  47. Factory services:          tv_factory:                  class:                      TvFactory          tv                  class:                      Tv                    factory_service:  tv_factory                  factory_method:    get
  48. Optional Dependencies class  DvdPlayer   {      function  __construct(HdmiDevice  $device  =  null){}   }   ! services:      tv:          class:            Tv          arguments:    [%tv_name%]      dvd_player:              class:        DvdPlayer              arguments  ["@?tv"]  
  49. Lazy-loaded Services services:      tv:          class:            Tv          arguments:    [“%tv_name%”]       lazy:         true
  50. Private Services services:      drm_decryptor:          class:            DrmDecryptor       public:       false      dvd_player:              class:        DvdPlayer              arguments  [“@drm_decryptor”]
  51. Scopes services:      tv:          class:            Tv          arguments:    [“%tv_name%”]       scope:       prototype
  52. PHPStorm support Adrien Brault sxc.hu/photo/228094/
  53. Questions? ! Thank you! :) ! joind.in/9760 flickr.com/eole/3809742516/

×