SlideShare a Scribd company logo
Dependency
Injection in PHP

PHPCon Poland
Szczyrk 25/10/13

!

by @cakper
flickr.com/limowreck666/223731385/
Kacper Gunia // @cakper
Software Engineer @SensioLabsUK
Symfony Certified Developer
#Symfony-PL // SymfonyLab.pl
Silesian PHP User Group // SPUG.pl
Inversion of Control
Dependency Injection
Events
Aspect Oriented
Programming
flickr.com/goetter/4559773791/
Diving into
Dependency Injection

flickr.com/haniamir/651043585/
Dependency Injection
!
!

class	
  DvdPlayer	
  
{	
  
	
  	
  	
  	
  public	
  function	
  playDisc(Disc	
  $disc)	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  echo	
  'Now	
  playing:	
  '.$disc-­‐>getMovieTitle();	
  
!

	
  	
  	
  	
  	
  	
  	
  	
  $tv	
  =	
  new	
  Tv('Samsung	
  40"');	
  
	
  	
  	
  	
  	
  	
  	
  	
  $tv-­‐>sendToOutput($disc-­‐>getResource());	
  
	
  	
  	
  	
  }	
  
}
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());	
  
	
  	
  	
  	
  }	
  
}
Dependency Injection
class	
  DvdPlayer	
  
{	
  
	
  	
  	
  	
  private	
  $tv;	
  
!

	
  	
  	
  	
  public	
  function	
  __construct(Tv	
  $tv)	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>tv	
  =	
  $tv;	
  
	
  	
  	
  	
  }	
  //	
  (...)	
  
}	
  
!

$tv	
  =	
  new	
  Tv('Samsung	
  40"');	
  
$dvdPlayer	
  =	
  new	
  DvdPlayer($tv);
Dependency Injection
class	
  DvdPlayer	
  
{	
  
	
  	
  	
  	
  private	
  $device;	
  
!

	
  	
  	
  	
  public	
  function	
  __construct(HdmiDevice	
  $device)	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>device	
  =	
  $device;	
  
	
  	
  	
  	
  }	
  //	
  (...)	
  
}	
  
!

$projector	
  =	
  new	
  Projector('Epson	
  EB');	
  
$dvdPlayer	
  =	
  new	
  DvdPlayer($tv);
Nailed it!
“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
Types of Injection
Constructor
Setter
Property
Reflection
flickr.com/jensfinke/4417602702/
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);
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);
Property Injection
class	
  DvdPlayer	
  
{	
  
	
  	
  	
  	
  public	
  $remote;	
  
}	
  
!

$dvdPlayer	
  =	
  new	
  DvdPlayer();	
  
$dvdPlayer-­‐>remote	
  =	
  new	
  Remote();
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());
Pros & Cons

flickr.com/paperpariah/3589690234/
Advantage #1

Decoupling

flickr.com/roonster/3387705446/
Advantage #2

Dependency
Inversion Principle

flickr.com/antonsiniorg/1876733029/
Advantage #3

Reusability

flickr.com/ejpphoto/2314610838/
Advantage #4

Clean code

flickr.com/38659937@N06/4020413080/
Advantage #5

Easier testing

flickr.com/nattu/895220635/
Advantage #6

Instance
management

flickr.com/34094515@N00/3817086937/
Advantage #7

IDE support

flickr.com/gavin_fordham/9407339641/
Disadvantage

Complex
initialisation

flickr.com/toniblay/52445415/
Simple Solution

Factory

flickr.com/lenscrack/5577431429/
Proper Solution

Dependency Injection
Container

flickr.com/thomashawk/24089964/
“Dependency Injection
Container is simply a PHP
object that manages the
instantiation of other objects”
!

We call them “Services”
source: symfony.com
Our DvdPlayer
!
!

$tv	
  =	
  new	
  Tv('Samsung	
  40"');	
  
$dvdPlayer	
  =	
  new	
  DvdPlayer($tv);	
  
!

$disc	
  =	
  new	
  Disc('Pulp	
  Fiction');	
  
$dvdPlayer-­‐>playDisc($disc);
Simple Container class
class	
  Container	
  
{	
  
	
  	
  	
  	
  public	
  function	
  getTv()	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  new	
  Tv('Samsung	
  40"');	
  
	
  	
  	
  	
  }	
  
!

	
  	
  	
  	
  public	
  function	
  getDvdPlayer()	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  new	
  DvdPlayer($this-­‐>getTv());	
  
	
  	
  	
  	
  }	
  
}
Container use
!
!

$container	
  =	
  new	
  Container();	
  
!

$dvdPlayer	
  =	
  $container-­‐>getDvdPlayer();	
  
!

$disc	
  =	
  new	
  Disc('Pulp	
  Fiction');	
  
$dvdPlayer-­‐>playDisc($disc);
DIC Implementations
Twittee

Pimple

PHP-DI 

ZendDi

IlluminateContainer

OrnoDi

LeagueDi

SymfonyDependencyInjection 
flickr.com/smb_flickr/313116995/
DI & DIC Patterns

flickr.com/thelearningcurvedotca/8645721482/
Pattern #1

Expect Interfaces,
not Implementations

flickr.com/deapeajay/2969264395/
Pattern #2

Don’t check null values

flickr.com/g-ratphotos/3328593629/
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());	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  }	
  
}
Pattern #3

