Download - Dependency injection in PHP 5.3/5.4
![Page 2: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/2.jpg)
Dependency Injection
A real world « web » example
![Page 3: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/3.jpg)
In most web applications, you need to manage the user preferences
– The user language– Whether the user is authenticated or not– The user credentials– …
![Page 4: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/4.jpg)
This can be done with a User object
–setLanguage(), getLanguage()–setAuthenticated(), isAuthenticated()–addCredential(), hasCredential()–...
![Page 5: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/5.jpg)
The User informationneed to be persisted
between HTTP requests
We use the PHP session for the Storage
![Page 6: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/6.jpg)
class SessionStorage{ function __construct($cookieName = 'PHP_SESS_ID') { session_name($cookieName); session_start(); }
function set($key, $value) { $_SESSION[$key] = $value; }
// ...}
![Page 7: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/7.jpg)
class User{ protected $storage;
function __construct() { $this->storage = new SessionStorage(); }
function setLanguage($language) { $this->storage->set('language', $language); }
// ...}
$user = new User();
Very easy to use
Very hard to customize
![Page 8: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/8.jpg)
class User{ protected $storage;
function __construct($storage) { $this->storage = $storage; }}
$storage = new SessionStorage();$user = new User($storage);
Slightly more difficult to use
Very easy to customize
![Page 9: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/9.jpg)
That’s Dependency Injection
Nothing more
![Page 10: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/10.jpg)
Let’s understand why the first exampleis not a good idea
![Page 11: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/11.jpg)
I want to change the session cookie name
![Page 12: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/12.jpg)
class User{ protected $storage;
function __construct() { $this->storage = new SessionStorage('SESSION_ID'); }
function setLanguage($language) { $this->storage->set('language', $language); }
// ...}
$user = new User();
Hardcode it in the User class
![Page 13: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/13.jpg)
class User{ protected $storage;
function __construct() { $this->storage = new SessionStorage(STORAGE_SESSION_NAME); }}
define('STORAGE_SESSION_NAME', 'SESSION_ID');
$user = new User();
Add a globalconfiguration?
![Page 14: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/14.jpg)
class User{ protected $storage;
function __construct($sessionName) { $this->storage = new SessionStorage($sessionName); }}
$user = new User('SESSION_ID');
Configure via User?
![Page 15: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/15.jpg)
class User{ protected $storage;
function __construct($storageOptions) { $this->storage = new SessionStorage($storageOptions['session_name']); }}
$user = new User( array('session_name' => 'SESSION_ID'));
Configure with an array?
![Page 16: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/16.jpg)
I want to change the session storage implementation
FilesystemMySQL
Memcached…
![Page 17: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/17.jpg)
class User{ protected $storage;
function __construct() { $this->storage = Registry::get('session_storage'); }}
$storage = new SessionStorage();Registry::set('session_storage', $storage);$user = new User();
Use a global registry object?
![Page 18: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/18.jpg)
Now, the User depends on the Registry
![Page 19: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/19.jpg)
Instead of harcodingthe Storage dependency
inside the User class constructor
Inject the Storage dependencyin the User object
![Page 20: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/20.jpg)
class User{ protected $storage;
function __construct($storage) { $this->storage = $storage; }}
$storage = new SessionStorage('SESSION_ID');$user = new User($storage);
![Page 21: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/21.jpg)
What are the advantages?
![Page 22: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/22.jpg)
Use different Storage strategies
![Page 23: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/23.jpg)
class User{ protected $storage;
function __construct($storage) { $this->storage = $storage; }}
$storage = new MySQLSessionStorage('SESSION_ID');$user = new User($storage);
Use a differentStorage engine
![Page 24: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/24.jpg)
Configuration becomes natural
![Page 25: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/25.jpg)
class User{ protected $storage;
function __construct($storage) { $this->storage = $storage; }}
$storage = new MySQLSessionStorage('SESSION_ID');$user = new User($storage);
Configurationis natural
![Page 26: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/26.jpg)
Wrap third-party classes (Interface / Adapter)
![Page 27: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/27.jpg)
class User{ protected $storage;
function __construct(SessionStorageInterface $storage) { $this->storage = $storage; }}
interface SessionStorageInterface{ function get($key);
function set($key, $value);}
Add an interface
![Page 28: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/28.jpg)
Mock the Storage object (for testing)
![Page 29: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/29.jpg)
class User{ protected $storage;
function __construct(SessionStorageInterface $storage) { $this->storage = $storage; }}
class SessionStorageForTests implements SessionStorageInterface{ protected $data = array();
static function set($key, $value) { self::$data[$key] = $value; }}
Mock the Session
![Page 30: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/30.jpg)
Use different Storage strategies
Configuration becomes natural
Wrap third-party classes (Interface / Adapter)
Mock the Storage object (for testing)
Easy without changing the User class
![Page 31: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/31.jpg)
« Dependency Injection is where components are given their dependencies
through their constructors, methods, or directly into fields. »
http://www.picocontainer.org/injection.html
![Page 32: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/32.jpg)
$storage = new SessionStorage();
// constructor injection$user = new User($storage);
// setter injection$user = new User();$user->setStorage($storage);
// property injection$user = new User();$user->storage = $storage;
![Page 33: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/33.jpg)
A slightly more complexweb example
![Page 34: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/34.jpg)
$request = new Request();$response = new Response();
$storage = new FileSessionStorage('SESSION_ID');$user = new User($storage);
$cache = new FileCache( array('dir' => __DIR__.'/cache'));$routing = new Routing($cache);
![Page 35: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/35.jpg)
class Application{ function __construct() { $this->request = new WebRequest(); $this->response = new WebResponse();
$storage = new FileSessionStorage('SESSION_ID'); $this->user = new User($storage);
$cache = new FileCache( array('dir' => dirname(__FILE__).'/cache') ); $this->routing = new Routing($cache); }}
$application = new Application();
![Page 36: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/36.jpg)
Back to square 1
![Page 37: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/37.jpg)
class Application{ function __construct() { $this->request = new WebRequest(); $this->response = new WebResponse();
$storage = new FileSessionStorage('SESSION_ID'); $this->user = new User($storage);
$cache = new FileCache( array('dir' => dirname(__FILE__).'/cache') ); $this->routing = new Routing($cache); }}
$application = new Application();
![Page 38: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/38.jpg)
We need a Container
Describes objectsand their dependencies
Instantiates and configuresobjects on-demand
![Page 39: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/39.jpg)
A containerSHOULD be able to manage
ANY PHP object (POPO)
The objects MUST not knowthat they are managed
by a container
![Page 40: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/40.jpg)
• Parameters– The SessionStorageInterface implementation we want to use (the class name)– The session name
• Objects– SessionStorage– User
• Dependencies– User depends on a SessionStorageInterface implementation
![Page 41: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/41.jpg)
Let’s build a simple container with PHP 5.3
![Page 42: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/42.jpg)
DI Container
Managing parameters
![Page 43: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/43.jpg)
class Container{ protected $parameters = array();
public function setParameter($key, $value) { $this->parameters[$key] = $value; }
public function getParameter($key) { return $this->parameters[$key]; }}
![Page 44: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/44.jpg)
$container = new Container();$container->setParameter('session_name', 'SESSION_ID');$container->setParameter('storage_class', 'SessionStorage');
$class = $container->getParameter('storage_class');$sessionStorage = new $class($container->getParameter('session_name'));$user = new User($sessionStorage);
Decoupling
Customization
Objects creation
![Page 45: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/45.jpg)
class Container{ protected $parameters = array();
public function __set($key, $value) { $this->parameters[$key] = $value; }
public function __get($key) { return $this->parameters[$key]; }}
Using PHP magic methods
![Page 46: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/46.jpg)
$container = new Container();$container->session_name = 'SESSION_ID';$container->storage_class = 'SessionStorage';
$sessionStorage = new $container->storage_class($container->session_name);$user = new User($sessionStorage);
Interfaceis cleaner
![Page 47: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/47.jpg)
DI Container
Managing objects
![Page 48: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/48.jpg)
We need a way to describe how to create objects,without actually instantiating anything!
Anonymous functions to the rescue!
![Page 49: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/49.jpg)
A lambda is a functiondefined on the fly
with no name
function () { echo 'Hello world!'; };
![Page 50: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/50.jpg)
A lambda can be storedin a variable
$hello = function () { echo 'Hello world!'; };
![Page 51: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/51.jpg)
And then it can be usedas any other PHP callable
$hello();
call_user_func($hello);
![Page 52: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/52.jpg)
You can also pass a lambdaas an argument to a function or method
function foo(Closure $func) { $func();}
foo($hello);
![Page 53: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/53.jpg)
$hello = function ($name) { echo 'Hello '.$name; };
$hello('Fabien');
call_user_func($hello, 'Fabien');
function foo(Closure $func, $name) { $func($name);}
foo($hello, 'Fabien');
![Page 54: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/54.jpg)
DI Container
Managing objects
![Page 55: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/55.jpg)
class Container{ protected $parameters = array(); protected $objects = array();
public function __set($key, $value) { $this->parameters[$key] = $value; }
public function __get($key) { return $this->parameters[$key]; }
public function setService($key, Closure $service) { $this->objects[$key] = $service; }
public function getService($key) { return $this->objects[$key]($this); }}
Store a lambda able to create the object on-demand
Ask the closure to create the object and pass the
current Container
![Page 56: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/56.jpg)
$container = new Container();$container->session_name = 'SESSION_ID';$container->storage_class = 'SessionStorage';$container->setService('user', function ($c) { return new User($c->getService('storage'));});$container->setService('storage', function ($c) { return new $c->storage_class($c->session_name);});
$user = $container->getService('user');
Creating the Useris now as easy as before
Description
![Page 57: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/57.jpg)
$container = new Container();
$container->setService('storage', function ($c) { return new $c->storage_class($c->session_name);});
$container->setService('user', function ($c) { return new User($c->getService('storage'));});
$container->session_name = 'SESSION_ID';
$container->storage_class = 'SessionStorage';
Order does not matter
![Page 58: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/58.jpg)
class Container{ protected $values = array();
function __set($id, $value) { $this->values[$id] = $value; }
function __get($id) { if (is_callable($this->values[$id])) { return $this->values[$id]($this); } else { return $this->values[$id]; } }}
Simplify the code
![Page 59: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/59.jpg)
$container = new Container();$container->session_name = 'SESSION_ID';$container->storage_class = 'SessionStorage';$container->user = function ($c) { return new User($c->storage);};$container->storage = function ($c) { return new $c->storage_class($c->session_name);};
$user = $container->user;
Unified interface
![Page 60: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/60.jpg)
DI Container
Scope
![Page 61: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/61.jpg)
For some objects, like the user,the container must alwaysreturn the same instance
![Page 62: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/62.jpg)
spl_object_hash($container->user)
!==
spl_object_hash($container->user)
![Page 63: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/63.jpg)
$container->user = function ($c) { static $user;
if (is_null($user)) { $user = new User($c->storage); }
return $user;};
![Page 64: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/64.jpg)
spl_object_hash($container->user)
===
spl_object_hash($container->user)
![Page 65: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/65.jpg)
$container->user = $container->asShared(function ($c) { return new User($c->storage);});
![Page 66: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/66.jpg)
A closure is a lambdathat remembers the context
of its creation…
![Page 67: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/67.jpg)
class Article{ public function __construct($title) { $this->title = $title; }
public function getTitle() { return $this->title; }}
$articles = array( new Article('Title 1'), new Article('Title 2'),);
![Page 68: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/68.jpg)
$mapper = function ($article) { return $article->getTitle();};
$titles = array_map($mapper, $articles);
![Page 69: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/69.jpg)
$method = 'getTitle';
$mapper = function ($article) use($method) { return $article->$method();};
$method = 'getAuthor';
$titles = array_map($mapper, $articles);
![Page 70: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/70.jpg)
$mapper = function ($method) { return function ($article) use($method) { return $article->$method(); };};
![Page 71: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/71.jpg)
$titles = array_map($mapper('getTitle'), $articles);
$authors = array_map($mapper('getAuthor'), $articles);
![Page 72: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/72.jpg)
$container->user = $container->asShared(function ($c) { return new User($c->storage);});
![Page 73: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/73.jpg)
function asShared(Closure $lambda){ return function ($container) use ($lambda) { static $object;
if (is_null($object)) { $object = $lambda($container); }
return $object; };}
![Page 74: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/74.jpg)
class Container{ protected $values = array();
function __set($id, $value) { $this->values[$id] = $value; }
function __get($id) { if (!isset($this->values[$id])) { throw new InvalidArgumentException(sprintf('Value "%s" is not defined.', $id)); }
if (is_callable($this->values[$id])) { return $this->values[$id]($this); } else { return $this->values[$id]; } }}
Error management
![Page 75: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/75.jpg)
class Container{ protected $values = array();
function __set($id, $value) { $this->values[$id] = $value; }
function __get($id) { if (!isset($this->values[$id])) { throw new InvalidArgumentException(sprintf('Value "%s" is not defined.', $id)); }
if (is_callable($this->values[$id])) { return $this->values[$id]($this); } else { return $this->values[$id]; } }
function asShared($callable) { return function ($c) use ($callable) { static $object;
if (is_null($object)) { $object = $callable($c); }
return $object; }; }}
40 LOC for a fully-featured container
![Page 76: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/76.jpg)
$container = new Container();$container->session_name = 'SESSION_ID';$container->storage_class = 'SessionStorage';$container->user = $container->asShared(function ($c) { return new User($c->storage);});$container->storage = $container->asShared(function ($c) { return new $c->storage_class($c->session_name);});
![Page 77: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/77.jpg)
github.com/fabpot/pimple
![Page 78: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/78.jpg)
... and with PHP 5.4?
![Page 79: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/79.jpg)
$container = new Container();$container->session_name = 'SESSION_ID';$container->storage_class = 'SessionStorage';$container->user = $container->asShared(function () { return new User($this->storage);});$container->storage = $container->asShared(function () { return new $this->storage_class($this->session_name);});
![Page 80: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/80.jpg)
$title = function () { echo $this->title;};
print get_class($title);// \Closure
![Page 81: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/81.jpg)
class Article{ public $title;
public function __construct($title) { $this->title = $title; }}
$a = new Article('Title 1');
$title = function () { echo $this->title;};
$getTitle = $title->bindTo($a);$getTitle();
![Page 82: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/82.jpg)
class Article{ private $title;
public function __construct($title) { $this->title = $title; }}
$a = new Article('Title 1');
$title = function () { echo $this->title;};
$getTitle = $title->bindTo($a, $a);$getTitle();
![Page 83: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/83.jpg)
wiki.php.net/rfc/closures/object-extension
![Page 84: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/84.jpg)
if (is_callable($this->values[$id])) { $value = $value->bindTo($this);
return $this->values[$id](); } else { return $this->values[$id]; }
![Page 85: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/85.jpg)
function asShared($callable) { $callable = $callable->bindTo($this);
return function () use ($callable) { static $object;
if (is_null($object)) { $object = $callable(); }
return $object; }; }
![Page 86: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/86.jpg)
$container = new Container();$container->session_name = 'SESSION_ID';$container->storage_class = 'SessionStorage';$container->user = $container->asShared(function () { return new User($this->storage);});$container->storage = $container->asShared(function () { return new $this->storage_class($this->session_name);});
![Page 87: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/87.jpg)
A DI Containerdoes NOT manageALL your objects
![Page 88: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/88.jpg)
A DI Container / Service Containermanages your SERVICES
![Page 89: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/89.jpg)
Good rule of thumb:It manages “Global” objects
Objects with only one instance (!= Singletons)
![Page 90: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/90.jpg)
LIKEa User, a Request,
a database Connection, a Logger, …
![Page 91: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/91.jpg)
UNLIKEModel objects (a Product, a blog Post, …)
![Page 92: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/92.jpg)
Performance
![Page 93: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/93.jpg)
The Symfony2 Dependency Injection Component
![Page 94: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/94.jpg)
Rock-solid implementation of a DIC in PHP 5.3
![Page 95: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/95.jpg)
At the core of the Symfony2 framework
![Page 96: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/96.jpg)
namespace Symfony\Component\DependencyInjection;
interface ContainerInterface{ function set($id, $service, $scope = self::SCOPE_CONTAINER); function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE); function has($id); function getParameter($name); function hasParameter($name); function setParameter($name, $value);
function enterScope($name); function leaveScope($name); function addScope(ScopeInterface $scope); function hasScope($name); function isScopeActive($name);}
![Page 97: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/97.jpg)
Very flexible
Configuration in PHP, XML, YAML, or INI
![Page 98: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/98.jpg)
use Symfony\Component\DependencyInjection\ContainerBuilder;use Symfony\Component\DependencyInjection\Reference;
$sc = new ContainerBuilder();$sc->setParameter('session_name', 'SESSION_ID');$sc->setParameter('storage_class', 'SessionStorage');$sc ->register('user', 'User') ->addArgument(new Reference('storage'));$sc->register('storage', '%storage_class%') ->addArgument('%session_name%');
$sc->get('user');
![Page 99: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/99.jpg)
parameters: session_name: SESSION_ID storage_class: SessionStorage
services: user: class: User arguments: [@storage] storage: class: %storage_class% arguments: [%session_name%]
![Page 100: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/100.jpg)
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;use Symfony\Component\Config\FileLocator;
$sc = new ContainerBuilder();
$loader = new YamlFileLoader($sc, new FileLocator(__DIR__));$loader->load('services.yml');
![Page 101: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/101.jpg)
<container xmlns="http://symfony.com/schema/dic/services"> <parameters> <parameter key="session_name">SESSION_ID</parameter> <parameter key="storage_class">SessionStorage</parameter> </parameters>
<services> <service id="user" class="User"> <argument type="service" id="storage" /> </service>
<service id="storage" class="%storage_class%"> <argument>%session_name%</argument> </service> </services></container>
![Page 102: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/102.jpg)
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> <parameters> <parameter key="session_name">SESSION_ID</parameter> <parameter key="storage_class">SessionStorage</parameter> </parameters> <services> <service id="user" class="User"> <argument type="service" id="storage" /> </service>
<service id="storage" class="%storage_class%"> <argument>%session_name%</argument> </service> </services></container>
![Page 103: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/103.jpg)
<container xmlns="http://symfony-project.org/schema/dic/services"> <import resource="parameters.yml" /> <import resource="parameters.ini" /> <import resource="services.xml" /></container>
imports: - { resource: parameters.yml } - { resource: parameters.ini } - { resource: services.xml }
![Page 104: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/104.jpg)
As fast as it can be
The container can be“compiled” downto plain PHP code
![Page 105: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/105.jpg)
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
$dumper = new PhpDumper($sc);echo $dumper->dump();
![Page 106: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/106.jpg)
class ProjectServiceContainer extends Container{ public function __construct() { parent::__construct(new ParameterBag($this->getDefaultParameters())); }
protected function getStorageService() { $class = $this->getParameter('storage_class'); return $this->services['storage'] = new $class($this->getParameter('session_name')); }
protected function getUserService() { return $this->services['user'] = new \User($this->get('storage')); }
protected function getDefaultParameters() { return array( 'session_name' => 'SESSION_ID', 'storage_class' => 'SessionStorage', ); }}
![Page 107: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/107.jpg)
$dumper = new GraphvizDumper($sc);echo $dumper->dump();
$ doc -Tpng -o sc.png sc.dot
![Page 108: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/108.jpg)
There is more...
Semantic configurationScope management
Compiler passes (optimizers)Aliases
Abstract definitions...
![Page 109: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/109.jpg)
Remember, most of the time,you don’t need a Container
to use Dependency Injection
![Page 110: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/110.jpg)
You can start to use and benefit from Dependency Injection today
![Page 111: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/111.jpg)
by implementing itin your projects
by using externals librariesthat already use DI
without the need of a container
![Page 112: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/112.jpg)
SymfonyZend Framework
DoctrineSwift Mailer
…
![Page 113: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/113.jpg)
Questions?
![Page 114: Dependency injection in PHP 5.3/5.4](https://reader034.vdocument.in/reader034/viewer/2022050903/540e1f278d7f72927e8b4aff/html5/thumbnails/114.jpg)
Sensio S.A.92-98, boulevard Victor Hugo
92 115 Clichy CedexFRANCE
Tél. : +33 1 40 99 80 80
Contact Fabien Potencier
fabien.potencier at sensio.com
http://sensiolabs.com/http://symfony.com/
http://fabien.potencier.org/