Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Dependency Injection in PHP

1,940,451 views

Published on

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

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/

×