Skip to content

Commit bf50adc

Browse files
committed
Reword
1 parent 3e0ea84 commit bf50adc

File tree

1 file changed

+289
-26
lines changed

1 file changed

+289
-26
lines changed

service_container/import.rst

Lines changed: 289 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -131,35 +131,298 @@ a relative or absolute path to the imported file:
131131
->exclude('../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}');
132132
};
133133
134-
When loading a configuration file, Symfony loads first the imported files and
135-
then it processes the parameters and services defined in the file. If you use the
136-
:ref:`default services.yaml configuration <service-container-services-load-example>`
137-
as in the above example, the ``App\`` definition creates services for classes
138-
found in ``../src/*``. If your imported file defines services for those classes
139-
too, they will be overridden.
140-
141-
There are exactly three possible solutions in order services not to get overriden:
142-
1. Include the file with ``App\`` statement in the ``imports`` as the first element.
143-
In order to the fact that the ``imports`` statement not override existing services, it checks if the services exists,
144-
also take into account that the last element of the ``imports`` has the highest priority and will be executed first,
145-
having included ``App\`` as a first element of ``imports`` (with the lowest priority) it will be imported in the end.
146-
And being the last import element it will only add not existing services in the container.
147-
2. Include the path to the service in the ``exclude`` section.
148-
3. Write service definitions down the ``App\`` statement to override it
149-
150-
It's recommended to use the 1st approach to define services in the container
151-
Using the first approach the whole ``services.yaml`` file will look the foolowing way:
134+
When loading a configuration file, Symfony first processes all imported files in
135+
the order they are listed under the ``imports`` key. After all imports are processed,
136+
it then processes the parameters and services defined directly in the current file.
137+
In practice, this means that **later definitions override earlier ones**.
138+
139+
For example, if you use the :ref:`default services.yaml configuration <service-container-services-load-example>`
140+
as in the above example, your main ``config/services.yaml`` file uses the ``App\``
141+
namespace to auto-discover services and loads them after all imported files.
142+
If an imported file (e.g. ``config/services/mailer.yaml``) defines a service that
143+
is also auto-discovered, the definition from ``services.yaml`` will take precedence.
144+
145+
To make sure your specific service definitions are not overridden by auto-discovery,
146+
consider one of the following strategies:
147+
148+
#. :ref:`Exclude services from auto-discovery <import-exclude-services-from-auto-discovery>`
149+
#. :ref:`Override services in the same file <import-override-services-in-the-same-file>`
150+
#. :ref:`Control import order <import-control-import-order>`
151+
152+
.. _import-exclude-services-from-auto-discovery:
153+
154+
**Exclude services from auto-discovery**
155+
156+
Adjust the ``App\`` definition to use the ``exclude`` option. This prevents Symfony
157+
from auto-registering classes that are defined manually elsewhere:
158+
159+
.. configuration-block::
160+
161+
.. code-block:: yaml
162+
163+
# config/services.yaml
164+
imports:
165+
- { resource: services/mailer.yaml }
166+
# ... other imports
167+
168+
services:
169+
_defaults:
170+
autowire: true
171+
autoconfigure: true
172+
173+
App\:
174+
resource: '../src/*'
175+
exclude:
176+
- '../src/Mailer/'
177+
- '../src/SpecificClass.php'
178+
179+
.. code-block:: xml
180+
181+
<!-- config/services.xml -->
182+
<?xml version="1.0" encoding="UTF-8" ?>
183+
<container xmlns="http://symfony.com/schema/dic/services"
184+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
185+
xsi:schemaLocation="http://symfony.com/schema/dic/services
186+
https://symfony.com/schema/dic/services/services-1.0.xsd">
187+
188+
<imports>
189+
<import resource="services/mailer.xml"/>
190+
<!-- If you want to import a whole directory: -->
191+
<import resource="services/"/>
192+
</imports>
193+
194+
<services>
195+
<defaults autowire="true" autoconfigure="true"/>
196+
197+
<prototype namespace="App\" resource="../src/*">
198+
<exclude>../src/Mailer/</exclude>
199+
<exclude>../src/SpecificClass.php</exclude>
200+
</prototype>
201+
202+
<!-- ... -->
203+
</services>
204+
</container>
205+
206+
.. code-block:: php
207+
208+
// config/services.php
209+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
210+
211+
return function(ContainerConfigurator $container): void {
212+
$container->import('services/mailer.php');
213+
// If you want to import a whole directory:
214+
$container->import('services/');
215+
216+
$services = $container->services()
217+
->defaults()
218+
->autowire()
219+
->autoconfigure()
220+
;
221+
222+
$services->load('App\\', '../src/*')
223+
->exclude([
224+
'../src/Mailer/',
225+
'../src/SpecificClass.php',
226+
]);
227+
};
228+
229+
.. _import-override-services-in-the-same-file:
230+
231+
**Override services in the same file**
232+
233+
You can define specific services after the ``App\`` auto-discovery block in the
234+
same file. These later definitions will override the auto-registered ones:
152235

153236
.. configuration-block::
237+
238+
.. code-block:: yaml
239+
240+
# config/services.yaml
241+
services:
242+
_defaults:
243+
autowire: true
244+
autoconfigure: true
245+
246+
App\:
247+
resource: '../src/*'
248+
249+
App\Mailer\MyMailer:
250+
arguments: ['%env(MAILER_DSN)%']
251+
252+
.. code-block:: xml
253+
254+
<!-- config/services.xml -->
255+
<?xml version="1.0" encoding="UTF-8" ?>
256+
<container xmlns="http://symfony.com/schema/dic/services"
257+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
258+
xsi:schemaLocation="http://symfony.com/schema/dic/services
259+
https://symfony.com/schema/dic/services/services-1.0.xsd">
260+
261+
<imports>
262+
<import resource="services/mailer.xml"/>
263+
<!-- If you want to import a whole directory: -->
264+
<import resource="services/"/>
265+
</imports>
266+
267+
<services>
268+
<defaults autowire="true" autoconfigure="true"/>
269+
270+
<prototype namespace="App\" resource="../src/*"/>
271+
272+
<service id="App\Mailer\MyMailer">
273+
<argument>%env(MAILER_DSN)%</argument>
274+
</service>
275+
276+
<!-- ... -->
277+
</services>
278+
</container>
279+
280+
.. code-block:: php
281+
282+
// config/services.php
283+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
284+
285+
return function(ContainerConfigurator $container): void {
286+
$services = $container->services()
287+
->defaults()
288+
->autowire()
289+
->autoconfigure();
290+
291+
$services->load('App\\', '../src/*');
292+
293+
$services->set(App\Mailer\MyMailer::class)
294+
->arg(0, '%env(MAILER_DSN)%');
295+
};
296+
297+
.. _import-control-import-order:
298+
299+
**Control import order**
300+
301+
Move the ``App\`` auto-discovery config to a separate file and import it
302+
before more specific service files. This way, specific service definitions
303+
can override the auto-discovered ones.
304+
305+
.. configuration-block::
306+
154307
.. code-block:: yaml
155-
###> imports are loaded first (imports not overrides existing services) ###
156-
imports:
157-
- resource: 'services_yaml/resource_services.yaml' # PRIORITY 1 (last) (contains App\ with resource statement)
158-
- resource: 'services_yaml/services/' # PRIORITY 2
159-
- resource: 'services_yaml/parameters/' # PRIORITY 3 (first)
160-
161-
###> then services.yaml (what below overrides imports) ###
162-
###>... it's better to use only imports
308+
309+
# config/services/autodiscovery.yaml
310+
services:
311+
_defaults:
312+
autowire: true
313+
autoconfigure: true
314+
315+
App\:
316+
resource: '../../src/*'
317+
exclude:
318+
- '../../src/Mailer/'
319+
320+
# config/services/mailer.yaml
321+
services:
322+
App\Mailer\SpecificMailer:
323+
# ... custom configuration
324+
325+
# config/services.yaml
326+
imports:
327+
- { resource: services/autodiscovery.yaml }
328+
- { resource: services/mailer.yaml }
329+
- { resource: services/ }
330+
331+
services:
332+
# definitions here override anything from the imports above
333+
# consider keeping most definitions inside imported files
334+
335+
.. code-block:: xml
336+
337+
<!-- config/services/autodiscovery.xml -->
338+
<?xml version="1.0" encoding="UTF-8" ?>
339+
<container xmlns="http://symfony.com/schema/dic/services"
340+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
341+
xsi:schemaLocation="http://symfony.com/schema/dic/services
342+
https://symfony.com/schema/dic/services/services-1.0.xsd">
343+
344+
<services>
345+
<defaults autowire="true" autoconfigure="true"/>
346+
347+
<prototype namespace="App\" resource="../../src/*">
348+
<exclude>../../src/Mailer/</exclude>
349+
</prototype>
350+
</services>
351+
</container>
352+
353+
<!-- config/services/mailer.xml -->
354+
<?xml version="1.0" encoding="UTF-8" ?>
355+
<container xmlns="http://symfony.com/schema/dic/services"
356+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
357+
xsi:schemaLocation="http://symfony.com/schema/dic/services
358+
https://symfony.com/schema/dic/services/services-1.0.xsd">
359+
360+
<services>
361+
<service id="App\Mailer\SpecificMailer">
362+
<!-- ... custom configuration -->
363+
</service>
364+
</services>
365+
</container>
366+
367+
<!-- config/services.xml -->
368+
<?xml version="1.0" encoding="UTF-8" ?>
369+
<container xmlns="http://symfony.com/schema/dic/services"
370+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
371+
xsi:schemaLocation="http://symfony.com/schema/dic/services
372+
https://symfony.com/schema/dic/services/services-1.0.xsd">
373+
374+
<imports>
375+
<import resource="services/autodiscovery.xml"/>
376+
<import resource="services/mailer.xml"/>
377+
<import resource="services/"/>
378+
</imports>
379+
380+
<services>
381+
<!-- definitions here override anything from the imports above -->
382+
<!-- consider keeping most definitions inside imported files -->
383+
</services>
384+
</container>
385+
386+
.. code-block:: php
387+
388+
// config/services/autodiscovery.php
389+
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
390+
391+
return function (ContainerConfigurator $container): void {
392+
$services = $container->services()
393+
->defaults()
394+
->autowire()
395+
->autoconfigure();
396+
397+
$services->load('App\\', '../../src/*')
398+
->exclude([
399+
'../../src/Mailer/',
400+
]);
401+
};
402+
403+
// config/services/mailer.php
404+
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
405+
406+
return function (ContainerConfigurator $container): void {
407+
$services = $container->services();
408+
409+
$services->set(App\Mailer\SpecificMailer::class);
410+
// Add any custom configuration here if needed
411+
};
412+
413+
// config/services.php
414+
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
415+
416+
return function (ContainerConfigurator $container): void {
417+
$container->import('services/autodiscovery.php');
418+
$container->import('services/mailer.php');
419+
$container->import('services/');
420+
421+
$services = $container->services();
422+
423+
// definitions here override anything from the imports above
424+
// consider keeping most definitions inside imported files
425+
};
163426
164427
.. include:: /components/dependency_injection/_imports-parameters-note.rst.inc
165428

0 commit comments

Comments
 (0)