Skip to content

Commit 722e76e

Browse files
committed
[DI] Add section about Service Closures
1 parent c0f4dd4 commit 722e76e

File tree

3 files changed

+98
-1
lines changed

3 files changed

+98
-1
lines changed

service_container/lazy_services.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ Lazy Services
66

77
.. seealso::
88

9-
Another way to inject services lazily is via a :doc:`service subscriber </service_container/service_subscribers_locators>`.
9+
Other ways to inject services lazily is via a :doc:`service closure </service_container/service_closures>` or
10+
:doc:`service subscriber </service_container/service_subscribers_locators>`.
1011

1112
Why Lazy Services?
1213
------------------
+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
.. index::
2+
single: DependencyInjection; Service Closures
3+
4+
Service Closures
5+
================
6+
7+
This feature wraps the injected service into a closure allowing it to be
8+
lazily loaded when and if needed.
9+
This is useful if the service being injected is a bit heavy to instantiate
10+
or is used only in certain cases.
11+
The service is instantiated the first time the closure is called, while
12+
all subsequent calls return the same instance, unless the service is
13+
:doc:`not shared </service_container/shared>`::
14+
15+
// src/Service/MyService.php
16+
namespace App\Service;
17+
18+
use Symfony\Component\Mailer\MailerInterface;
19+
20+
class MyService
21+
{
22+
/**
23+
* @var callable(): MailerInterface
24+
*/
25+
private \Closure $mailer;
26+
27+
public function __construct(\Closure $mailer)
28+
{
29+
$this->mailer = $mailer;
30+
}
31+
32+
public function doSomething(): void
33+
{
34+
// ...
35+
36+
$this->getMailer()->send($email);
37+
}
38+
39+
private function getMailer(): MailerInterface
40+
{
41+
return ($this->mailer)();
42+
}
43+
}
44+
45+
To define a service closure and inject it to another service, create an
46+
argument of type ``service_closure``:
47+
48+
.. configuration-block::
49+
50+
.. code-block:: yaml
51+
52+
# config/services.yaml
53+
services:
54+
App\Service\MyService:
55+
arguments: [!service_closure '@mailer']
56+
57+
.. code-block:: xml
58+
59+
<!-- config/services.xml -->
60+
<?xml version="1.0" encoding="UTF-8" ?>
61+
<container xmlns="http://symfony.com/schema/dic/services"
62+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
63+
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
64+
65+
<services>
66+
67+
<service id="App\Service\MyService">
68+
<argument type="service_closure" id="mailer"/>
69+
</service>
70+
71+
</services>
72+
</container>
73+
74+
.. code-block:: php
75+
76+
// config/services.php
77+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
78+
79+
use App\Service\MyService;
80+
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
81+
use Symfony\Component\DependencyInjection\Reference;
82+
83+
return function (ContainerConfigurator $configurator) {
84+
$services = $configurator->services();
85+
86+
$services->set(MyService::class)
87+
->args([new ServiceClosureArgument(new Reference('mailer'))]);
88+
};
89+
90+
.. seealso::
91+
92+
Another way to inject services lazily is via a :doc:`service locators </service_container/service_subscribers_locators>`.

service_container/service_subscribers_locators.rst

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ instantiation of the services to be lazy. However, that's not possible using
1212
the explicit dependency injection since services are not all meant to
1313
be ``lazy`` (see :doc:`/service_container/lazy_services`).
1414

15+
.. seealso::
16+
17+
Another way to inject services lazily is via a :doc:`service closure </service_container/service_closures>`.
18+
1519
This can typically be the case in your controllers, where you may inject several
1620
services in the constructor, but the action called only uses some of them.
1721
Another example are applications that implement the `Command pattern`_

0 commit comments

Comments
 (0)