Dependency Injectionwith PHP 5.3... with a bit of PHP 5.4Fabien Potencier@fabpotfabien@symfony.com
Dependency InjectionA real world « web » example
In most web applications, you need to manage the user preferences  –The user language  –Whether the user is authenticated ...
This can be done with a User object  –setLanguage(), getLanguage()  –setAuthenticated(), isAuthenticated()  –addCredential...
The User information         need to be persisted        between HTTP requestsWe use the PHP session for the Storage
class SessionStorage{    function __construct($cookieName = PHP_SESS_ID)    {        session_name($cookieName);        ses...
class User{    protected $storage;    function __construct()                                             Very hard to    {...
class User{    protected $storage;                 Very easy to                                         customize    funct...
That’s Dependency Injection      Nothing more
Let’s understand why the first exampleis not a good idea
I want to change the session cookie name
class User{    protected $storage;                                                H ardcode it in the    function __constr...
class User{    protected $storage;    function __construct()    {        $this->storage = new SessionStorage(STORAGE_SESSI...
class User{    protected $storage;    function __construct($sessionName)    {        $this->storage = new SessionStorage($...
class User{    protected $storage;    function __construct($storageOptions)    {        $this->storage = newSessionStorage...
I want to change the session storage implementation                   Filesystem                     MySQL                ...
class User{    protected $storage;    function __construct()                                                    Use a glob...
Now, the User depends on the Registry
Instead of harcoding    the Storage dependencyinside the User class constructorInject the Storage dependency       in the ...
class User{    protected $storage;    function __construct($storage)    {        $this->storage = $storage;    }}$storage ...
What are the advantages?
Use different Storage strategies
class User{    protected $storage;    function __construct($storage)    {        $this->storage = $storage;    }          ...
Configuration becomes natural
class User{    protected $storage;    function __construct($storage)    {        $this->storage = $storage;    }          ...
Wrap third-party classes (Interface / Adapter)
class User{    protected $storage;                           Add an interface    function __construct(SessionStorageInterf...
Mock the Storage object (for testing)
class User{    protected $storage;    function __construct(SessionStorageInterface $storage)    {        $this->storage = ...
Use different Storage strategies      Configuration becomes naturalWrap third-party classes (Interface / Adapter)   Mock t...
« Dependency Injection is wherecomponents are given their dependencies through their constructors, methods, or          di...
$storage = new SessionStorage();// constructor injection$user = new User($storage);// setter injection$user = new User();$...
A slightly more complexweb example
$request = new Request();$response = new Response();$storage = new FileSessionStorage(SESSION_ID);$user = new User($storag...
class Application{    function __construct()    {        $this->request = new WebRequest();        $this->response = new W...
Back to square 1
class Application{    function __construct()    {        $this->request = new WebRequest();        $this->response = new W...
We need a Container     Describes objects  and their dependencies Instantiates and configures     objects on-demand
A containerSHOULD be able to manage  ANY PHP object (POPO)The objects MUST not know  that they are managed      by a conta...
• Parameters  –The SessionStorageInterface implementation we want to use (the class name)  –The session name• Objects  –Se...
Let’s build a simple container with PHP 5.3
DI ContainerManaging parameters
class Container{    protected $parameters = array();    public function setParameter($key, $value)    {        $this->para...
Decoupling$container = new Container();                         Customization$container->setParameter(session_name, SESSIO...
Using PHP                                            magic methodsclass Container{    protected $parameters = array();    ...
Interface                                                  is cleaner$container = new Container();$container->session_name...
DI ContainerManaging objects
We need a way to describe how to create objects,    without actually instantiating anything!      Anonymous functions to t...
A lambda is a function                  defined on the fly                   with no namefunction () { echo Hello world!; };
A lambda can be stored                      in a variable$hello = function () { echo Hello world!; };
And then it can be used               as any other PHP callable$hello();call_user_func($hello);
You can also pass a lambda           as an argument to a function or methodfunction foo(Closure $func) {    $func();}foo($...
$hello = function ($name) { echo Hello .$name; };$hello(Fabien);call_user_func($hello, Fabien);function foo(Closure $func,...
DI ContainerManaging objects
class Container{    protected $parameters = array();    protected $objects = array();    public function __set($key, $valu...
Description$container = new Container();$container->session_name = SESSION_ID;$container->storage_class = SessionStorage;$...
Order does not$container = new Container();                        matter$container->setService(storage, function ($c) {  ...
class Container                                  Simplify the code{    protected $values = array();    function __set($id,...
Unified interface$container = new Container();$container->session_name = SESSION_ID;$container->storage_class = SessionSto...
DI ContainerScope
For some objects, like the user,   the container must always    return the same instance
spl_object_hash($container->user)               !==spl_object_hash($container->user)
$container->user = function ($c) {    static $user;     if (is_null($user)) {         $user = new User($c->storage);     }...
spl_object_hash($container->user)               ===spl_object_hash($container->user)
$container->user = $container->asShared(function ($c) {    return new User($c->storage);});
A closure is a lambdathat remembers the context      of its creation…
class Article{    public function __construct($title)    {        $this->title = $title;    }    public function getTitle(...
$mapper = function ($article) {    return $article->getTitle();};$titles = array_map($mapper, $articles);
$method = getTitle;$mapper = function ($article) use($method) {    return $article->$method();};$method = getAuthor;$title...
$mapper = function ($method) {    return function ($article) use($method) {        return $article->$method();    };};
$titles = array_map($mapper(getTitle), $articles);$authors = array_map($mapper(getAuthor), $articles);
$container->user = $container->asShared(function ($c) {    return new User($c->storage);});
function asShared(Closure $lambda){    return function ($container) use ($lambda)    {        static $object;         if (...
class Container{    protected $values = array();    function __set($id, $value)    {        $this->values[$id] = $value;  ...
class Container{    protected $values = array();    function __set($id, $value)    {        $this->values[$id] = $value;  ...
$container = new Container();$container->session_name = SESSION_ID;$container->storage_class = SessionStorage;$container->...
github.com/fabpot/pimple
... and with PHP 5.4?
$container = new Container();$container->session_name = SESSION_ID;$container->storage_class = SessionStorage;$container->...
$title = function () {    echo $this->title;};print get_class($title);// Closure
class Article{    public $title;    public function __construct($title)    {        $this->title = $title;    }}$a = new A...
class Article{    private $title;    public function __construct($title)    {        $this->title = $title;    }}$a = new ...
wiki.php.net/rfc/closures/object-extension
if (is_callable($this->values[$id])) {    $value = $value->bindTo($this);    return $this->values[$id]();} else {  return ...
function asShared($callable){    $callable = $callable->bindTo($this);    return function () use ($callable) {        stat...
$container = new Container();$container->session_name = SESSION_ID;$container->storage_class = SessionStorage;$container->...
A DI Containerdoes NOT manage ALL your objects
A DI Container / Service Container     manages your SERVICES
Good rule of thumb:    It manages “Global” objectsObjects with only one instance (!= Singletons)
LIKE        a User, a Request,a database Connection, a Logger, …
UNLIKEModel objects (a Product, a blog Post, …)
Performance
The Symfony2 Dependency InjectionComponent
Rock-solid implementation of a DIC in PHP 5.3
At the core of the Symfony2 framework
namespace SymfonyComponentDependencyInjection;interface ContainerInterface{      function set($id, $service, $scope = self...
Very flexibleConfiguration in PHP, XML, YAML, or INI
use SymfonyComponentDependencyInjectionContainerBuilder;use SymfonyComponentDependencyInjectionReference;$sc = new Contain...
parameters:    session_name: SESSION_ID    storage_class: SessionStorageservices:  user:    class: User    arguments: [@st...
use SymfonyComponentDependencyInjectionLoaderYamlFileLoader;use SymfonyComponentConfigFileLocator;$sc = new ContainerBuild...
<container xmlns="http://symfony.com/schema/dic/services">    <parameters>        <parameter key="session_name">SESSION_ID...
<container xmlns="http://symfony.com/schema/dic/services"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:...
<container xmlns="http://symfony-project.org/schema/dic/services">  <import resource="parameters.yml" />  <import resource...
As fast as it can be   The container can be     “compiled” down     to plain PHP code
use SymfonyComponentDependencyInjectionDumperPhpDumper;$dumper = new PhpDumper($sc);echo $dumper->dump();
class ProjectServiceContainer extends Container{    public function __construct()    {        parent::__construct(new Para...
$dumper = new GraphvizDumper($sc);echo $dumper->dump();$ doc -Tpng -o sc.png sc.dot
There is more... Semantic configuration   Scope managementCompiler passes (optimizers)          Aliases   Abstract definit...
Remember, most of the time, you don’t need a Containerto use Dependency Injection
You can start to use and benefit from    Dependency Injection today
by implementing it        in your projects  by using externals libraries      that already use DIwithout the need of a con...
SymfonyZend Framework   Doctrine  Swift Mailer      …
Questions?
Sensio S.A.   92-98, boulevard Victor Hugo       92 115 Clichy Cedex              FRANCE     Tél. : +33 1 40 99 80 80     ...
Upcoming SlideShare
Loading in...5
×

Dependency injection in PHP 5.3/5.4

29,156

Published on

Published in: Technology, Business
2 Comments
111 Likes
Statistics
Notes
No Downloads
Views
Total Views
29,156
On Slideshare
0
From Embeds
0
Number of Embeds
27
Actions
Shares
0
Downloads
592
Comments
2
Likes
111
Embeds 0
No embeds

No notes for slide

Dependency injection in PHP 5.3/5.4

  1. 1. Dependency Injectionwith PHP 5.3... with a bit of PHP 5.4Fabien Potencier@fabpotfabien@symfony.com
  2. 2. Dependency InjectionA real world « web » example
  3. 3. In most web applications, you need to manage the user preferences –The user language –Whether the user is authenticated or not –The user credentials –…
  4. 4. This can be done with a User object –setLanguage(), getLanguage() –setAuthenticated(), isAuthenticated() –addCredential(), hasCredential() –...
  5. 5. The User information need to be persisted between HTTP requestsWe use the PHP session for the Storage
  6. 6. class SessionStorage{ function __construct($cookieName = PHP_SESS_ID) { session_name($cookieName); session_start(); } function set($key, $value) { $_SESSION[$key] = $value; } // ...}
  7. 7. class User{ protected $storage; function __construct() Very hard to { customize $this->storage = new SessionStorage(); } function setLanguage($language) { $this->storage->set(language, $language); } // ...} Very easy to use$user = new User();
  8. 8. class User{ protected $storage; Very easy to customize function __construct($storage) { $this->storage = $storage; }}$storage = new SessionStorage();$user = new User($storage); Slightly more difficult to use
  9. 9. That’s Dependency Injection Nothing more
  10. 10. Let’s understand why the first exampleis not a good idea
  11. 11. I want to change the session cookie name
  12. 12. class User{ protected $storage; H ardcode it in the function __construct() User class { $this->storage = new SessionStorage(SESSION_ID); } function setLanguage($language) { $this->storage->set(language, $language); } // ...}$user = new User();
  13. 13. class User{ protected $storage; function __construct() { $this->storage = new SessionStorage(STORAGE_SESSION_NAME); }} Add a global configuration?define(STORAGE_SESSION_NAME, SESSION_ID);$user = new User();
  14. 14. class User{ protected $storage; function __construct($sessionName) { $this->storage = new SessionStorage($sessionName); }}$user = new User(SESSION_ID); Configure via User?
  15. 15. class User{ protected $storage; function __construct($storageOptions) { $this->storage = newSessionStorage($storageOptions[session_name]); }}$user = new User( array(session_name => SESSION_ID)); Configure with an array?
  16. 16. I want to change the session storage implementation Filesystem MySQL Memcached …
  17. 17. class User{ protected $storage; function __construct() Use a global { registry object? $this->storage = Registry::get(session_storage); }}$storage = new SessionStorage();Registry::set(session_storage, $storage);$user = new User();
  18. 18. Now, the User depends on the Registry
  19. 19. Instead of harcoding the Storage dependencyinside the User class constructorInject the Storage dependency in the User object
  20. 20. class User{ protected $storage; function __construct($storage) { $this->storage = $storage; }}$storage = new SessionStorage(SESSION_ID);$user = new User($storage);
  21. 21. What are the advantages?
  22. 22. Use different Storage strategies
  23. 23. class User{ protected $storage; function __construct($storage) { $this->storage = $storage; } Use a different} Storage engine$storage = new MySQLSessionStorage(SESSION_ID);$user = new User($storage);
  24. 24. Configuration becomes natural
  25. 25. class User{ protected $storage; function __construct($storage) { $this->storage = $storage; } Configuration} is natural$storage = new MySQLSessionStorage(SESSION_ID);$user = new User($storage);
  26. 26. Wrap third-party classes (Interface / Adapter)
  27. 27. class User{ protected $storage; Add an interface function __construct(SessionStorageInterface $storage) { $this->storage = $storage; }}interface SessionStorageInterface{ function get($key); function set($key, $value);}
  28. 28. Mock the Storage object (for testing)
  29. 29. class User{ protected $storage; function __construct(SessionStorageInterface $storage) { $this->storage = $storage; }} Mock the Sessionclass SessionStorageForTests implements SessionStorageInterface{ protected $data = array(); static function set($key, $value) { self::$data[$key] = $value; }}
  30. 30. Use different Storage strategies Configuration becomes naturalWrap third-party classes (Interface / Adapter) Mock the Storage object (for testing)Easy without changing the User class
  31. 31. « Dependency Injection is wherecomponents are given their dependencies through their constructors, methods, or directly into fields. »http://www.picocontainer.org/injection.html
  32. 32. $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;
  33. 33. A slightly more complexweb example
  34. 34. $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);
  35. 35. 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();
  36. 36. Back to square 1
  37. 37. 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();
  38. 38. We need a Container Describes objects and their dependencies Instantiates and configures objects on-demand
  39. 39. A containerSHOULD be able to manage ANY PHP object (POPO)The objects MUST not know that they are managed by a container
  40. 40. • Parameters –The SessionStorageInterface implementation we want to use (the class name) –The session name• Objects –SessionStorage –User• Dependencies –User depends on a SessionStorageInterface implementation
  41. 41. Let’s build a simple container with PHP 5.3
  42. 42. DI ContainerManaging parameters
  43. 43. class Container{ protected $parameters = array(); public function setParameter($key, $value) { $this->parameters[$key] = $value; } public function getParameter($key) { return $this->parameters[$key]; }}
  44. 44. Decoupling$container = new Container(); Customization$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); Objects creation
  45. 45. Using PHP magic methodsclass Container{ protected $parameters = array(); public function __set($key, $value) { $this->parameters[$key] = $value; } public function __get($key) { return $this->parameters[$key]; }}
  46. 46. Interface is cleaner$container = new Container();$container->session_name = SESSION_ID;$container->storage_class = SessionStorage;$sessionStorage = new $container->storage_class($container->session_name);$user = new User($sessionStorage);
  47. 47. DI ContainerManaging objects
  48. 48. We need a way to describe how to create objects, without actually instantiating anything! Anonymous functions to the rescue!
  49. 49. A lambda is a function defined on the fly with no namefunction () { echo Hello world!; };
  50. 50. A lambda can be stored in a variable$hello = function () { echo Hello world!; };
  51. 51. And then it can be used as any other PHP callable$hello();call_user_func($hello);
  52. 52. You can also pass a lambda as an argument to a function or methodfunction foo(Closure $func) { $func();}foo($hello);
  53. 53. $hello = function ($name) { echo Hello .$name; };$hello(Fabien);call_user_func($hello, Fabien);function foo(Closure $func, $name) { $func($name);}foo($hello, Fabien);
  54. 54. DI ContainerManaging objects
  55. 55. class Container{ protected $parameters = array(); protected $objects = array(); public function __set($key, $value) { $this->parameters[$key] = $value; } public function __get($key) Store a lambda { return $this->parameters[$key]; able to create the } object on-demand public function setService($key, Closure $service) { $this->objects[$key] = $service; the closure to create Ask } t and pass the the objec public function getService($key) current Container { return $this->objects[$key]($this); }}
  56. 56. Description$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);}); Creating the User$user = $container->getService(user); is now as easy as before
  57. 57. Order does not$container = new Container(); matter$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;
  58. 58. class Container Simplify the code{ 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]; } }}
  59. 59. Unified interface$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;
  60. 60. DI ContainerScope
  61. 61. For some objects, like the user, the container must always return the same instance
  62. 62. spl_object_hash($container->user) !==spl_object_hash($container->user)
  63. 63. $container->user = function ($c) { static $user; if (is_null($user)) { $user = new User($c->storage); } return $user;};
  64. 64. spl_object_hash($container->user) ===spl_object_hash($container->user)
  65. 65. $container->user = $container->asShared(function ($c) { return new User($c->storage);});
  66. 66. A closure is a lambdathat remembers the context of its creation…
  67. 67. 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),);
  68. 68. $mapper = function ($article) { return $article->getTitle();};$titles = array_map($mapper, $articles);
  69. 69. $method = getTitle;$mapper = function ($article) use($method) { return $article->$method();};$method = getAuthor;$titles = array_map($mapper, $articles);
  70. 70. $mapper = function ($method) { return function ($article) use($method) { return $article->$method(); };};
  71. 71. $titles = array_map($mapper(getTitle), $articles);$authors = array_map($mapper(getAuthor), $articles);
  72. 72. $container->user = $container->asShared(function ($c) { return new User($c->storage);});
  73. 73. function asShared(Closure $lambda){ return function ($container) use ($lambda) { static $object; if (is_null($object)) { $object = $lambda($container); } return $object; };}
  74. 74. class Container{ protected $values = array(); function __set($id, $value) { $this->values[$id] = $value; } function __get($id) Error management { 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]; } }}
  75. 75. 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)) { 40 LO C for a fully- } $object = $callable($c); feature d container return $object; }; }}
  76. 76. $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);});
  77. 77. github.com/fabpot/pimple
  78. 78. ... and with PHP 5.4?
  79. 79. $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);});
  80. 80. $title = function () { echo $this->title;};print get_class($title);// Closure
  81. 81. 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();
  82. 82. 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();
  83. 83. wiki.php.net/rfc/closures/object-extension
  84. 84. if (is_callable($this->values[$id])) { $value = $value->bindTo($this); return $this->values[$id]();} else { return $this->values[$id];}
  85. 85. function asShared($callable){ $callable = $callable->bindTo($this); return function () use ($callable) { static $object; if (is_null($object)) { $object = $callable(); } return $object; };}
  86. 86. $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);});
  87. 87. A DI Containerdoes NOT manage ALL your objects
  88. 88. A DI Container / Service Container manages your SERVICES
  89. 89. Good rule of thumb: It manages “Global” objectsObjects with only one instance (!= Singletons)
  90. 90. LIKE a User, a Request,a database Connection, a Logger, …
  91. 91. UNLIKEModel objects (a Product, a blog Post, …)
  92. 92. Performance
  93. 93. The Symfony2 Dependency InjectionComponent
  94. 94. Rock-solid implementation of a DIC in PHP 5.3
  95. 95. At the core of the Symfony2 framework
  96. 96. namespace SymfonyComponentDependencyInjection;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);}
  97. 97. Very flexibleConfiguration in PHP, XML, YAML, or INI
  98. 98. use SymfonyComponentDependencyInjectionContainerBuilder;use SymfonyComponentDependencyInjectionReference;$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);
  99. 99. parameters: session_name: SESSION_ID storage_class: SessionStorageservices: user: class: User arguments: [@storage] storage: class: %storage_class% arguments: [%session_name%]
  100. 100. use SymfonyComponentDependencyInjectionLoaderYamlFileLoader;use SymfonyComponentConfigFileLocator;$sc = new ContainerBuilder();$loader = new YamlFileLoader($sc, new FileLocator(__DIR__));$loader->load(services.yml);
  101. 101. <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>
  102. 102. <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/serviceshttp://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>
  103. 103. <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 }
  104. 104. As fast as it can be The container can be “compiled” down to plain PHP code
  105. 105. use SymfonyComponentDependencyInjectionDumperPhpDumper;$dumper = new PhpDumper($sc);echo $dumper->dump();
  106. 106. 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, ); }}
  107. 107. $dumper = new GraphvizDumper($sc);echo $dumper->dump();$ doc -Tpng -o sc.png sc.dot
  108. 108. There is more... Semantic configuration Scope managementCompiler passes (optimizers) Aliases Abstract definitions ...
  109. 109. Remember, most of the time, you don’t need a Containerto use Dependency Injection
  110. 110. You can start to use and benefit from Dependency Injection today
  111. 111. by implementing it in your projects by using externals libraries that already use DIwithout the need of a container
  112. 112. SymfonyZend Framework Doctrine Swift Mailer …
  113. 113. Questions?
  114. 114. Sensio S.A. 92-98, boulevard Victor Hugo 92 115 Clichy Cedex FRANCE 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/
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×