Skip to content

Commit 5385339

Browse files
[DependencyInjection] Add #[AutowireLocator] attribute
1 parent 80f7c9e commit 5385339

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

reference/attributes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Dependency Injection
3838
* :ref:`Autowire <autowire-attribute>`
3939
* :ref:`AutowireCallable <autowiring_closures>`
4040
* :doc:`AutowireDecorated </service_container/service_decoration>`
41+
* :ref:`AutowireLocator <service-locator_autowire-locator>`
4142
* :ref:`AutowireServiceClosure <autowiring_closures>`
4243
* :ref:`Exclude <service-psr4-loader>`
4344
* :ref:`TaggedIterator <tags_reference-tagged-services>`

service_container/service_subscribers_locators.rst

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,84 @@ This is done by having ``getSubscribedServices()`` return an array of
297297

298298
The above example requires using ``3.2`` version or newer of ``symfony/service-contracts``.
299299

300+
.. _service-locator_autowire-locator:
301+
302+
The AutowireLocator attribute
303+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
304+
305+
Another way to define a service locator is to use the
306+
:class:`Symfony\\Component\\DependencyInjection\\Attribute\\AutowireLocator`
307+
attribute::
308+
309+
// src/CommandBus.php
310+
namespace App;
311+
312+
use App\CommandHandler\BarHandler;
313+
use App\CommandHandler\FooHandler;
314+
use Psr\Container\ContainerInterface;
315+
use Symfony\Component\DependencyInjection\Attribute\AutowireLocator;
316+
use Symfony\Contracts\Service\ServiceSubscriberInterface;
317+
318+
class CommandBus implements ServiceSubscriberInterface
319+
{
320+
public function __construct(
321+
#[AutowireLocator(FooHandler::class, BarHandler::class)]
322+
private ContainerInterface $locator,
323+
) {
324+
}
325+
326+
public function handle(Command $command): mixed
327+
{
328+
$commandClass = get_class($command);
329+
330+
if ($this->locator->has($commandClass)) {
331+
$handler = $this->locator->get($commandClass);
332+
333+
return $handler->handle($command);
334+
}
335+
}
336+
}
337+
338+
Just like with the ``getSubscribedServices()`` method, it is possible
339+
to define aliased services thanks to named argument, as well as optional
340+
services::
341+
342+
// src/CommandBus.php
343+
namespace App;
344+
345+
use App\CommandHandler\BarHandler;
346+
use App\CommandHandler\BazHandler;
347+
use App\CommandHandler\FooHandler;
348+
use Psr\Container\ContainerInterface;
349+
use Symfony\Component\DependencyInjection\Attribute\AutowireLocator;
350+
use Symfony\Contracts\Service\ServiceSubscriberInterface;
351+
352+
class CommandBus implements ServiceSubscriberInterface
353+
{
354+
public function __construct(
355+
#[AutowireLocator(
356+
fooHandlerAlias: FooHandler::class,
357+
barHandlerAlias: BarHandler::class,
358+
optionalBazHandlerAlias: '?'.BazHandler::class
359+
)]
360+
private ContainerInterface $locator,
361+
) {
362+
}
363+
364+
public function handle(Command $command): mixed
365+
{
366+
$fooHandler = $this->locator->get('fooHandlerAlias');
367+
368+
// ...
369+
}
370+
}
371+
372+
.. versionadded:: 6.4
373+
374+
The
375+
:class:`Symfony\\Component\\DependencyInjection\\Attribute\\AutowireLocator`
376+
attribute was introduced in Symfony 6.4.
377+
300378
.. _service-subscribers-locators_defining-service-locator:
301379

302380
Defining a Service Locator

0 commit comments

Comments
 (0)