Introduction to DI(C)
-
Upload
radek-benkel -
Category
Technology
-
view
1.974 -
download
3
description
Transcript of Introduction to DI(C)
![Page 2: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/2.jpg)
$speaker = new Speaker;
$speaker->name = "Radosław Benkel";$speaker->twitter = "@singlespl";$speaker->blog = "http://blog.rbenkel.me";
$speaker->givePresentation();
About me
![Page 3: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/3.jpg)
What?
![Page 4: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/4.jpg)
DependencyInjectionContainer
What?
![Page 5: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/5.jpg)
Dependency
What?
![Page 6: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/6.jpg)
Dependency
class TwitterAPIClient{ protected $httpClient; public function __construct() { $this->httpClient = new SomeCurlWrapper(); } /* ... */}
$client = new TwitterApiClient;
![Page 7: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/7.jpg)
Dependency
class TwitterAPIClient{ protected $httpClient; public function __construct() { $this->httpClient = new SomeCurlWrapper(); } /* ... */}
$client = new TwitterApiClient;
This����������� ������������������ is����������� ������������������ your����������� ������������������ dependency.
![Page 8: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/8.jpg)
“What’s����������� ������������������ wrong����������� ������������������ with����������� ������������������ that”?
Dependency
![Page 9: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/9.jpg)
Try testing it...
Dependency
![Page 10: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/10.jpg)
...or change client implementation
Dependency
![Page 11: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/11.jpg)
Dependency
![Page 12: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/12.jpg)
So let’s use Injection
Dependency
![Page 13: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/13.jpg)
Injection
What?
![Page 14: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/14.jpg)
Injection
class TwitterAPIClient{ protected $httpClient; public function __construct($httpClient) { $this->httpClient = $httpClient; } /* ... */}
$client = new TwitterApiClient(new SomeCurlWrapper);
And����������� ������������������ here����������� ������������������ you����������� ������������������ inject����������� ������������������ dependency
![Page 15: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/15.jpg)
So...
Injection
![Page 16: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/16.jpg)
Injection
public function __construct(){ $this->httpClient = new SomeCurlWrapper();}
public function __construct($httpClient){ $this->httpClient = $httpClient;}
VS
![Page 17: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/17.jpg)
it’s just like...
Injection
![Page 18: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/18.jpg)
Injection
VS
![Page 19: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/19.jpg)
Injection
VS
Try����������� ������������������ replacing����������� ������������������ battery,����������� ������������������ and����������� ������������������ you����������� ������������������ will����������� ������������������ now����������� ������������������ what����������� ������������������ I’m����������� ������������������ talking����������� ������������������ about.����������� ������������������
![Page 20: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/20.jpg)
Injection types:
Injection
![Page 21: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/21.jpg)
Injection types:
Injection
• constructor injection
![Page 22: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/22.jpg)
Injection types:
Injection
• constructor injection• setter injection
![Page 23: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/23.jpg)
Injection types:
Injection
• constructor injection• setter injection• interface injection
![Page 24: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/24.jpg)
Constructor injection
Injection
class TwitterAPIClient{ protected $httpClient; public function __construct($httpClient) { $this->httpClient = $httpClient; } /* ... */}$client = new TwitterApiClient(new SomeCurlWrapper);
![Page 25: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/25.jpg)
Setter injection
Injection
class TwitterAPIClient{ protected $httpClient; public function __construct() {} public function setHttpClient($httpClient) { $this->httpClient = $httpClient; } /* ... */}$client = new TwitterApiClient;$client->setHttpClient(new SomeCurlWrapper);
![Page 26: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/26.jpg)
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);
![Page 27: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/27.jpg)
So far so good...
Injection
![Page 28: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/28.jpg)
...until you don’t have to do something like
that:
Injection
![Page 29: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/29.jpg)
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'));
![Page 30: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/30.jpg)
Injection
![Page 31: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/31.jpg)
Injection
“How����������� ������������������ to����������� ������������������ solve����������� ������������������ that”?
![Page 32: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/32.jpg)
Just use...
Injection
![Page 33: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/33.jpg)
Container
What?
![Page 34: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/34.jpg)
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'));
![Page 35: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/35.jpg)
Container
require_once "container_dev.php";
$mapper = $container->get('mapper.user');
/* mapper is UserMapperDB, with different PDO configuration. */$mapper->save(new User('John', 'Doe'));
![Page 36: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/36.jpg)
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����������� ������������������ the����������� ������������������ difference
![Page 37: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/37.jpg)
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'));
![Page 38: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/38.jpg)
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����������� ������������������ the����������� ������������������ differenceConfigures����������� ������������������ services����������� ������������������ in����������� ������������������ different����������� ������������������ way,����������� ������������������ but����������� ������������������ for����������� ������������������ you,����������� ������������������ API����������� ������������������ for����������� ������������������ mapper����������� ������������������ is����������� ������������������ the����������� ������������������ same.
![Page 39: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/39.jpg)
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����������� ������������������ the����������� ������������������ difference*����������� ������������������ Assuming,����������� ������������������ that����������� ������������������ all����������� ������������������ mappers����������� ������������������ share����������� ������������������ the����������� ������������������ same����������� ������������������ interface,����������� ������������������ which����������� ������������������ they����������� ������������������ rather����������� ������������������ should.
![Page 40: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/40.jpg)
So, DIC it’s something like:
Container
![Page 41: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/41.jpg)
Container
![Page 42: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/42.jpg)
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. )
![Page 43: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/43.jpg)
So. Lets write simple one.
Container
![Page 44: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/44.jpg)
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; } }}
![Page 45: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/45.jpg)
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; } }}
*����������� ������������������ Inspired����������� ������������������ by����������� ������������������ Pimple
![Page 46: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/46.jpg)
Lets use that.
Injection
![Page 47: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/47.jpg)
Replacing this:
Injection
![Page 48: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/48.jpg)
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'));
![Page 49: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/49.jpg)
with this:
Injection
![Page 50: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/50.jpg)
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'));
![Page 51: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/51.jpg)
Because everything is configured in container...
Injection
![Page 52: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/52.jpg)
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')
);});
![Page 53: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/53.jpg)
...you can change e.g cache adapter...
Injection
![Page 54: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/54.jpg)
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') );});
![Page 55: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/55.jpg)
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') );});
![Page 56: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/56.jpg)
...and your your code hasn’t changed at all.
Injection
![Page 57: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/57.jpg)
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'));
![Page 58: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/58.jpg)
But probably, you should use another
DIC:
Container
![Page 59: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/59.jpg)
• AuraDIhttp://auraphp.github.com/Aura.Di/
• Pimplehttp://pimple.sensiolabs.org/
• Symfony % Dependency Injection Componenthttp://symfony.com/doc/current/components/dependency_injection/introduction.html
• ZF% Dependency Injectionhttp://framework.zend.com/wiki/display/ZFDEV%/Zend+DI+QuickStart
• Twitteehttp://twittee.org/
Container
![Page 60: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/60.jpg)
• AuraDIhttp://auraphp.github.com/Aura.Di/
• Pimplehttp://pimple.sensiolabs.org/
• Symfony % Dependency Injection Componenthttp://symfony.com/doc/current/components/dependency_injection/introduction.html
• ZF% Dependency Injectionhttp://framework.zend.com/wiki/display/ZFDEV%/Zend+DI+QuickStart
• Twitteehttp://twittee.org/
Container
PHP����������� ������������������ 5.4����������� ������������������ only
![Page 61: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/61.jpg)
• AuraDIhttp://auraphp.github.com/Aura.Di/
• Pimplehttp://pimple.sensiolabs.org/
• Symfony % Dependency Injection Componenthttp://symfony.com/doc/current/components/dependency_injection/introduction.html
• ZF% Dependency Injectionhttp://framework.zend.com/wiki/display/ZFDEV%/Zend+DI+QuickStart
• Twitteehttp://twittee.org/
Container
Small,����������� ������������������ basic
![Page 62: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/62.jpg)
• AuraDIhttp://auraphp.github.com/Aura.Di/
• Pimplehttp://pimple.sensiolabs.org/
• Symfony % Dependency Injection Componenthttp://symfony.com/doc/current/components/dependency_injection/introduction.html
• ZF% Dependency Injectionhttp://framework.zend.com/wiki/display/ZFDEV%/Zend+DI+QuickStart
• Twitteehttp://twittee.org/
Container
Lot’s����������� ������������������ of����������� ������������������ features
![Page 63: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/63.jpg)
• AuraDIhttp://auraphp.github.com/Aura.Di/
• Pimplehttp://pimple.sensiolabs.org/
• Symfony % Dependency Injection Componenthttp://symfony.com/doc/current/components/dependency_injection/introduction.html
• ZF% Dependency Injectionhttp://framework.zend.com/wiki/display/ZFDEV%/Zend+DI+QuickStart
• Twitteehttp://twittee.org/
Container
Fits����������� ������������������ into����������� ������������������ tweet!
![Page 64: Introduction to DI(C)](https://reader033.fdocuments.us/reader033/viewer/2022061114/54625968b1af9f7d228b4e27/html5/thumbnails/64.jpg)
Thank you!