$30 off During Our Annual Pro Sale. View Details »

Understanding Dependency Injection in Symfony

Understanding Dependency Injection in Symfony

The service container – or dependency injection container – is the core concept in the heart of the Symfony framework. It allows us to properly model the logic of our business, building decoupled services and helping our projects grow in a natural and elegant way. Often left out in a first approximation to Symfony, dependency injection is a key topic that needs to be mastered to fully unleash the framework’s potential.

Victoria Quirante

May 30, 2017
Tweet

More Decks by Victoria Quirante

Other Decks in Programming

Transcript

  1. I work at Limenius We build tailor-made projects with Symfony

    and React SF is a solid, mature framework that fosters high quality agile development Having a good understanding of DI is key for mastering the framework Victoria Quirante @vicqr [email protected]
  2. Goals 1. Clarify the terminology 2. Understand what DI is

    used for Victoria Quirante @vicqr [email protected] And what are the benefits
  3. Goals 1. Clarify the terminology 2. Understand what DI is

    used for 3. Learn how Symfony uses it Victoria Quirante @vicqr [email protected]
  4. Goals 1. Clarify the terminology 2. Understand what DI is

    used for 3. Learn how Symfony uses it Victoria Quirante @vicqr [email protected] And how to do it well
  5. Goals 1. Clarify the terminology 2. Understand what DI is

    used for 3. Learn how Symfony uses it Victoria Quirante @vicqr [email protected] Let’s go!
  6. Martin Fowler Robert C. Martin Coauthored the Agile Manifesto Named

    the “first five principles” (SOLID) Popularized terms like “inversion of control” and “dependency injection” ...
  7. Martin Fowler Robert C. Martin Coauthored the Agile Manifesto Named

    the “first five principles” (SOLID) Popularized terms like “inversion of control” and “dependency injection” ... They thought quite a bit about how to write better code
  8. The background Most of these concepts come from the early

    2000s It is all about how to write better code More reusable, readable, testable code Victoria Quirante @vicqr [email protected]
  9. The background Most of these concepts come from the early

    2000s It is all about how to write better code More reusable, readable, testable code Victoria Quirante @vicqr [email protected] “Inversion of Control Containers and the Dependency Injection pattern” https://martinfowler.com/articles/injection.html Good reading
  10. Inversion of control Victoria Quirante @vicqr [email protected] Traditional procedure programming

    Library 1 Your custom code Library 2 Library 3 Library 4 Your custom code calls some reusable libraries
  11. Inversion of control Victoria Quirante @vicqr [email protected] Traditional procedure programming

    Modern frameworks Library 1 Your custom code Library 2 Library 3 Library 4 The framework calls your custom code Framework Custom service 1 Custom service 2 Custom service 3 Custom service 4 Your custom code calls some reusable libraries
  12. Inversion of control and dependency injection Inversion of control is

    a broad concept DI is a specific form of IoC that solves a concrete problem Victoria Quirante @vicqr [email protected] Inversion of control (broad concept) DI = Inversion of how you plug components together
  13. Inversion of control and dependency injection Inversion of control is

    a broad concept DI is a specific form of IoC that solves a concrete problem DI is about how to assemble the components Victoria Quirante @vicqr [email protected] Inversion of control (broad concept) DI = Inversion of how you plug components together
  14. The problem: how to assemble DI is a (good) way

    to assemble the different components Victoria Quirante @vicqr [email protected] How to assemble different components Dependency Injection pattern
  15. The problem: how to assemble DI is a (good) way

    to assemble the different components Using a service locator is another possible solution Victoria Quirante @vicqr [email protected] How to assemble different components Dependency injection pattern Service locator pattern
  16. The problem: how to assemble DI is a (good) way

    to assemble the different components Using a service locator is another possible solution Both solutions try to decouple dependencies Victoria Quirante @vicqr [email protected] How to assemble different components Dependency injection pattern Service locator pattern
  17. Why is it so important to decouple? We don’t want

    to change the client code whenever we have to change the dependency or its configuration Victoria Quirante @vicqr [email protected]
  18. Assembling dependencies Victoria Quirante @vicqr [email protected] Some code Some dependency

    created right here Coupled services Services decoupled with SL Services decoupled with DI
  19. Assembling dependencies Victoria Quirante @vicqr [email protected] Some code Some dependency

    created right here Coupled services Services decoupled with SL Some code Some dependency The code asks for the dependency Services decoupled with DI
  20. Assembling dependencies Victoria Quirante @vicqr [email protected] Some code Some dependency

    created right here Coupled services Services decoupled with SL Services decoupled with DI Some code Some dependency The code asks for the dependency Some code Some dependency The dependency gets injected
  21. Dependency injection You don’t create the dependencies inside your object

    Instead, you inject the dependencies in you object Victoria Quirante @vicqr [email protected] It is a way to decouple your services
  22. Service locator You don’t create the dependencies inside your object

    Instead, your object asks for the dependencies to the service locator Victoria Quirante @vicqr [email protected] It is also a way to decouple your services
  23. Service locator: pattern or antipattern? Some say that it is

    an antipattern (the locator itself is a coupled dependency) And that is more difficult to test Victoria Quirante @vicqr [email protected]
  24. Service locator: pattern or antipattern? Some say that it is

    an antipattern (the locator itself is a coupled dependency) And that is more difficult to test Victoria Quirante @vicqr [email protected] Others say that only if you do it wrong
  25. «A common reason people give for preferring dependency injection is

    that it makes testing easier. [...] I suspect this observation comes from projects where people don't make the effort to ensure that their service locator can be easily substituted.» Martin Fowler
  26. «The choice between Service Locator and Dependency Injection is less

    important than the principle of separating service configuration from the use of services within an application.» Martin Fowler «A common reason people give for preferring dependency injection is that it makes testing easier. [...] I suspect this observation comes from projects where people don't make the effort to ensure that their service locator can be easily substituted.» Martin Fowler
  27. Dependency injection VS Service locator Service locator: - Easier to

    understand Dependency injection: - Easier to see what dependencies you have - You have access only to the dependencies that you need Victoria Quirante @vicqr [email protected]
  28. DI supports the dependency inversion principle S - Single Responsibility

    O - Open / closed L - Liskov substitution I - Interface segregation D - Dependency inversion Victoria Quirante @vicqr [email protected]
  29. DI supports the dependency inversion principle A. High-level modules should

    not depend on low-level modules. Both should depend on abstractions. B. Abstractions should not depend on details. Details should depend on abstractions. S - Single Responsibility O - Open / closed L - Liskov substitution I - Interface segregation D - Dependency inversion Victoria Quirante @vicqr [email protected]
  30. DI supports the dependency inversion principle A. High-level modules should

    not depend on low-level modules. Both should depend on abstractions. B. Abstractions should not depend on details. Details should depend on abstractions. S - Single Responsibility O - Open / closed L - Liskov substitution I - Interface segregation D - Dependency inversion Victoria Quirante @vicqr [email protected] The client code fully delegates the responsibility of providing the dependencies to the injector
  31. Summarizing benefits of DI Better code That follows SOLID And

    is more reusable, testable, readable Victoria Quirante @vicqr [email protected] It helps decoupling services
  32. The learning curve DI is simple, but there is a

    learning curve Thinking on a decoupled-fashion is not straightforward at the beginning Victoria Quirante @vicqr [email protected]
  33. General schema of Symfony application Twig templates Controllers Template 1

    Template 2 Template 3 Controller 1 Controller 2 Controller 3 Repositories Entities
  34. General schema of Symfony application Twig templates Controllers Template 1

    Template 2 Template 3 Controller 1 Controller 2 Controller 3 Repositories Entities
  35. General schema of Symfony application Twig templates Controllers Template 1

    Template 2 Template 3 Controller 1 Controller 2 Controller 3 Repositories Entities
  36. General schema of Symfony application Twig templates Controllers Template 1

    Template 2 Template 3 Controller 1 Controller 2 Controller 3 Repositories Entities
  37. General schema of Symfony application Twig templates Controllers Template 1

    Template 2 Template 3 Controller 1 Controller 2 Controller 3 Repositories Entities
  38. General schema of Symfony application Victoria Quirante @vicqr [email protected] Twig

    templates Controllers Services Template 1 Template 2 Template 3 Controller 1 Controller 2 Controller 3 Service 1 Service 2 Service 3 Service 4 Service 5 Repositories Entities Good part of your business logic goes here
  39. Services An object that does something A class that implements

    a concrete functionality Victoria Quirante @vicqr [email protected] That sounds quite broad...
  40. Services in Symfony - Symfony components as services: Swiftmailer, Validator...

    - Many bundles provide other services Victoria Quirante @vicqr [email protected]
  41. Services in Symfony - Symfony components as services: Swiftmailer, Validator...

    - Many bundles provide other services - You can create your own Victoria Quirante @vicqr [email protected] Very flexible
  42. Services in Symfony - Symfony components as services: Swiftmailer, Validator...

    - Many bundles provide other services - You can create your own Victoria Quirante @vicqr [email protected] It is really important to decouple Very flexible
  43. Coupled services class Invoicer { public function sendInvoice() { //

    ... $mailer = new Mailer(); // ... } } Victoria Quirante @vicqr [email protected]
  44. Decoupled services class Invoicer { public function sendInvoice() { //

    ... $mailer = new Mailer(); // ... } } Victoria Quirante @vicqr [email protected] class Invoicer { private $mailer; public function __construct($mailer) { $this->mailer = $mailer; } public function sendInvoice() { // ... $this->mailer->send($email); // ... } }
  45. Decoupled services class Invoicer { public function sendInvoice() { //

    ... $mailer = new Mailer(); // ... } } Victoria Quirante @vicqr [email protected] class Invoicer { private $mailer; public function __construct($mailer) { $this->mailer = $mailer; } public function sendInvoice() { // ... $this->mailer->send($email); // ... } }
  46. Decoupled services class Invoicer { public function sendInvoice() { //

    ... $mailer = new Mailer(); // ... } } Victoria Quirante @vicqr [email protected] class Invoicer { private $mailer; public function __construct($mailer) { $this->mailer = $mailer; } public function sendInvoice() { // ... $this->mailer->send($email); // ... } }
  47. Types of DI - Constructor injection - Setter injection ->

    good for optional dependencies - There are others: interface injection, property injection... Victoria Quirante @vicqr [email protected] http://symfony.com/doc/current/service_container/injection_types.html
  48. The Service Container Victoria Quirante @vicqr [email protected] It is an

    object that knows how to instantiate and configure objects It needs info about the constructor arguments and the relations between objects
  49. Do we always need a Service Container? No, we can

    implement DI without having a container But it is useful when we have lots of objects and dependencies Victoria Quirante @vicqr [email protected]
  50. Calling one service from the container public function myAction() {

    // ... // the container will instantiate a new FortuneCookieGenerator() $fortuneGenerator = $this->container->get('limenius.fortune_cookie_generator'); $message = $fortuneGenerator->getFortuneCookieMessage(); // ... } Victoria Quirante @vicqr [email protected]
  51. Calling one service from the container public function myAction() {

    // ... // the container will instantiate a new FortuneCookieGenerator() $fortuneGenerator = $this->container->get('limenius.fortune_cookie_generator'); $message = $fortuneGenerator->getFortuneCookieMessage(); // ... } Victoria Quirante @vicqr [email protected]
  52. But wait… is this not a service locator? Yes, the

    Service Container can be used as a service locator Victoria Quirante @vicqr [email protected]
  53. But wait… is this not a service locator? Yes, the

    Service Container can be used as a service locator Victoria Quirante @vicqr [email protected] It is actually used as such in the Controllers
  54. Controllers are ContainerAware! Is this not a bad practice? (difficult

    to test, etc.) Generally it is considered a bad practice to pass the container Controllers are a special case (if you want them to be) Victoria Quirante @vicqr [email protected]
  55. Controllers are ContainerAware! Is this not a bad practice? (difficult

    to test, etc.) Generally it is considered a bad practice to pass the container Controllers are a special case (if you want them to be) - It can actually be more performant - It is also easier to understand at the beginning Victoria Quirante @vicqr [email protected] https://stackoverflow.com/questions/26304755/dependancy-injecton-or-service-locator-symfony
  56. Controllers are ContainerAware! Is this not a bad practice? (difficult

    to test, etc.) Generally it is considered a bad practice to pass the container Controllers are a special case (if you want them to be) - It can actually be more performant - It is also easier to understand at the beginning Victoria Quirante @vicqr [email protected] But remember: don’t put logic in your controllers https://stackoverflow.com/questions/26304755/dependancy-injecton-or-service-locator-symfony
  57. Bad practice: pass the container as a dependency - You

    can’t see the actual dependencies of the service - The service has access to too many things Victoria Quirante @vicqr [email protected]
  58. Step 1: Create the service class FortuneGenerator { public function

    getFortuneCookieMessage() { $messages = [ 'Aspire to achieve; you are almost there', 'It is time for you to explore new interests', 'The secret of getting ahead is getting started', ]; $index = array_rand($messages); return $messages[$index]; } } Victoria Quirante @vicqr [email protected]
  59. Step 2: Tell the container how to instantiate it #

    app/config/services.yml services: limenius.fortune_cookie_generator: class: Limenius\AppBundle\Fortune\FortuneGenerator arguments: [] Victoria Quirante @vicqr [email protected]
  60. Step 2: Tell the container how to instantiate it #

    app/config/services.yml services: limenius.fortune_cookie_generator: class: Limenius\AppBundle\Fortune\FortuneGenerator arguments: [] Victoria Quirante @vicqr [email protected]
  61. Step 2: Tell the container how to instantiate it #

    app/config/services.yml services: limenius.fortune_cookie_generator: class: Limenius\AppBundle\Fortune\FortuneGenerator arguments: [] Victoria Quirante @vicqr [email protected]
  62. Step 3: Injecting services in other services Victoria Quirante @vicqr

    [email protected] class Invoicer { private $mailer; public function __construct($mailer) { $this->mailer = $mailer; } public function sendInvoice() { // ... $this->mailer->send($message); // ... } }
  63. Step 3: Injecting services in other services Victoria Quirante @vicqr

    [email protected] class Invoicer { private $mailer; private $fortuneGenerator; public function __construct($mailer, $fortuneGenerator) { $this->mailer = $mailer; $this->fortuneGenerator = $fortuneGenerator; } public function sendInvoice() { // ... $this->mailer->send($email); $this->fortuneGenerator->getFortuneCookieMessage(); } } Constructor arguments
  64. Step 3: Injecting services in other services # app/config/services.xml <service

    id="limenius.invoicer" class="Limenius\AppBundle\Payments\Invoicer"> <argument type="service" id="mailer"/> <argument type="service" id="limenius.fortune_cookie_generator"/> </service> <service id="limenius.fortune_cookie_generator" class="Limenius\AppBundle\Fortune\FortuneGenerator"> </service> Victoria Quirante @vicqr [email protected] We can create this configuration in XML, YML, PHP...
  65. Step 3: Injecting services in other services # app/config/services.xml <service

    id="limenius.invoicer" class="Limenius\AppBundle\Payments\Invoicer"> <argument type="service" id="mailer"/> <argument type="service" id="limenius.fortune_cookie_generator"/> </service> <service id="limenius.fortune_cookie_generator" class="Limenius\AppBundle\Fortune\FortuneGenerator"> </service> Victoria Quirante @vicqr [email protected] We can create this configuration in XML, YML, PHP...
  66. Injecting parameters # app/config/services.xml <service id="limenius.invoicer" class="Limenius\AppBundle\Payments\Invoicer"> <argument type="service" id="mailer"/>

    <argument type="service" id="limenius.fortune_cookie_generator"/> </service> <service id="limenius.fortune_cookie_generator" class="Limenius\AppBundle\Fortune\FortuneGenerator"> <argument>%enable_unlucky_quotes%</argument> </service> Victoria Quirante @vicqr [email protected] The container also holds configuration parameters, declared in parameters.yml
  67. Optional dependencies via setter injection Victoria Quirante @vicqr [email protected] class

    Invoicer { private $mailer; private $fortuneGenerator; public function __construct($mailer, $fortuneGenerator) { $this->mailer = $mailer; $this->fortuneGenerator = $fortuneGenerator; } }
  68. Optional dependencies via setter injection Victoria Quirante @vicqr [email protected] class

    Invoicer { private $mailer; private $fortuneGenerator; public function __construct($mailer) { $this->mailer = $mailer; } public function setFortuneGenerator($fortuneGenerator) { $this->fortuneGenerator = $fortuneGenerator; } }
  69. Optional dependencies via setter injection Victoria Quirante @vicqr [email protected] #

    app/config/services.xml <service id="limenius.invoicer" class="Limenius\AppBundle\Payments\Invoicer"> <argument type="service" id="mailer"/> <argument type="service" id="limenius.fortune_cookie_generator"/> </service>
  70. Optional dependencies via setter injection Victoria Quirante @vicqr [email protected] #

    app/config/services.xml <service id="limenius.invoicer" class="Limenius\AppBundle\Payments\Invoicer"> <argument type="service" id="mailer"/> <argument type="service" id="limenius.fortune_cookie_generator"/> <call method="setFortuneGenerator"> <argument type="service" id="limenius.fortune_cookie_generator" /> </call> </service> http://symfony.com/doc/current/service_container/calls.html
  71. Good practices when creating your services - Services should do

    only one thing - Inject only the dependencies that you need - Use calls for optional dependencies Victoria Quirante @vicqr [email protected]
  72. Parent services services: limenius.base_doctrine_repository: abstract: true arguments: ['@doctrine.entity_manager'] limenius.chinese_wisdom_repository: class:

    Limenius\AppBundle\Repository\ChineseWisdomRepository parent: limenius.base_doctrine_repository Victoria Quirante @vicqr [email protected] Useful when you have many services using the same dependencies
  73. Parent services services: limenius.base_doctrine_repository: abstract: true arguments: ['@doctrine.entity_manager'] limenius.chinese_wisdom_repository: class:

    Limenius\AppBundle\Repository\ChineseWisdomRepository parent: limenius.base_doctrine_repository Victoria Quirante @vicqr [email protected] Useful when you have many services using the same dependencies
  74. Parent services services: limenius.base_doctrine_repository: abstract: true arguments: ['@doctrine.entity_manager'] limenius.chinese_wisdom_repository: class:

    Limenius\AppBundle\Repository\ChineseWisdomRepository parent: limenius.base_doctrine_repository Victoria Quirante @vicqr [email protected] Useful when you have many services using the same dependencies http://symfony.com/doc/current/service_container/parent_services.html
  75. Factories class FortuneGeneratorFactory { public static function createFortuneGenerator() { $fortuneGenerator

    = new FortuneGenerator(); // ... return $fortuneGenerator; } } Victoria Quirante @vicqr [email protected] Useful when you want to create complex objects The container will call a method on the factory, instead of directly instantiating the class
  76. Example: Injecting repositories # app/config/services.xml <service id="limenius.fortune_cookie_generator" class="Limenius\AppBundle\Fortune\FortuneGenerator"> <argument type="service"

    id="limenius.repository.chinese_wisdom"/> </service> <service id="limenius.repository.chinese_wisdom" class="Limenius\DietoBundle\Entity\ChineseWisdomRepository" factory-service="doctrine.orm.entity_manager" factory-method="getRepository"> <argument type="string">Limenius\DietoBundle\Entity\ChineseWisdom</argument> </service> Victoria Quirante @vicqr [email protected] We can instantiate a single repository instead of passing the whole entity manager
  77. Example: Injecting repositories # app/config/services.xml <service id="limenius.fortune_cookie_generator" class="Limenius\AppBundle\Fortune\FortuneGenerator"> <argument type="service"

    id="limenius.repository.chinese_wisdom"/> </service> <service id="limenius.repository.chinese_wisdom" class="Limenius\DietoBundle\Entity\ChineseWisdomRepository" factory-service="doctrine.orm.entity_manager" factory-method="getRepository"> <argument type="string">Limenius\DietoBundle\Entity\ChineseWisdom</argument> </service> Victoria Quirante @vicqr [email protected] We can instantiate a single repository instead of passing the whole entity manager
  78. Service tags # app/config/services.yml services: # ... admin.fortune_cookie: class: Limenius\AppBundle\Admin\FortuneCookieAdmin

    arguments: [~, Limenius\AppBundle\Entity\FortuneCookie, ~] tags: - { name: sonata.admin, manager_type: orm, label: Fortune Cookies } Victoria Quirante @vicqr [email protected] http://symfony.com/doc/current/service_container/tags.html For example, SonataAdminBundle uses them to identify the Admins
  79. Service tags # app/config/services.yml services: # ... admin.fortune_cookie: class: Limenius\AppBundle\Admin\FortuneCookieAdmin

    arguments: [~, Limenius\AppBundle\Entity\FortuneCookie, ~] tags: - { name: sonata.admin, manager_type: orm, label: Fortune Cookies } Victoria Quirante @vicqr [email protected] http://symfony.com/doc/current/service_container/tags.html For example, SonataAdminBundle uses them to identify the Admins
  80. Compiler passes class MyCompilerPass implements CompilerPassInterface { public function process(ContainerBuilder

    $container) { ... // find all service IDs with the sonata.admin tag $taggedServices = $container->findTaggedServiceIds('sonata.admin'); foreach ($taggedServices as $id => $tags) { // do something } } } Victoria Quirante @vicqr [email protected] You want to execute some custom code during the container compilation
  81. Compiler passes class MyCompilerPass implements CompilerPassInterface { public function process(ContainerBuilder

    $container) { ... // find all service IDs with the sonata.admin tag $taggedServices = $container->findTaggedServiceIds('sonata.admin'); foreach ($taggedServices as $id => $tags) { // do something } } } Victoria Quirante @vicqr [email protected] You want to execute some custom code during the container compilation
  82. Autowiring class Invoicer { private $mailer; private $fortuneGenerator; public function

    __construct($mailer, $fortuneGenerator) { $this->mailer = $mailer; $this->fortuneGenerator = $fortuneGenerator; } public function sendInvoice() { // ... $this->mailer->send($email); $this->fortuneGenerator->getFortune(); } } Victoria Quirante @vicqr [email protected]
  83. Autowiring class Invoicer { private $mailer; private $fortuneGenerator; public function

    __construct(MailerInterface $mailer, FortuneGenerator $fortuneGenerator) { $this->mailer = $mailer; $this->fortuneGenerator = $fortuneGenerator; } public function sendInvoice() { // ... $this->mailer->send($email); $this->fortuneGenerator->getFortune(); } } Victoria Quirante @vicqr [email protected] It only works if you write the typehints
  84. Autowiring class Invoicer { private $mailer; private $fortuneGenerator; public function

    __construct(MailerInterface $mailer, FortuneGenerator $fortuneGenerator) { $this->mailer = $mailer; $this->fortuneGenerator = $fortuneGenerator; } public function sendInvoice() { // ... $this->mailer->send($email); $this->fortuneGenerator->getFortune(); } } Victoria Quirante @vicqr [email protected] http://symfony.com/doc/current/service_container/autowiring.html It only works if you write the typehints
  85. Simpler configuration Short syntax services: limenius.invoicer: class: Limenius\AppBundle\Payments\Invoicer autowire: true

    Victoria Quirante @vicqr [email protected] http://symfony.com/blog/new-in-symfony-3-3-simpler-service-configuration
  86. Simpler configuration Short syntax services: limenius.invoicer: class: Limenius\AppBundle\Payments\Invoicer autowire: true

    Limenius\AppBundle\Payments\Invoicer: autowire: true Victoria Quirante @vicqr [email protected] The id of the service is considered to be the class
  87. Simpler configuration Default service configuration services: _defaults: autowire: true Interface-based

    service configuration services: _instanceof: Twig_ExtensionInterface: tags: ['twig.extension'] Victoria Quirante @vicqr [email protected] Applies to all services defined in the file Applies to all services implementing the interface
  88. Autoconfiguration services: _defaults: autowire: true autoconfigure: true _instanceof: Symfony\Component\Security\Core\Authorization\Voter\VoterInterface: tags:

    [security.voter] AppBundle\Security\PostVoter: ~ Victoria Quirante @vicqr [email protected] https://symfony.com/blog/new-in-symfony-3-3-service-autoconfiguration Like an automated version of _instanceof
  89. PSR-4 based service discovery services: App\: resource: '../../src/{Controller, Command}' Victoria

    Quirante @vicqr [email protected] http://symfony.com/blog/new-in-symfony-3-3-psr-4-based-service-discovery Looks in the directories, infers the PSR-4 class names and registers the services
  90. PSR-4 based service discovery services: App\: resource: '../../src/{Controller, Command}' Victoria

    Quirante @vicqr [email protected] http://symfony.com/blog/new-in-symfony-3-3-psr-4-based-service-discovery Looks in the directories, infers the PSR-4 class names and registers the services
  91. Service locators - For some reason, you want to have

    dependencies available that you are not going to use Victoria Quirante @vicqr [email protected]
  92. Service locators - For some reason, you want to have

    dependencies available that you are not going to use - Possible solutions: - Injecting dependencies that you are not going to use - Injecting the whole container Victoria Quirante @vicqr [email protected]
  93. Service locators - For some reason, you want to have

    dependencies available that you are not going to use - Possible solutions: - Injecting dependencies that you are not going to use Instantiating objects that you don’t need - Injecting the whole container Victoria Quirante @vicqr [email protected]
  94. Service locators - For some reason, you want to have

    dependencies available that you are not going to use - Possible solutions: - Injecting dependencies that you are not going to use Instantiating objects that you don’t need - Injecting the whole container Too broad access, actual dependencies hidden Victoria Quirante @vicqr [email protected]
  95. Service locators - For some reason, you want to have

    dependencies available that you are not going to use - Possible solutions: - Injecting dependencies that you are not going to use Instantiating objects that you don’t need - Injecting the whole container Too broad access, actual dependencies hidden You can create a service locator (a container that contains just the services that you want, not all of them) and inject it with DI Victoria Quirante @vicqr [email protected] http://symfony.com/blog/new-in-symfony-3-3-service-locators
  96. Symfony 4 - Compose your application It will be released

    in November 2017 They wanted to automate bundle installation/configuration It makes as easy to create projects with lots or few dependencies Victoria Quirante @vicqr [email protected]
  97. «As a developer, I want to start small, without too

    many dependencies. But I also want to be able to grow my application as I see fit. From a micro-framework style app to a gigantic monolith. Your choice. The framework should not get in the way.» Fabien Potencier
  98. «As a developer, I want to start small, without too

    many dependencies. But I also want to be able to grow my application as I see fit. From a micro-framework style app to a gigantic monolith. Your choice. The framework should not get in the way.» Fabien Potencier «Symfony Flex is all about making it simple and easy to create any Symfony applications, from the most simple micro-style project to the more complex ones with dozens of dependencies. It automates adding and removing bundles. It takes care of giving you sensible defaults. It helps discovering good bundles.» Fabien Potencier
  99. Symfony Flex - Automation to the max It is a

    composer plugin that comes with Symfony 4 The idea is automation to the max Moving towards zero configuration time It will also “promote” a curated list of bundles Victoria Quirante @vicqr [email protected] https://medium.com/@fabpot/symfony-4-a-small-screencast-cf6511823f
  100. Final thoughts (i) Dependency injection is a very good way

    of decoupling your services Victoria Quirante @vicqr [email protected]
  101. Final thoughts (ii) With SF you have a lot of

    freedom designing your services (where your business logic is) Using DI properly is essential Victoria Quirante @vicqr [email protected]
  102. Final thoughts (iii) SF is moving towards making default configuration

    100% straightforward But this does not mean that we don’t need to understand what is going on Victoria Quirante @vicqr [email protected]