Avoid ‘Service Locator’

flickr.com/mateus27_24-25/2224073271/
class	
  DvdPlayer	
  
{	
  
	
  	
  	
  	
  private	
  $locator;	
  
!

	
  	
  	
  	
  public	
  function	
  __construct()	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>locator	
  =	
  ServiceLocator::getInstance();	
  
	
  	
  	
  	
  }	
  
!
!

	
  	
  	
  	
  public	
  function	
  playDisc(Disc	
  $disc)	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>locator	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>getTv()	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>sendToOutput($disc-­‐>getResource());	
  
	
  	
  	
  	
  }	
  
}
Pattern #4

Don’t inject whole
container

flickr.com/ucumari/580865728/
Pattern #5

In DIC store
Services and Properties,
but not Entities

flickr.com/madlyinlovewithlife/8674850717/
Pattern #6

Don’t be afraid to create
plenty of small Classes

flickr.com/geoki/2691420977/
Symfony DIC
in action
Services
new	
  Tv('Samsung	
  40”’)	
  
!

services:	
  
	
  	
  tv:	
  
	
  	
  	
  	
  class:	
  	
  	
  	
  	
  	
  Tv	
  
	
  	
  	
  	
  arguments:	
  	
  [“Samsung	
  40"”]	
  
Parameters
new	
  Tv('Samsung	
  40”’)	
  
!

parameters:	
  
	
  	
  tv_name:	
  	
  Samsung	
  40"	
  
Parameters & Services
new	
  Tv('Samsung	
  40”’)	
  
!

parameters:	
  
	
  	
  tv_name:	
  	
  Samsung	
  40"	
  
!

services:	
  
	
  	
  tv:	
  
	
  	
  	
  	
  class:	
  	
  	
  	
  	
  	
  Tv	
  
	
  	
  	
  	
  arguments:	
  	
  [“%tv_name%”]	
  
!

$container-­‐>get('tv');
Compiled Container
!
!
!
!

protected	
  function	
  getTvService()	
  
{	
  
	
  	
  	
  	
  return	
  $this-­‐>services['tv']	
  =	
  new	
  Tv('Samsung');	
  
}	
  
Static Factory
services:	
  
	
  	
  	
  	
  tv	
  
	
  	
  	
  	
  	
  	
  	
  	
  class:	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Tv	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  factory_class:	
  	
  TvFactory	
  
	
  	
  	
  	
  	
  	
  	
  	
  factory_method:	
  get
Factory
services:	
  
	
  	
  	
  	
  tv_factory:	
  
	
  	
  	
  	
  	
  	
  	
  	
  class:	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  TvFactory	
  
	
  	
  	
  	
  tv	
  
	
  	
  	
  	
  	
  	
  	
  	
  class:	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Tv	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  factory_service:	
  tv_factory	
  
	
  	
  	
  	
  	
  	
  	
  	
  factory_method:	
  	
  get
Optional Dependencies
class	
  DvdPlayer	
  
{	
  
	
  	
  function	
  __construct(HdmiDevice	
  $device	
  =	
  null){}	
  
}	
  
!

services:	
  
	
  	
  tv:	
  
	
  	
  	
  	
  class:	
  	
  	
  	
  	
  	
  Tv	
  
	
  	
  	
  	
  arguments:	
  	
  [%tv_name%]	
  
	
  	
  dvd_player:	
  
	
  	
  	
  	
  	
  	
  class:	
  	
  	
  	
  DvdPlayer	
  
	
  	
  	
  	
  	
  	
  arguments	
  ["@?tv"]	
  
Lazy-loaded Services
services:	
  
	
  	
  tv:	
  
	
  	
  	
  	
  class:	
  	
  	
  	
  	
  	
  Tv	
  
	
  	
  	
  	
  arguments:	
  	
  [“%tv_name%”]	
  
	
   	
   lazy:	
  	
   	
   	
   true
Private Services
services:	
  
	
  	
  drm_decryptor:	
  
	
  	
  	
  	
  class:	
  	
  	
  	
  	
  	
  DrmDecryptor	
  
	
   	
   public:	
  	
   	
   false	
  
	
  	
  dvd_player:	
  
	
  	
  	
  	
  	
  	
  class:	
  	
  	
  	
  DvdPlayer	
  
	
  	
  	
  	
  	
  	
  arguments	
  [“@drm_decryptor”]
Scopes
services:	
  
	
  	
  tv:	
  
	
  	
  	
  	
  class:	
  	
  	
  	
  	
  	
  Tv	
  
	
  	
  	
  	
  arguments:	
  	
  [“%tv_name%”]	
  
	
   	
   scope:	
   	
   	
   prototype
PHPStorm
support
Adrien Brault

sxc.hu/photo/228094/
Questions?
!

Thank you! :)
!

joind.in/9760
flickr.com/eole/3809742516/

More Related Content

Dependency Injection in PHP