Skip to content

Commit fff7f31

Browse files
committed
[DI] Add ServiceLocatorArgument to generate array-based locators
1 parent 89e9e3a commit fff7f31

File tree

1 file changed

+78
-14
lines changed

1 file changed

+78
-14
lines changed

service_container/service_subscribers_locators.rst

Lines changed: 78 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,80 @@ service type to a service.
246246
Defining a Service Locator
247247
--------------------------
248248

249-
To manually define a service locator, create a new service definition and add
250-
the ``container.service_locator`` tag to it. Use the first argument of the
251-
service definition to pass a collection of services to the service locator:
249+
To manually define a service locator and inject it to another service, create an
250+
argument of type ``service_locator``:
251+
252+
.. configuration-block::
253+
254+
.. code-block:: yaml
255+
256+
# config/services.yaml
257+
services:
258+
App\CommandBus:
259+
arguments:
260+
!service_locator
261+
App\FooCommand: '@app.command_handler.foo'
262+
App\BarCommand: '@app.command_handler.bar'
263+
264+
.. code-block:: xml
265+
266+
<!-- config/services.xml -->
267+
<?xml version="1.0" encoding="UTF-8" ?>
268+
<container xmlns="http://symfony.com/schema/dic/services"
269+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
270+
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
271+
272+
<services>
273+
<service id="App\CommandBus">
274+
<argument type="service_locator">
275+
<argument key="App\FooCommand" type="service" id="sapp.command_handler.foo" />
276+
<argument key="App\BarCommandr" type="service" id="app.command_handler.bar" />
277+
<!-- if the element has no key, the ID of the original service is used -->
278+
<argument type="service" id="app.command_handler.baz"/>
279+
</argument>
280+
</service>
281+
</services>
282+
</container>
283+
284+
.. code-block:: php
285+
286+
// config/services.php
287+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
288+
289+
use App\CommandBus;
290+
291+
return function(ContainerConfigurator $configurator) {
292+
$services = $configurator->services();
293+
294+
$services->set(CommandBus::class)
295+
->args([service_locator([
296+
'App\FooCommand' => ref('app.command_handler.foo'),
297+
'App\BarCommand' => ref('app.command_handler.bar'),
298+
// if the element has no key, the ID of the original service is used
299+
ref('app.command_handler.baz'),
300+
])]);
301+
};
302+
303+
.. versionadded:: 4.2
304+
305+
The ability to add services without specifying an array key was introduced
306+
in Symfony 4.2.
307+
308+
.. versionadded:: 4.2
309+
310+
The ``service_locator`` argument type was introduced in Symfony 4.2.
311+
312+
As shown in the previous sections, the constructor of the ``CommandBus`` class
313+
must type-hint its argument with ``ContainerInterface``. Then, you can get any of
314+
the service locator services via their ID (e.g. ``$this->locator->get('App\FooCommand')``).
315+
316+
Reusing a Service Locator in Multiple Services
317+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
318+
319+
If you inject the same service locator in several services, it's better to
320+
define the service locator as a stand-alone service and then inject it in the
321+
other files. To do so, create a new service definition using the ``ServiceLocator``
322+
class:
252323

253324
.. configuration-block::
254325

@@ -334,17 +405,7 @@ service definition to pass a collection of services to the service locator:
334405
previous Symfony versions you always needed to add the
335406
``container.service_locator`` tag explicitly.
336407

337-
.. versionadded:: 4.2
338-
339-
The ability to add services without specifying their id was introduced in
340-
Symfony 4.2.
341-
342-
.. note::
343-
344-
The services defined in the service locator argument must include keys,
345-
which later become their unique identifiers inside the locator.
346-
347-
Now you can use the service locator by injecting it in any other service:
408+
Now you can inject the service locator in any other services:
348409

349410
.. configuration-block::
350411

@@ -386,6 +447,9 @@ Now you can use the service locator by injecting it in any other service:
386447
->args([ref('app.command_handler_locator')]);
387448
};
388449
450+
Using Service Locators in Compiler Passes
451+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
452+
389453
In :doc:`compiler passes </service_container/compiler_passes>` it's recommended
390454
to use the :method:`Symfony\\Component\\DependencyInjection\\Compiler\\ServiceLocatorTagPass::register`
391455
method to create the service locators. This will save you some boilerplate and

0 commit comments

Comments
 (0)