Introduction to DI(C)
Upcoming SlideShare
Loading in...5
×
 

Introduction to DI(C)

on

  • 1,933 views

Quick introduction to Dependency Injection (Container).

Quick introduction to Dependency Injection (Container).

Statistics

Views

Total Views
1,933
Views on SlideShare
1,932
Embed Views
1

Actions

Likes
1
Downloads
12
Comments
0

1 Embed 1

https://si0.twimg.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Introduction to DI(C) Introduction to DI(C) Presentation Transcript

  • Introduction to DI(C)meet.php #5 http://meetphp.pl/ 19.05.2012
  • About me$speaker = new Speaker;$speaker->name = "Radosław Benkel";$speaker->twitter = "@singlespl";$speaker->blog = "http://blog.rbenkel.me";$speaker->givePresentation();
  • What?
  • What?DependencyInjectionContainer
  • What?Dependency
  • Dependencyclass TwitterAPIClient{ protected $httpClient; public function __construct() { $this->httpClient = new SomeCurlWrapper(); } /* ... */}$client = new TwitterApiClient;
  • Dependency This
  •   is
  •   your
  •   dependency.class TwitterAPIClient{ protected $httpClient; public function __construct() { $this->httpClient = new SomeCurlWrapper(); } /* ... */}$client = new TwitterApiClient;
  • Dependency“What’s
  •   wrong
  •   with
  •    that”?
  • DependencyTry testing it...
  • Dependency...or change client implementation
  • Dependency
  • DependencySo let’s use Injection
  • What?Injection
  • Injectionclass TwitterAPIClient{ protected $httpClient; public function __construct($httpClient) { $this->httpClient = $httpClient; } /* ... */} And
  •   here
  •   you
  •   inject
  •   dependency$client = new TwitterApiClient(new SomeCurlWrapper);
  • Injection So...
  • Injectionpublic function __construct(){ $this->httpClient = new SomeCurlWrapper();} VSpublic function __construct($httpClient){ $this->httpClient = $httpClient;}
  • Injectionit’s just like...
  • Injection VS
  • Injection VSTry
  •   replacing
  •   battery,
  •   and
  •   you
  •   will
  •   now
  •   what
  •   I’m
  •   talking
  •    about.
  •   
  • InjectionInjection types:
  • Injection Injection types:• constructor injection
  • Injection Injection types:• constructor injection• setter injection
  • Injection Injection types:• constructor injection• setter injection• interface injection
  • Injection Constructor injectionclass TwitterAPIClient{ protected $httpClient; public function __construct($httpClient) { $this->httpClient = $httpClient; } /* ... */}$client = new TwitterApiClient(new SomeCurlWrapper);
  • Injection Setter injectionclass TwitterAPIClient{ protected $httpClient; public function __construct() {} public function setHttpClient($httpClient) { $this->httpClient = $httpClient; } /* ... */}$client = new TwitterApiClient;$client->setHttpClient(new SomeCurlWrapper);
  • 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);
  • InjectionSo far so good...
  • Injection...until you don’t have to do something like that:
  • 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));
  • Injection
  • Injection“How
  •   to
  •   solve
  •   that”?
  • InjectionJust use...
  • What?Container
  • 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));
  • Containerrequire_once "container_dev.php";$mapper = $container->get(mapper.user);/* mapper is UserMapperDB, with different PDO configuration.*/$mapper->save(new User(John, Doe));
  • Containerrequire_once "container_prod.php";$mapper = $container->get(mapper.user);$mapper->save(new User(John, Doe)); Find
  •   the
  •   differencerequire_once "container_dev.php";$mapper = $container->get(mapper.user);$mapper->save(new User(John, Doe));
  • 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));
  • Containerrequire_once "container_prod.php";$mapper = $container->get(mapper.user);$mapper->save(new User(John, Doe)); Find
  •   the
  •   difference Configures
  •   services
  •   in
  •   different
  •   way,
  •   but
  •    for
  •   you,
  •   API
  •   for
  •   mapper
  •   is
  •   the
  •   same.require_once "container_dev.php";$mapper = $container->get(mapper.user);$mapper->save(new User(John, Doe));
  • Containerrequire_once "container_prod.php";$mapper = $container->get(mapper.user);$mapper->save(new User(John, Doe)); *
  •   Assuming,
  •   tthe
  •   difference the
  •    Find
  •    hat
  •   all
  •   mappers
  •   share
  •   same
  •   interface,
  •   which
  •   they
  •   rather
  •   should.require_once "container_dev.php";$mapper = $container->get(mapper.user);$mapper->save(new User(John, Doe));
  • ContainerSo, DIC it’s something like:
  • Container
  • 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. )
  • ContainerSo. Lets write simple one.
  • 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; } }}
  • Containerclass Container{ protected $items = array(); *
  •   Inspired
  •   by
  •   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; } }}
  • InjectionLets use that.
  • InjectionReplacing this:
  • 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));
  • Injectionwith this:
  • 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));
  • InjectionBecause everything is configured in container...
  • 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) );});
  • Injection...you can change e.g cache adapter...
  • 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) );});
  • 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) );});
  • Injection...and your your codehasn’t changed at all.
  • 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));
  • Container But probably, youshould use another DIC:
  • 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/
  • Container• AuraDI PHP
  •   5.4
  •   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/
  • Container• AuraDI http://auraphp.github.com/Aura.Di/• Pimple Small,
  •   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/
  • Container• AuraDI Lot’s
  •   of
  •   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/
  • 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
  •   into
  •   tweet!
  • Thank you!