@@ -246,9 +246,80 @@ service type to a service.
246246Defining 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 services. To do so, create a new service definition using the
322+ ``ServiceLocator `` 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+
389453In :doc: `compiler passes </service_container/compiler_passes >` it's recommended
390454to use the :method: `Symfony\\ Component\\ DependencyInjection\\ Compiler\\ ServiceLocatorTagPass::register `
391455method to create the service locators. This will save you some boilerplate and
0 commit comments