Dependency Injection in PHP

  • 10,066 views
Uploaded on

Slides from my talk during PHPCon Poland. …

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

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
10,066
On Slideshare
0
From Embeds
0
Number of Embeds
26

Actions

Shares
Downloads
73
Comments
3
Likes
19

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

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