@@ -131,35 +131,298 @@ a relative or absolute path to the imported file:
131
131
->exclude('../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}');
132
132
};
133
133
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:
152
235
153
236
..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
+
154
307
..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
+ };
163
426
164
427
..include ::/components/dependency_injection/_imports-parameters-note.rst.inc
165
428