Home > other >  Symfony DependencyInjection : import multiple resources (yaml)
Symfony DependencyInjection : import multiple resources (yaml)

Time:11-02

I am trying to implement Symfony Dependency Injection Component (https://symfony.com/doc/current/components/dependency_injection.html) in a non Symfony project.

It works well if I put all my services and parameters into a single "services.yaml" file. Ex:

# services.yaml

parameters:
    mysql.host: "127.0.0.1"
    mysql.database: "database"
    mysql.username: "root"
    mysql.password: ""

    oracle.database: ""
    oracle.username: ""
    oracle.password: ""

    cookie.domain: ".site.local"
    cookie.lifetime: 0
    cookie.useHttps: true

services:
    _defaults:
        autowire: true
        autoconfigure: true

    App\:
        resource: '../src/*'
        exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'

    OtherNamespace\:
        resource: '../someHomemadeLibrary/src/*'
    
    OtherNamespace\Database\Drivers\MySqlDriver:
        class: OtherNamespace\Database\Drivers\MySqlDriver
        arguments:
            $host: "%mysql.host%"
            $database: "%mysql.database%"
            $username: "%mysql.username%"
            $password: "%mysql.password%"

    # ...    

As the file is getting very large, I wanted to split it into different files, as explained here : https://symfony.com/doc/current/service_container/import.html#importing-configuration-with-imports

So I tried :

# index.php

$containerBuilder = new ContainerBuilder();
$loader = new YamlFileLoader($containerBuilder, new FileLocator('config/'));
$loader->load('services.yaml');
# services.yaml

imports:
    - { resource: "databases.yaml" }
    - { resource: "sessions.yaml" }

services:
    _defaults:
        autowire: true
        autoconfigure: true

    App\:
        resource: '../src/*'
        exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'


    OtherNamespace\:
        resource: '../someHomemadeLibrary/src/*'

# databases.yaml

parameters:
    mysql.host: "127.0.0.1"
    mysql.database: "database"
    mysql.username: "root"
    mysql.password: ""

services:
    OtherNamespace\Database\Drivers\MySqlDriver:
        class: OtherNamespace\Database\Drivers\MySqlDriver
        arguments:
            $host: "%mysql.host%"
            $database: "%mysql.database%"
            $username: "%mysql.username%"
            $password: "%mysql.password%"

    # ...  

But in this configuration, I get the following error :

Fatal error: Uncaught Symfony\Component\DependencyInjection\Exception\RuntimeException: Cannot autowire service "OtherNamespace\Database\Drivers\MySqlDriver": argument "$host" of method "__construct()" is type-hinted "string", you should configure its value explicitly.

If I switch the import order, then it is the CookieSession that has a problem. It is like the import is overriding the parameters and services to only use the last one ? How can I split my services and their parameters in multiple files ?

Thank you !

CodePudding user response:

The problem was that my services were correctly imported from my databases.yaml and other yaml into my services.yaml file, but in this file, I also had automatic classes conversion into services.

So my services defined were reloaded/converted, but without the parameters and all. I added exclusions and it works!

    App\:
        resource: '../src/*'
        exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'


    OtherNamespace\:
        resource: '../someHomemadeLibrary/src/*'
        exclude: 
        [
            '.../theClassFileDeclaredInAnotherYaml.php',
            '../or/a/whole/folder/not/to/be/loaded/again/*.php'
        ]

Thanks to @NicoHaase, @Cerad and @WillB. for their help !

  • Related