tarasovich/symfony-yaml-merge-loader

Possibility to merge imports in services.yaml

v1.0.0 2022-07-05 10:54 UTC

This package is auto-updated.

Last update: 2025-06-05 17:32:36 UTC


README

This is extension of Symfony\Component\DependencyInjection\Loader\YamlFileLoader adding possibility to merge imports in services.yaml:

# config/services.yaml
imports:
- { resource: 'services/*.yaml', merge: true }

Complication

From Official symfony docs:

When loading a configuration file, Symfony loads first the imported files and then it processes the parameters and services defined in the file. If you use the default services.yaml configuration, the App\ definition creates services for classes found in ../src/*. If your imported file defines services for those classes too, they will be overridden.

A possible solution for this is to add the classes and/or directories of the imported files in the exclude option of the App\ definition. Another solution is to not use imports and add the service definitions in the same file, but after the App\ definition to override it.“

With this extension you don't need to exclude imported services from App\ definition.

Installation

Get the extension using composer

Add YamlFileMergeLoader by running this command from the terminal at the root of your Symfony project:

composer require tarasovich/symfony-yaml-merge-loader

Replace default loader

// src/Kernel.php (your kernel class may be defined in a different class/path)
namespace App;

use Symfony\Component\HttpKernel\Kernel as BaseKernel;
use Tarasovich\YamlFileMergeLoader;
// ...

class Kernel extends BaseKernel
{
    protected function getContainerLoader(ContainerInterface $container): LoaderInterface
    {
        /** @var ContainerBuilder $container */
        return YamlFileMergeLoader::replaceOriginalLoader(
            $container,
            parent::getContainerLoader($container),
            $this->getEnvironment()
        );
    }
}

Organize imports files

Move some services and/or parameters definitions into other file, eg:

# config/services/hello_word.yaml
parameters:
  app.hello_word.text: 'Hello World!'

services:
  _defaults:
    autowire: true
    autoconfigure: true

  App\Service\HelloWordService:
    arguments:
      $defaultText: '%app.hello_word.text%'

Import resource to your services.yaml with merge: true option.

# config/services.yaml
imports:
- { resource: 'services/*.yaml', merge: true }

services:
  _defaults:
    autowire: true
    autoconfigure: true

  App\:
    resource: '../src/'
    exclude:
      - '../src/DependencyInjection/'
      - '../src/Entity/'
      - '../src/Kernel.php'
      - '../src/Tests/'

That was it!

Now your App\Service\HelloWordService will be not overridden with the App\ definition from config/services.yaml.