diff --git a/service_container/service_subscribers_locators.rst b/service_container/service_subscribers_locators.rst index 1c98bc7d471..c2b4c75fd23 100644 --- a/service_container/service_subscribers_locators.rst +++ b/service_container/service_subscribers_locators.rst @@ -243,6 +243,55 @@ service type to a service. The ``key`` attribute can be omitted if the service name internally is the same as in the service container. +Add Dependency Injection Attributes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 6.2 + + The ability to add attributes was introduced in Symfony 6.2. + +As an alternate to aliasing services in your configuration, you can also configure +the following dependency injection attributes in the ``getSubscribedServices()`` +method directly: + +* :class:`Symfony\\Component\\DependencyInjection\\Attribute\\Autowire` +* :class:`Symfony\\Component\\DependencyInjection\\Attribute\\TaggedIterator` +* :class:`Symfony\\Component\\DependencyInjection\\Attribute\\TaggedLocator` +* :class:`Symfony\\Component\\DependencyInjection\\Attribute\\Target` +* :class:`Symfony\\Component\\DependencyInjection\\Attribute\\MapDecorated` + +This is done by having ``getSubscribedServices()`` return an array of +:class:`Symfony\\Contracts\\Service\\Attribute\\SubscribedService` objects +(these can be combined with standard ``string[]`` values):: + + use Psr\Container\ContainerInterface; + use Psr\Log\LoggerInterface; + use Symfony\Component\DependencyInjection\Attribute\Autowire; + use Symfony\Component\DependencyInjection\Attribute\TaggedIterator; + use Symfony\Component\DependencyInjection\Attribute\TaggedLocator; + use Symfony\Component\DependencyInjection\Attribute\Target; + use Symfony\Contracts\Service\Attribute\SubscribedService; + + public static function getSubscribedServices(): array + { + return [ + // ... + new SubscribedService('logger', LoggerInterface::class, attributes: new Autowire(service: 'monolog.logger.event')), + + // can event use parameters + new SubscribedService('env', string, attributes: new Autowire('%kernel.environment%')), + + // Target + new SubscribedService('event.logger', LoggerInterface::class, attributes: new Target('eventLogger')), + + // TaggedIterator + new SubscribedService('loggers', 'iterable', attributes: new TaggedIterator('logger.tag')), + + // TaggedLocator + new SubscribedService('handlers', ContainerInterface::class, attributes: new TaggedLocator('handler.tag')), + ]; + } + Defining a Service Locator -------------------------- @@ -256,7 +305,7 @@ argument of type ``service_locator``: # config/services.yaml services: App\CommandBus: - arguments: + arguments: - !service_locator App\FooCommand: '@app.command_handler.foo' App\BarCommand: '@app.command_handler.bar' @@ -721,4 +770,63 @@ and compose your services with them:: as this will include the trait name, not the class name. Instead, use ``__CLASS__.'::'.__FUNCTION__`` as the service id. +SubscribedService Attributes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 6.2 + + The ability to add attributes was introduced in Symfony 6.2. + +You can use the ``attributes`` argument of ``SubscribedService`` to add any +of the following dependency injection attributes: + +* :class:`Symfony\\Component\\DependencyInjection\\Attribute\\Autowire` +* :class:`Symfony\\Component\\DependencyInjection\\Attribute\\TaggedIterator` +* :class:`Symfony\\Component\\DependencyInjection\\Attribute\\TaggedLocator` +* :class:`Symfony\\Component\\DependencyInjection\\Attribute\\Target` +* :class:`Symfony\\Component\\DependencyInjection\\Attribute\\MapDecorated` + +Here's an example:: + + // src/Service/MyService.php + namespace App\Service; + + use Psr\Log\LoggerInterface; + use Symfony\Component\DependencyInjection\Attribute\Autowire; + use Symfony\Component\DependencyInjection\Attribute\Target; + use Symfony\Component\Routing\RouterInterface; + use Symfony\Contracts\Service\Attribute\SubscribedService; + use Symfony\Contracts\Service\ServiceSubscriberInterface; + use Symfony\Contracts\Service\ServiceSubscriberTrait; + + class MyService implements ServiceSubscriberInterface + { + use ServiceSubscriberTrait; + + public function doSomething() + { + // $this->environment() ... + // $this->router() ... + // $this->logger() ... + } + + #[SubscribedService(attributes: new Autowire('%kernel.environment%'))] + private function environment(): string + { + return $this->container->get(__METHOD__); + } + + #[SubscribedService(attributes: new Autowire(service: 'router'))] + private function router(): RouterInterface + { + return $this->container->get(__METHOD__); + } + + #[SubscribedService(attributes: new Target('requestLogger'))] + private function logger(): LoggerInterface + { + return $this->container->get(__METHOD__); + } + } + .. _`Command pattern`: https://en.wikipedia.org/wiki/Command_pattern