Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit defdea4

Browse filesBrowse files
committed
feature #15731 [DependencyInjection] Add section about Service Closures (HypeMC)
This PR was merged into the 5.4 branch. Discussion ---------- [DependencyInjection] Add section about Service Closures Documents service closures added in symfony/symfony#21770 and symfony/symfony#41176, and the `service_closure()` PHP-DSL function added in symfony/symfony#42625 . Commits ------- f2b2fdb [DI] Add section about Service Closures
2 parents 951ed0d + f2b2fdb commit defdea4
Copy full SHA for defdea4

File tree

3 files changed

+122
-1
lines changed
Filter options

3 files changed

+122
-1
lines changed

‎service_container/lazy_services.rst

Copy file name to clipboardExpand all lines: service_container/lazy_services.rst
+2-1Lines changed: 2 additions & 1 deletion
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 are 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
------------------
+115Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
.. index::
2+
single: DependencyInjection; Service Closures
3+
4+
Service Closures
5+
================
6+
7+
.. versionadded:: 5.4
8+
9+
The ``service_closure()`` function was introduced in Symfony 5.4.
10+
11+
This feature wraps the injected service into a closure allowing it to be
12+
lazily loaded when and if needed.
13+
This is useful if the service being injected is a bit heavy to instantiate
14+
or is used only in certain cases.
15+
The service is instantiated the first time the closure is called, while
16+
all subsequent calls return the same instance, unless the service is
17+
:doc:`not shared </service_container/shared>`::
18+
19+
// src/Service/MyService.php
20+
namespace App\Service;
21+
22+
use Symfony\Component\Mailer\MailerInterface;
23+
24+
class MyService
25+
{
26+
/**
27+
* @var callable(): MailerInterface
28+
*/
29+
private \Closure $mailer;
30+
31+
public function __construct(\Closure $mailer)
32+
{
33+
$this->mailer = $mailer;
34+
}
35+
36+
public function doSomething(): void
37+
{
38+
// ...
39+
40+
$this->getMailer()->send($email);
41+
}
42+
43+
private function getMailer(): MailerInterface
44+
{
45+
return ($this->mailer)();
46+
}
47+
}
48+
49+
To define a service closure and inject it to another service, create an
50+
argument of type ``service_closure``:
51+
52+
.. configuration-block::
53+
54+
.. code-block:: yaml
55+
56+
# config/services.yaml
57+
services:
58+
App\Service\MyService:
59+
arguments: [!service_closure '@mailer']
60+
61+
.. code-block:: xml
62+
63+
<!-- config/services.xml -->
64+
<?xml version="1.0" encoding="UTF-8" ?>
65+
<container xmlns="http://symfony.com/schema/dic/services"
66+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
67+
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
68+
69+
<services>
70+
<service id="App\Service\MyService">
71+
<argument type="service_closure" id="mailer"/>
72+
</service>
73+
</services>
74+
</container>
75+
76+
.. code-block:: php
77+
78+
// config/services.php
79+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
80+
81+
use App\Service\MyService;
82+
83+
return function (ContainerConfigurator $containerConfigurator) {
84+
$services = $containerConfigurator->services();
85+
86+
$services->set(MyService::class)
87+
->args([service_closure('mailer')]);
88+
89+
// In case the dependency is optional
90+
// $services->set(MyService::class)
91+
// ->args([service_closure('mailer')->ignoreOnInvalid()]);
92+
};
93+
94+
.. seealso::
95+
96+
Another way to inject services lazily is via a
97+
:doc:`service locator </service_container/service_subscribers_locators>`.
98+
99+
Using a Service Closure in a Compiler Pass
100+
------------------------------------------
101+
102+
In :doc:`compiler passes </service_container/compiler_passes>` you can create
103+
a service closure by wrapping the service reference into an instance of
104+
:class:`Symfony\\Component\\DependencyInjection\\Argument\\ServiceClosureArgument`::
105+
106+
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
107+
use Symfony\Component\DependencyInjection\ContainerBuilder;
108+
use Symfony\Component\DependencyInjection\Reference;
109+
110+
public function process(ContainerBuilder $containerBuilder): void
111+
{
112+
// ...
113+
114+
$myService->addArgument(new ServiceClosureArgument(new Reference('mailer')));
115+
}

‎service_container/service_subscribers_locators.rst

Copy file name to clipboardExpand all lines: service_container/service_subscribers_locators.rst
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ 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
18+
:doc:`service closure </service_container/service_closures>`.
19+
1520
This can typically be the case in your controllers, where you may inject several
1621
services in the constructor, but the action called only uses some of them.
1722
Another example are applications that implement the `Command pattern`_

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.