@@ -6,7 +6,7 @@ Service Container
66=================
77
88Your application is *full * of useful objects: one "Mailer" object might help you
9- deliver email messages while another object might help you save things to the database.
9+ send email messages while another object might help you save things to the database.
1010Almost *everything * that your app "does" is actually done by one of these objects.
1111And each time you install a new bundle, you get access to even more!
1212
@@ -17,21 +17,13 @@ then you can fetch a service by using that service's id::
1717 $logger = $container->get('logger');
1818 $entityManager = $container->get('doctrine.entity_manager');
1919
20- The container is the *heart * of Symfony: it allows you to standardize and centralize
21- the way objects are constructed. It makes your life easier, is super fast, and emphasizes
22- an architecture that promotes reusable and decoupled code. It's also a big reason
23- that Symfony is so fast and extensible!
24-
25- Finally, configuring and using the service container is easy. By the end
26- of this article, you'll be comfortable creating your own objects via the
27- container and customizing objects from any third-party bundle. You'll begin
28- writing code that is more reusable, testable and decoupled, simply because
29- the service container makes writing good code so easy.
20+ The container allows you to centralize the way objects are constructed. It makes
21+ your life easier, promotes a strong architecture and is super fast!
3022
3123Fetching and using Services
3224---------------------------
3325
34- The moment you start a Symfony app,the container *already * contains many services.
26+ The moment you start a Symfony app,your container *already * contains many services.
3527These are like *tools *, waiting for you to take advantage of them. In your controller,
3628you have access to the container via ``$this->container ``. Want to:doc: `log </logging >`
3729something? No problem::
@@ -86,11 +78,10 @@ in the container.
8678
8779..sidebar ::Container: Lazy-loaded for speed
8880
89- If the container holds so many useful objects (services), does that mean those
90- objects are instantiated on *every * request? No! The container is lazy: it doesn't
91- instantiate a service until (and unless) you ask for it. For example, if you
92- never use the ``validator `` service during a request, the container will never
93- instantiate it.
81+ Wait! Are all the services (objects) instantiated on *every * request? No! The
82+ container is lazy: it doesn't instantiate a service until (and unless) you ask
83+ for it. For example, if you never use the ``validator `` service during a request,
84+ the container will never instantiate it.
9485
9586..index ::
9687 single: Service Container; Configuring services
@@ -100,10 +91,9 @@ in the container.
10091Creating/Configuring Services in the Container
10192----------------------------------------------
10293
103- You can also leverage the container to organize your *own * code into services. For
104- example, suppose you want to show your users a random, happy message every time
105- they do something. If you put this code in your controller, it can't be re-used.
106- Instead, you decide to create a new class::
94+ You can also organize your *own * code into services. For example, suppose you need
95+ to show your users a random, happy message. If you put this code in your controller,
96+ it can't be re-used. Instead, you decide to create a new class::
10797
10898 // src/AppBundle/Service/MessageGenerator.php
10999 namespace AppBundle\Service;
@@ -133,14 +123,13 @@ the service container *how* to instantiate it:
133123
134124# app/config/services.yml
135125services :
136- # configures defaults for all services in this file
137126_defaults :
138127autowire :true
139128autoconfigure :true
140129
141- # registers all classes in the dir(s) as services
130+ # load services from whatever directories you want (you can update this!)
142131AppBundle\ :
143- resource :' ../../src/AppBundle/{Service}'
132+ resource :' ../../src/AppBundle/{Service,EventDispatcher,Twig,Form }'
144133
145134 ..code-block ::xml
146135
@@ -153,9 +142,10 @@ the service container *how* to instantiate it:
153142 TODO
154143
155144 That's it! Thanks to the ``AppBundle\ `` line and ``resource `` key below it, all
156- classes in the ``src/AppBundle/Service `` directory will automatically be added to
157- the container. Each service's "key" is simply its class name. You can use it immediately
158- inside your controller::
145+ classes in the ``src/AppBundle/Service `` directory (and a few other directories)
146+ will automatically be added to the container.
147+
148+ Each service's "key" is its class name. You can use it immediately inside your controller::
159149
160150 use AppBundle\Service\MessageGenerator;
161151
@@ -175,10 +165,8 @@ inside your controller::
175165 }
176166
177167When you ask for the ``MessageGenerator::class `` service, the container constructs
178- a new ``MessageGenerator `` object and returns it. If you never ask for the
179- ``MessageGenerator::class `` service during a request, it's *never * constructed, saving
180- you memory and increasing the speed of your app. This also means that there's almost
181- no performance overhead for defining a lot of services.
168+ a new ``MessageGenerator `` object and returns it. But if you never ask for the service,
169+ it's *never * constructed: saving memory and speed.
182170
183171As a bonus, the ``MessageGenerator::class `` service is only created *once *: the same
184172instance is returned each time you ask for it.
@@ -221,25 +209,26 @@ and set it on a ``$logger`` property::
221209 }
222210
223211That's it! The container will *automatically * know to pass the ``logger `` service
224- when instantiating the ``MessageGenerator ``? How does it know to do this? The key
225- is the ``LoggerInterface `` type-hint in your ``__construct() `` method and the
226- ``autowire: true `` config in ``services.yml ``. When you type-hint an argument, the
227- container will automatically find the matching service. If it can't or there is any
228- ambuiguity, you'll see a clear exception suggesting how to fix it.
212+ when instantiating the ``MessageGenerator ``? How does it know to do this?
213+ :doc: `Autowiring </service_container/autowiring >`. The key is the ``LoggerInterface ``
214+ type-hint in your ``__construct() `` method and the ``autowire: true `` config in
215+ ``services.yml ``. When you type-hint an argument, the container will automatically
216+ find the matching service. If it can't or there is any ambuiguity, you'll see a clear
217+ exception suggesting how to fix it.
229218
230219Be sure to read more about:doc: `autowiring </service_container/autowiring >`.
231220
232221..tip ::
233222
234- Howdo you know to use ``LoggerInterface `` for the type-hint? The best way to
235- know this is by reading the docs for whateverservice you're using. You can
236- also use the ``php bin/console debug:container `` console command to get a hint
223+ Howshould you know to use ``LoggerInterface `` for the type-hint? The best way
224+ is by reading the docs for whateverfeature you're using. You can also use the
225+ ``php bin/console debug:container `` console command to get a hint
237226 to the class name for a service.
238227
239228Handling Multiple Services
240229--------------------------
241230
242- Suppose you also want to emailsome site administrator each time a site update is
231+ Suppose you also want to emaila site administrator each time a site update is
243232made. To do that, you create a new class::
244233
245234 // src/AppBundle/Updates/SiteUpdateManager.php
@@ -289,7 +278,7 @@ the new ``Updates`` sub-directory:
289278
290279# registers all classes in Services & Updates directories
291280AppBundle\ :
292- resource :' ../../src/AppBundle/{Service,Updates}'
281+ resource :' ../../src/AppBundle/{Service,Updates,EventDispatcher,Twig,Form }'
293282
294283 ..code-block ::xml
295284
@@ -316,16 +305,15 @@ Now, you can use the service immediately::
316305 // ...
317306 }
318307
319- Just like before, when you ask for the ``SiteUpdateManager `` service, the container
320- will automatically instantiate it for you. By reading the type-hints on the ``__construct() ``
321- method in that class, it takes care of passing the correct services as arguments.
322- All of that is taken care of for you.
308+ Thanks to autowiring and your type-hints in ``__construct() ``, the container creates
309+ the ``SiteUpdateManager `` object and passes it the correct arguments. In most cases,
310+ this works perfectly.
323311
324312Manually Wiring Arguments
325313-------------------------
326314
327- There are a few cases when an argument to a service cannot be autowired. For example,
328- suppose you want to make the admin email configurable:
315+ But there are a few cases when an argument to a service cannot be autowired. For
316+ example, suppose you want to make the admin email configurable:
329317
330318..code-block ::diff
331319
@@ -394,7 +382,8 @@ pass here. No problem! In your configuration, you can explicitly set this argume
394382 TODO
395383
396384 Thanks to this, the container will pass ``manager@example.com `` as the third argument
397- to ``__construct `` when creating the ``SiteUpdateManager `` service.
385+ to ``__construct `` when creating the ``SiteUpdateManager `` service. The other arguments
386+ will still be autowired.
398387
399388.. _service-container-parameters :
400389
@@ -460,6 +449,67 @@ You can also fetch parameters directly from the container::
460449
461450 For more info about parameters, see:doc: `/service_container/parameters `.
462451
452+ Choose a Specific Service
453+ -------------------------
454+
455+ The ``MessageGenerator `` service created earlier requires a ``LoggerInterface `` argument::
456+
457+ // src/AppBundle/Service/MessageGenerator.php
458+ // ...
459+
460+ use Psr\Log\LoggerInterface;
461+
462+ class MessageGenerator
463+ {
464+ private $logger;
465+
466+ public function __construct(LoggerInterface $logger)
467+ {
468+ $this->logger = $logger;
469+ }
470+ // ...
471+ }
472+
473+ However, there are *multiple * services in the container that implement ``LoggerInterface ``,
474+ such as ``logger ``, ``monolog.logger.request ``, ``monolog.logger.php ``, etc. How
475+ does the container know which one to use?
476+
477+ In these situations, the container is usually configured to automatically choose
478+ one of the services - ``logger `` in this case (read more about why in:ref: `service-autowiring-alias `).
479+ But, you can control this and pass in a different logger:
480+
481+ ..configuration-block ::
482+
483+ ..code-block ::yaml
484+
485+ # app/config/services.yml
486+ services :
487+ # ... same code as before
488+
489+ # explicitly configure the service
490+ AppBundle\Service\MessageGenerator :
491+ arguments :
492+ $logger :' @monolog.logger.request'
493+
494+ ..code-block ::xml
495+
496+ <!-- app/config/services.xml-->
497+ TODO
498+
499+ ..code-block ::php
500+
501+ // app/config/services.php
502+ TODO
503+
504+ This tells the container that the ``$logger `` argument to ``_construct `` should use
505+ service whose id is ``monolog.logger.request ``.
506+
507+ ..tip ::
508+
509+ The ``@ `` symbol is important: that's what tells the container you want to pass
510+ the *service * whose id is ``monolog.logger.request ``, and not just the *string *
511+ ``monolog.logger.request ``.
512+
463513Learn more
464514----------
465515