Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to DI(C)

Introduction to DI(C)

Quick introduction to Dependency Injection (Container).

Radek Benkel

May 21, 2012
Tweet

More Decks by Radek Benkel

Other Decks in Technology

Transcript

  1. $speaker = new Speaker; $speaker->name = "Radosław Benkel"; $speaker->twitter =

    "@singlespl"; $speaker->blog = "http://blog.rbenkel.me"; $speaker->givePresentation(); About me
  2. Dependency class TwitterAPIClient { protected $httpClient; public function __construct() {

    $this->httpClient = new SomeCurlWrapper(); } /* ... */ } $client = new TwitterApiClient;
  3. Dependency class TwitterAPIClient { protected $httpClient; public function __construct() {

    $this->httpClient = new SomeCurlWrapper(); } /* ... */ } $client = new TwitterApiClient; This
  4. Injection class TwitterAPIClient { protected $httpClient; public function __construct($httpClient) {

    $this->httpClient = $httpClient; } /* ... */ } $client = new TwitterApiClient(new SomeCurlWrapper); And
  5. Injection public function __construct() { $this->httpClient = new SomeCurlWrapper(); }

    public function __construct($httpClient) { $this->httpClient = $httpClient; } VS
  6. Constructor injection Injection class TwitterAPIClient { protected $httpClient; public function

    __construct($httpClient) { $this->httpClient = $httpClient; } /* ... */ } $client = new TwitterApiClient(new SomeCurlWrapper);
  7. Setter injection Injection class TwitterAPIClient { protected $httpClient; public function

    __construct() {} public function setHttpClient($httpClient) { $this->httpClient = $httpClient; } /* ... */ } $client = new TwitterApiClient; $client->setHttpClient(new SomeCurlWrapper);
  8. Interface injection Injection interface 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);
  9. 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'));
  10. Container require_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'));
  11. Container require_once "container_dev.php"; $mapper = $container->get('mapper.user'); /* mapper is UserMapperDB,

    with different PDO configuration. */ $mapper->save(new User('John', 'Doe'));
  12. Container require_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')); Find
  13. Container require_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'));
  14. Container require_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')); Find
  15. Container require_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')); Find
  16. What it does: Container • injects object dependencies • creates

    objects on demand • objects could be shared • (and sometimes other stuff, like tagging, XML/ JSON/YAML config etc. )
  17. Container class 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; } } }
  18. Container class 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; } } } *
  19. 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'));
  20. Injection require_once "container_prod.php"; $mapper = $container->get('mapper.user'); /* mapper is UserMapperEncrypted,

    which uses UserMapperCached (using Redis for cache), which uses UserMapperDB, which uses PDO. */ $mapper->save(new User('John', 'Doe'));
  21. 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') ); });
  22. 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') ); });
  23. 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') ); });
  24. Injection require_once "container_prod.php"; $mapper = $container->get('mapper.user'); /* mapper is UserMapperEncrypted,

    which uses UserMapperCached (using Apc for cache), which uses UserMapperDB, which uses PDO. */ $mapper->save(new User('John', 'Doe'));
  25. • AuraDI http://auraphp.github.com/Aura.Di/ • Pimple http://pimple.sensiolabs.org/ • Symfony Dependency Injection

    Component http://symfony.com/doc/current/components/dependency_injection/ introduction.html • ZF Dependency Injection http://framework.zend.com/wiki/display/ZFDEV /Zend+DI+QuickStart • Twittee http://twittee.org/ Container
  26. • AuraDI http://auraphp.github.com/Aura.Di/ • Pimple http://pimple.sensiolabs.org/ • Symfony Dependency Injection

    Component http://symfony.com/doc/current/components/dependency_injection/ introduction.html • ZF Dependency Injection http://framework.zend.com/wiki/display/ZFDEV /Zend+DI+QuickStart • Twittee http://twittee.org/ Container PHP
  27. • AuraDI http://auraphp.github.com/Aura.Di/ • Pimple http://pimple.sensiolabs.org/ • Symfony Dependency Injection

    Component http://symfony.com/doc/current/components/dependency_injection/ introduction.html • ZF Dependency Injection http://framework.zend.com/wiki/display/ZFDEV /Zend+DI+QuickStart • Twittee http://twittee.org/ Container Small,
  28. • AuraDI http://auraphp.github.com/Aura.Di/ • Pimple http://pimple.sensiolabs.org/ • Symfony Dependency Injection

    Component http://symfony.com/doc/current/components/dependency_injection/ introduction.html • ZF Dependency Injection http://framework.zend.com/wiki/display/ZFDEV /Zend+DI+QuickStart • Twittee http://twittee.org/ Container Lot’s
  29. • AuraDI http://auraphp.github.com/Aura.Di/ • Pimple http://pimple.sensiolabs.org/ • Symfony Dependency Injection

    Component http://symfony.com/doc/current/components/dependency_injection/ introduction.html • ZF Dependency Injection http://framework.zend.com/wiki/display/ZFDEV /Zend+DI+QuickStart • Twittee http://twittee.org/ Container Fits