Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 2d11347

Browse filesBrowse files
committed
more tweaks
1 parent 8433fc1 commit 2d11347
Copy full SHA for 2d11347

File tree

1 file changed

+98
-48
lines changed
Filter options

1 file changed

+98
-48
lines changed

‎service_container.rst

Copy file name to clipboardExpand all lines: service_container.rst
+98-48Lines changed: 98 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Service Container
66
=================
77

88
Your 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.
1010
Almost *everything* that your app "does" is actually done by one of these objects.
1111
And 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

3123
Fetching 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.
3527
These are like *tools*, waiting for you to take advantage of them. In your controller,
3628
you have access to the container via ``$this->container``. Want to :doc:`log </logging>`
3729
something? 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.
10091
Creating/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
135125
services:
136-
# configures defaults for all services in this file
137126
_defaults:
138127
autowire: true
139128
autoconfigure: true
140129
141-
# registers all classes in the dir(s) as services
130+
# load services from whatever directories you want (you can update this!)
142131
AppBundle\:
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

177167
When 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

183171
As a bonus, the ``MessageGenerator::class`` service is only created *once*: the same
184172
instance is returned each time you ask for it.
@@ -221,25 +209,26 @@ and set it on a ``$logger`` property::
221209
}
222210

223211
That'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

230219
Be sure to read more about :doc:`autowiring </service_container/autowiring>`.
231220

232221
.. tip::
233222

234-
How do you know to use ``LoggerInterface`` for the type-hint? The best way to
235-
know this is by reading the docs for whatever service you're using. You can
236-
also use the ``php bin/console debug:container`` console command to get a hint
223+
How should you know to use ``LoggerInterface`` for the type-hint? The best way
224+
is by reading the docs for whatever feature 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

239228
Handling Multiple Services
240229
--------------------------
241230

242-
Suppose you also want to email some site administrator each time a site update is
231+
Suppose you also want to email a site administrator each time a site update is
243232
made. 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
291280
AppBundle\:
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

324312
Manually 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+
463513
Learn more
464514
----------
465515

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.