Introduction to DI(C)

  • 1,705 views
Uploaded on

Quick introduction to Dependency Injection (Container).

Quick introduction to Dependency Injection (Container).

More in: Technology , Business
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,705
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
13
Comments
0
Likes
1

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. Introduction to DI(C)meet.php #5 http://meetphp.pl/ 19.05.2012
  • 2. About me$speaker = new Speaker;$speaker->name = "Radosław Benkel";$speaker->twitter = "@singlespl";$speaker->blog = "http://blog.rbenkel.me";$speaker->givePresentation();
  • 3. What?
  • 4. What?DependencyInjectionContainer
  • 5. What?Dependency
  • 6. Dependencyclass TwitterAPIClient{ protected $httpClient; public function __construct() { $this->httpClient = new SomeCurlWrapper(); } /* ... */}$client = new TwitterApiClient;
  • 7. Dependency This
  • 8.   is
  • 9.   your
  • 10.   dependency.class TwitterAPIClient{ protected $httpClient; public function __construct() { $this->httpClient = new SomeCurlWrapper(); } /* ... */}$client = new TwitterApiClient;
  • 11. Dependency“What’s
  • 12.   wrong
  • 13.   with
  • 14.    that”?
  • 15. DependencyTry testing it...
  • 16. Dependency...or change client implementation
  • 17. Dependency
  • 18. DependencySo let’s use Injection
  • 19. What?Injection
  • 20. Injectionclass TwitterAPIClient{ protected $httpClient; public function __construct($httpClient) { $this->httpClient = $httpClient; } /* ... */} And
  • 21.   here
  • 22.   you
  • 23.   inject
  • 24.   dependency$client = new TwitterApiClient(new SomeCurlWrapper);
  • 25. Injection So...
  • 26. Injectionpublic function __construct(){ $this->httpClient = new SomeCurlWrapper();} VSpublic function __construct($httpClient){ $this->httpClient = $httpClient;}
  • 27. Injectionit’s just like...
  • 28. Injection VS
  • 29. Injection VSTry
  • 30.   replacing
  • 31.   battery,
  • 32.   and
  • 33.   you
  • 34.   will
  • 35.   now
  • 36.   what
  • 37.   I’m
  • 38.   talking
  • 39.    about.
  • 40.   
  • 41. InjectionInjection types:
  • 42. Injection Injection types:• constructor injection
  • 43. Injection Injection types:• constructor injection• setter injection
  • 44. Injection Injection types:• constructor injection• setter injection• interface injection
  • 45. Injection Constructor injectionclass TwitterAPIClient{ protected $httpClient; public function __construct($httpClient) { $this->httpClient = $httpClient; } /* ... */}$client = new TwitterApiClient(new SomeCurlWrapper);
  • 46. Injection Setter injectionclass TwitterAPIClient{ protected $httpClient; public function __construct() {} public function setHttpClient($httpClient) { $this->httpClient = $httpClient; } /* ... */}$client = new TwitterApiClient;$client->setHttpClient(new SomeCurlWrapper);
  • 47. Injection Interface injectioninterface HttpClientInterface { public function setHttpClient($httpClient);}class TwitterAPIClient implements HttpClientInterface { protected $httpClient; public function __construct() {} public function setHttpClient($httpClient) { $this->httpClient = $httpClient; } /* ... */}$client = new TwitterApiClient;$client->setHttpClient(new SomeCurlWrapper);
  • 48. InjectionSo far so good...
  • 49. Injection...until you don’t have to do something like that:
  • 50. Injection$mapper = new UserMapperEncrypted( new UserMapperCached( new UserMapperDB( new PDO( mysql:host=127.0.0.1, user, password ) ), new RedisCacheAdapter( 127.0.0.1:6379 ) ), YourSuperSecretPass);$mapper->save(new User(John, Doe));
  • 51. Injection
  • 52. Injection“How
  • 53.   to
  • 54.   solve
  • 55.   that”?
  • 56. InjectionJust use...
  • 57. What?Container
  • 58. Containerrequire_once "container_prod.php";$mapper = $container->get(mapper.user);/* mapper is UserMapperEncrypted, which uses UserMapperCached,which uses UserMapperDB, which uses PDO. */$mapper->save(new User(John, Doe));
  • 59. Containerrequire_once "container_dev.php";$mapper = $container->get(mapper.user);/* mapper is UserMapperDB, with different PDO configuration.*/$mapper->save(new User(John, Doe));
  • 60. Containerrequire_once "container_prod.php";$mapper = $container->get(mapper.user);$mapper->save(new User(John, Doe)); Find
  • 61.   the
  • 62.   differencerequire_once "container_dev.php";$mapper = $container->get(mapper.user);$mapper->save(new User(John, Doe));
  • 63. Containerrequire_once "container_prod.php";$mapper = $container->get(mapper.user);$mapper->save(new User(John, Doe));require_once "container_dev.php";$mapper = $container->get(mapper.user);$mapper->save(new User(John, Doe));
  • 64. Containerrequire_once "container_prod.php";$mapper = $container->get(mapper.user);$mapper->save(new User(John, Doe)); Find
  • 65.   the
  • 66.   difference Configures
  • 67.   services
  • 68.   in
  • 69.   different
  • 70.   way,
  • 71.   but
  • 72.    for
  • 73.   you,
  • 74.   API
  • 75.   for
  • 76.   mapper
  • 77.   is
  • 78.   the
  • 79.   same.require_once "container_dev.php";$mapper = $container->get(mapper.user);$mapper->save(new User(John, Doe));
  • 80. Containerrequire_once "container_prod.php";$mapper = $container->get(mapper.user);$mapper->save(new User(John, Doe)); *
  • 81.   Assuming,
  • 82.   tthe
  • 83.   difference the
  • 84.    Find
  • 85.    hat
  • 86.   all
  • 87.   mappers
  • 88.   share
  • 89.   same
  • 90.   interface,
  • 91.   which
  • 92.   they
  • 93.   rather
  • 94.   should.require_once "container_dev.php";$mapper = $container->get(mapper.user);$mapper->save(new User(John, Doe));
  • 95. ContainerSo, DIC it’s something like:
  • 96. Container
  • 97. Container What it does:• injects object dependencies• creates objects on demand• objects could be shared• (and sometimes other stuff, like tagging, XML/ JSON/YAML config etc. )
  • 98. ContainerSo. Lets write simple one.
  • 99. Containerclass Container{ protected $items = array(); public function get($key) { $item = $this->items[$key]; return is_callable($item) ? $item($this) : $item; } public function set($key, $value, $shared = false) { if ($shared === true && is_callable($value)) { $this->items[$key] = function($c) use ($value) { static $obj; if (!$obj) { $obj = $value($c); } return $obj; }; } else { $this->items[$key] = $value; } }}
  • 100. Containerclass Container{ protected $items = array(); *
  • 101.   Inspired
  • 102.   by
  • 103.   Pimple public function get($key) { $item = $this->items[$key]; return is_callable($item) ? $item($this) : $item; } public function set($key, $value, $shared = false) { if ($shared === true && is_callable($value)) { $this->items[$key] = function($c) use ($value) { static $obj; if (!$obj) { $obj = $value($c); } return $obj; }; } else { $this->items[$key] = $value; } }}
  • 104. InjectionLets use that.
  • 105. InjectionReplacing this:
  • 106. Injection$mapper = new UserMapperEncrypted( new UserMapperCached( new UserMapperDB( new PDO( mysql:host=127.0.0.1, user, password ) ), new RedisCacheAdapter( 127.0.0.1:6379 ) ), YourSuperSecretPass);$mapper->save(new User(John, Doe));
  • 107. Injectionwith this:
  • 108. Injectionrequire_once "container_prod.php";$mapper = $container->get(mapper.user);/* mapper is UserMapperEncrypted, which uses UserMapperCached(using Redis for cache), which uses UserMapperDB, which usesPDO. */$mapper->save(new User(John, Doe));
  • 109. InjectionBecause everything is configured in container...
  • 110. Injection//container_prod.php$c = new Container();$c->set(pdo.dsn, mysql:host=127.0.0.1);$c->set(pdo.user, user);$c->set(pdo.pass, password);$c->set(redis.host, 127.0.0.1:6379);$c->set(mcrypt.key, YourSuperSecretPass);$c->set(pdo, function(Container $c) { return new PDO( $c->get(pdo.dsn), $c->get(pdo.user), $c->get(pdo.pass), );}, true);$c->set(cache.adapter, function(Container $c) { return new RedisCacheAdapter($c->get(redis.host));});$c->set(mapper.user, function(Container $c) { return new UserMapperEncrypted( new UserMapperCached( new UserMapperDB($c->get(pdo)), $c->get(cache.adapter) ), $c->get(mcrypt.key) );});
  • 111. Injection...you can change e.g cache adapter...
  • 112. Injection//container_prod.php$c = new Container();$c->set(pdo.dsn, mysql:host=127.0.0.1);$c->set(pdo.user, user);$c->set(pdo.pass, password);$c->set(mcrypt.key, YourSuperSecretPass);$c->set(pdo, function(Container $c) { return new PDO( $c->get(pdo.dsn), $c->get(pdo.user), $c->get(pdo.pass), );}, true);$c->set(cache.adapter, function(Container $c) { return new ApcCacheAdapter();});$c->set(mapper.user, function(Container $c) { return new UserMapperEncrypted( new UserMapperCached( new UserMapperDB($c->get(pdo)), $c->get(cache.adapter) ), $c->get(mcrypt.key) );});
  • 113. Injection//container_prod.php$c = new Container();$c->set(pdo.dsn, mysql:host=127.0.0.1);$c->set(pdo.user, user);$c->set(pdo.pass, password);$c->set(mcrypt.key, YourSuperSecretPass);$c->set(pdo, function(Container $c) { return new PDO( $c->get(pdo.dsn), $c->get(pdo.user), $c->get(pdo.pass), );}, true);$c->set(cache.adapter, function(Container $c) { return new ApcCacheAdapter();});$c->set(mapper.user, function(Container $c) { return new UserMapperEncrypted( new UserMapperCached( new UserMapperDB($c->get(pdo)), $c->get(cache.adapter) ), $c->get(mcrypt.key) );});
  • 114. Injection...and your your codehasn’t changed at all.
  • 115. Injectionrequire_once "container_prod.php";$mapper = $container->get(mapper.user);/* mapper is UserMapperEncrypted, which uses UserMapperCached(using Apc for cache), which uses UserMapperDB, which usesPDO. */$mapper->save(new User(John, Doe));
  • 116. Container But probably, youshould use another DIC:
  • 117. Container• AuraDI http://auraphp.github.com/Aura.Di/• Pimple http://pimple.sensiolabs.org/• Symfony 2 Dependency Injection Component http://symfony.com/doc/current/components/dependency_injection/ introduction.html• ZF2 Dependency Injection http://framework.zend.com/wiki/display/ZFDEV2/Zend+DI+QuickStart• Twittee http://twittee.org/
  • 118. Container• AuraDI PHP
  • 119.   5.4
  • 120.   only http://auraphp.github.com/Aura.Di/• Pimple http://pimple.sensiolabs.org/• Symfony 2 Dependency Injection Component http://symfony.com/doc/current/components/dependency_injection/ introduction.html• ZF2 Dependency Injection http://framework.zend.com/wiki/display/ZFDEV2/Zend+DI+QuickStart• Twittee http://twittee.org/
  • 121. Container• AuraDI http://auraphp.github.com/Aura.Di/• Pimple Small,
  • 122.   basic http://pimple.sensiolabs.org/• Symfony 2 Dependency Injection Component http://symfony.com/doc/current/components/dependency_injection/ introduction.html• ZF2 Dependency Injection http://framework.zend.com/wiki/display/ZFDEV2/Zend+DI+QuickStart• Twittee http://twittee.org/
  • 123. Container• AuraDI Lot’s
  • 124.   of
  • 125.   features http://auraphp.github.com/Aura.Di/• Pimple http://pimple.sensiolabs.org/• Symfony 2 Dependency Injection Component http://symfony.com/doc/current/components/dependency_injection/ introduction.html• ZF2 Dependency Injection http://framework.zend.com/wiki/display/ZFDEV2/Zend+DI+QuickStart• Twittee http://twittee.org/
  • 126. Container• AuraDI http://auraphp.github.com/Aura.Di/• Pimple http://pimple.sensiolabs.org/• Symfony 2 Dependency Injection Component http://symfony.com/doc/current/components/dependency_injection/ introduction.html• ZF2 Dependency Injection http://framework.zend.com/wiki/display/ZFDEV2/Zend+DI+QuickStart• Twittee http://twittee.org/ Fits
  • 127.   into
  • 128.   tweet!
  • 129. Thank you!