Skip to content

Commit 3cf0bab

Browse files
committed
Merge branch '7.2' into 7.3
* 7.2: Reword Update import.rst
2 parents 5bab527 + f35d5a7 commit 3cf0bab

File tree

1 file changed

+292
-11
lines changed

1 file changed

+292
-11
lines changed

service_container/import.rst

Lines changed: 292 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -128,17 +128,298 @@ a relative or absolute path to the imported file:
128128
$services->load('App\\', '../src/*');
129129
};
130130
131-
When loading a configuration file, Symfony loads first the imported files and
132-
then it processes the parameters and services defined in the file. If you use the
133-
:ref:`default services.yaml configuration <service-container-services-load-example>`
134-
as in the above example, the ``App\`` definition creates services for classes
135-
found in ``../src/*``. If your imported file defines services for those classes
136-
too, they will be overridden.
137-
138-
A possible solution for this is to add the classes and/or directories of the
139-
imported files in the ``exclude`` option of the ``App\`` definition. Another
140-
solution is to not use imports and add the service definitions in the same file,
141-
but after the ``App\`` definition to override it.
131+
When loading a configuration file, Symfony first processes all imported files in
132+
the order they are listed under the ``imports`` key. After all imports are processed,
133+
it then processes the parameters and services defined directly in the current file.
134+
In practice, this means that **later definitions override earlier ones**.
135+
136+
For example, if you use the :ref:`default services.yaml configuration <service-container-services-load-example>`
137+
as in the above example, your main ``config/services.yaml`` file uses the ``App\``
138+
namespace to auto-discover services and loads them after all imported files.
139+
If an imported file (e.g. ``config/services/mailer.yaml``) defines a service that
140+
is also auto-discovered, the definition from ``services.yaml`` will take precedence.
141+
142+
To make sure your specific service definitions are not overridden by auto-discovery,
143+
consider one of the following strategies:
144+
145+
#. :ref:`Exclude services from auto-discovery <import-exclude-services-from-auto-discovery>`
146+
#. :ref:`Override services in the same file <import-override-services-in-the-same-file>`
147+
#. :ref:`Control import order <import-control-import-order>`
148+
149+
.. _import-exclude-services-from-auto-discovery:
150+
151+
**Exclude services from auto-discovery**
152+
153+
Adjust the ``App\`` definition to use the ``exclude`` option. This prevents Symfony
154+
from auto-registering classes that are defined manually elsewhere:
155+
156+
.. configuration-block::
157+
158+
.. code-block:: yaml
159+
160+
# config/services.yaml
161+
imports:
162+
- { resource: services/mailer.yaml }
163+
# ... other imports
164+
165+
services:
166+
_defaults:
167+
autowire: true
168+
autoconfigure: true
169+
170+
App\:
171+
resource: '../src/*'
172+
exclude:
173+
- '../src/Mailer/'
174+
- '../src/SpecificClass.php'
175+
176+
.. code-block:: xml
177+
178+
<!-- config/services.xml -->
179+
<?xml version="1.0" encoding="UTF-8" ?>
180+
<container xmlns="http://symfony.com/schema/dic/services"
181+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
182+
xsi:schemaLocation="http://symfony.com/schema/dic/services
183+
https://symfony.com/schema/dic/services/services-1.0.xsd">
184+
185+
<imports>
186+
<import resource="services/mailer.xml"/>
187+
<!-- If you want to import a whole directory: -->
188+
<import resource="services/"/>
189+
</imports>
190+
191+
<services>
192+
<defaults autowire="true" autoconfigure="true"/>
193+
194+
<prototype namespace="App\" resource="../src/*">
195+
<exclude>../src/Mailer/</exclude>
196+
<exclude>../src/SpecificClass.php</exclude>
197+
</prototype>
198+
199+
<!-- ... -->
200+
</services>
201+
</container>
202+
203+
.. code-block:: php
204+
205+
// config/services.php
206+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
207+
208+
return function(ContainerConfigurator $container): void {
209+
$container->import('services/mailer.php');
210+
// If you want to import a whole directory:
211+
$container->import('services/');
212+
213+
$services = $container->services()
214+
->defaults()
215+
->autowire()
216+
->autoconfigure()
217+
;
218+
219+
$services->load('App\\', '../src/*')
220+
->exclude([
221+
'../src/Mailer/',
222+
'../src/SpecificClass.php',
223+
]);
224+
};
225+
226+
.. _import-override-services-in-the-same-file:
227+
228+
**Override services in the same file**
229+
230+
You can define specific services after the ``App\`` auto-discovery block in the
231+
same file. These later definitions will override the auto-registered ones:
232+
233+
.. configuration-block::
234+
235+
.. code-block:: yaml
236+
237+
# config/services.yaml
238+
services:
239+
_defaults:
240+
autowire: true
241+
autoconfigure: true
242+
243+
App\:
244+
resource: '../src/*'
245+
246+
App\Mailer\MyMailer:
247+
arguments: ['%env(MAILER_DSN)%']
248+
249+
.. code-block:: xml
250+
251+
<!-- config/services.xml -->
252+
<?xml version="1.0" encoding="UTF-8" ?>
253+
<container xmlns="http://symfony.com/schema/dic/services"
254+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
255+
xsi:schemaLocation="http://symfony.com/schema/dic/services
256+
https://symfony.com/schema/dic/services/services-1.0.xsd">
257+
258+
<imports>
259+
<import resource="services/mailer.xml"/>
260+
<!-- If you want to import a whole directory: -->
261+
<import resource="services/"/>
262+
</imports>
263+
264+
<services>
265+
<defaults autowire="true" autoconfigure="true"/>
266+
267+
<prototype namespace="App\" resource="../src/*"/>
268+
269+
<service id="App\Mailer\MyMailer">
270+
<argument>%env(MAILER_DSN)%</argument>
271+
</service>
272+
273+
<!-- ... -->
274+
</services>
275+
</container>
276+
277+
.. code-block:: php
278+
279+
// config/services.php
280+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
281+
282+
return function(ContainerConfigurator $container): void {
283+
$services = $container->services()
284+
->defaults()
285+
->autowire()
286+
->autoconfigure();
287+
288+
$services->load('App\\', '../src/*');
289+
290+
$services->set(App\Mailer\MyMailer::class)
291+
->arg(0, '%env(MAILER_DSN)%');
292+
};
293+
294+
.. _import-control-import-order:
295+
296+
**Control import order**
297+
298+
Move the ``App\`` auto-discovery config to a separate file and import it
299+
before more specific service files. This way, specific service definitions
300+
can override the auto-discovered ones.
301+
302+
.. configuration-block::
303+
304+
.. code-block:: yaml
305+
306+
# config/services/autodiscovery.yaml
307+
services:
308+
_defaults:
309+
autowire: true
310+
autoconfigure: true
311+
312+
App\:
313+
resource: '../../src/*'
314+
exclude:
315+
- '../../src/Mailer/'
316+
317+
# config/services/mailer.yaml
318+
services:
319+
App\Mailer\SpecificMailer:
320+
# ... custom configuration
321+
322+
# config/services.yaml
323+
imports:
324+
- { resource: services/autodiscovery.yaml }
325+
- { resource: services/mailer.yaml }
326+
- { resource: services/ }
327+
328+
services:
329+
# definitions here override anything from the imports above
330+
# consider keeping most definitions inside imported files
331+
332+
.. code-block:: xml
333+
334+
<!-- config/services/autodiscovery.xml -->
335+
<?xml version="1.0" encoding="UTF-8" ?>
336+
<container xmlns="http://symfony.com/schema/dic/services"
337+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
338+
xsi:schemaLocation="http://symfony.com/schema/dic/services
339+
https://symfony.com/schema/dic/services/services-1.0.xsd">
340+
341+
<services>
342+
<defaults autowire="true" autoconfigure="true"/>
343+
344+
<prototype namespace="App\" resource="../../src/*">
345+
<exclude>../../src/Mailer/</exclude>
346+
</prototype>
347+
</services>
348+
</container>
349+
350+
<!-- config/services/mailer.xml -->
351+
<?xml version="1.0" encoding="UTF-8" ?>
352+
<container xmlns="http://symfony.com/schema/dic/services"
353+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
354+
xsi:schemaLocation="http://symfony.com/schema/dic/services
355+
https://symfony.com/schema/dic/services/services-1.0.xsd">
356+
357+
<services>
358+
<service id="App\Mailer\SpecificMailer">
359+
<!-- ... custom configuration -->
360+
</service>
361+
</services>
362+
</container>
363+
364+
<!-- config/services.xml -->
365+
<?xml version="1.0" encoding="UTF-8" ?>
366+
<container xmlns="http://symfony.com/schema/dic/services"
367+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
368+
xsi:schemaLocation="http://symfony.com/schema/dic/services
369+
https://symfony.com/schema/dic/services/services-1.0.xsd">
370+
371+
<imports>
372+
<import resource="services/autodiscovery.xml"/>
373+
<import resource="services/mailer.xml"/>
374+
<import resource="services/"/>
375+
</imports>
376+
377+
<services>
378+
<!-- definitions here override anything from the imports above -->
379+
<!-- consider keeping most definitions inside imported files -->
380+
</services>
381+
</container>
382+
383+
.. code-block:: php
384+
385+
// config/services/autodiscovery.php
386+
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
387+
388+
return function (ContainerConfigurator $container): void {
389+
$services = $container->services()
390+
->defaults()
391+
->autowire()
392+
->autoconfigure();
393+
394+
$services->load('App\\', '../../src/*')
395+
->exclude([
396+
'../../src/Mailer/',
397+
]);
398+
};
399+
400+
// config/services/mailer.php
401+
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
402+
403+
return function (ContainerConfigurator $container): void {
404+
$services = $container->services();
405+
406+
$services->set(App\Mailer\SpecificMailer::class);
407+
// Add any custom configuration here if needed
408+
};
409+
410+
// config/services.php
411+
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
412+
413+
return function (ContainerConfigurator $container): void {
414+
$container->import('services/autodiscovery.php');
415+
$container->import('services/mailer.php');
416+
$container->import('services/');
417+
418+
$services = $container->services();
419+
420+
// definitions here override anything from the imports above
421+
// consider keeping most definitions inside imported files
422+
};
142423
143424
.. include:: /components/dependency_injection/_imports-parameters-note.rst.inc
144425

0 commit comments

Comments
 (0)