Skip to content

Commit f61e70c

Browse files
committed
minor #9989 Tell about controllers in doc about service subscribers (nicolas-grekas, javiereguiluz)
This PR was merged into the 3.4 branch. Discussion ---------- Tell about controllers in doc about service subscribers Fixes #8872 Might need a link from ./controller.rst Where do we tell about action injection btw? Commits ------- 81738f0 Minor rewords e2e0b44 Tell about controllers in doc about service subscribers
2 parents cb8ebdb + 81738f0 commit f61e70c

File tree

1 file changed

+25
-29
lines changed

1 file changed

+25
-29
lines changed

service_container/service_subscribers_locators.rst

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ instantiation of the services to be lazy. However, that's not possible using
1313
the explicit dependency injection since services are not all meant to
1414
be ``lazy`` (see :doc:`/service_container/lazy_services`).
1515

16-
A real-world example are applications that implement the `Command pattern`_
16+
This can typically be the case in your controllers, where you may inject several
17+
services in the constructor, but the action executed only uses some of them.
18+
Another example are applications that implement the `Command pattern`_
1719
using a CommandBus to map command handlers by Command class names and use them
1820
to handle their respective command when it is asked for::
1921

@@ -50,35 +52,12 @@ to handle their respective command when it is asked for::
5052

5153
Considering that only one command is handled at a time, instantiating all the
5254
other command handlers is unnecessary. A possible solution to lazy-load the
53-
handlers could be to inject the whole dependency injection container::
54-
55-
// ...
56-
use Symfony\Component\DependencyInjection\ContainerInterface;
57-
58-
class CommandBus
59-
{
60-
private $container;
61-
62-
public function __construct(ContainerInterface $container)
63-
{
64-
$this->container = $container;
65-
}
66-
67-
public function handle(Command $command)
68-
{
69-
$commandClass = get_class($command);
70-
71-
if ($this->container->has($commandClass)) {
72-
$handler = $this->container->get($commandClass);
73-
74-
return $handler->handle($command);
75-
}
76-
}
77-
}
55+
handlers could be to inject the main dependency injection container.
7856

7957
However, injecting the entire container is discouraged because it gives too
8058
broad access to existing services and it hides the actual dependencies of the
81-
services.
59+
services. Doing so also requires services to be made public, which isn't the
60+
case by default in Symfony applications.
8261

8362
**Service Subscribers** are intended to solve this problem by giving access to a
8463
set of predefined services while instantiating them only when actually needed
@@ -139,8 +118,7 @@ The injected service is an instance of :class:`Symfony\\Component\\DependencyInj
139118
which implements the PSR-11 ``ContainerInterface``, but it is also a callable::
140119

141120
// ...
142-
$locateHandler = $this->locator;
143-
$handler = $locateHandler($commandClass);
121+
$handler = ($this->locator)($commandClass);
144122

145123
return $handler->handle($command);
146124

@@ -173,6 +151,24 @@ Service types can also be keyed by a service name for internal use::
173151
];
174152
}
175153

154+
When extending a class that also implements ``ServiceSubscriberInterface``,
155+
it's your responsibility to call the parent when overriding the method. This
156+
typically happens when extending ``AbstractController``::
157+
158+
use Psr\Log\LoggerInterface;
159+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
160+
161+
class MyController extends AbstractController
162+
{
163+
public static function getSubscribedServices()
164+
{
165+
return array_merge(parent::getSubscribedServices(), [
166+
// ...
167+
'logger' => LoggerInterface::class,
168+
]);
169+
}
170+
}
171+
176172
Optional Services
177173
~~~~~~~~~~~~~~~~~
178174

0 commit comments

Comments
 (0)