New in Symfony 3.4: PHP-based configuration for services and routes

Contributed by
Nicolas Grekas
in #23834
and #24180.

Symfony supports several configuration formats out-of-the-box: XML, YAML, PHP and PHP annotations. The best thing is that we don't force you to use any particular format. You are always in charge when deciding the format to use, and you can even mix them (e.g. YAML for basic config, XML for services, and PHP annotations for routes).

By default we use YAML in some of the main configuration files (services.yml, security.yml, config.yml) because it provides a good balance between readability, conciseness and features. However, that requires to have the Yaml component as a dependency of Symfony applications.

Symfony 4 will minimize the dependencies needed by applications (a fresh Symfony 4 application contains 70% less code than a Symfony 3.3 application) so removing this Yaml dependency was a priority for us. We could switch to the existing PHP configuration format, but it's not concise and readable enough.

That's why in Symfony 3.4 we introduced a new PHP-based configuration format to define routes and services. This is how it looks when configuring routes:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// app/config/routing.php
return function (RoutingConfigurator $routes) {
    // import routes defined in a separate file
    $routes->import('legacy_routes.php')
        ->prefix('/legacy')
    ;

    // define the routes using a "fluent interface"
    $routes
        ->add('product', '/products/{id}')
            ->controller('App\Controller\ProductController::show')
            ->schemes(['https'])
            ->requirements(['id' => '\d+'])
            ->defaults(['id' => 0])

        ->add('homepage', '/')
            ->controller('App\Controller\DefaultController::index')
    ;
};

Similarly, a file defining services would look like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// app/config/services.php
return function (ContainerConfigurator $container) {
    $container->import('legacy_services.php');

    $params = $container->parameters();
    $params->set('app.foo_param', 'param_value');

    $container = $container->services()->defaults()
        ->private()
        ->autoconfigure()
        ->autowire();

    $container
        ->load('App\\', '../src/*')
        ->exclude('../src/{Entity,Repository,Tests}');
    $container
        ->load('App\\Controller\\', '../src/Controller')
        ->tag('controller.service_arguments');

    $container->set(FooClass::class)
        ->args(['some_argument', ref(BarClass::class)])
        ->tag('kernel.event_listener', ['event' => 'kernel.exception']);

    $container->alias('foo', FooClass::class)->public();
};

We may use this configuration format by default in Symfony 4 applications, but you will still be able to use your own favorite format, being YAML or XML or PHP annotations. That will never change.

Comments

Symfony 4 will certainly miss default YAML dependency. Anyway, we still can use YAML in Symfony 4, which is good.
What about all the existing bundles that uses YAML? I guess that if I required even only one of them I'll end up with Yaml component installed anyway
Finally ! Nice one !
Such a little Silex, new generation :D
@Massimiliano bundles using the YAML component MUST require it on their composer.json files at it was always be. So yes, it will be required.

I'm really not a big fan of the PHP config, but we still have the choice. ;-)
This blog post is misleading. YAML is still a requirement of Symfony 4 default skeleton and that will stay.
Thanks, @fabien, otherwise I'd go for Silex.
@fabien, this is what I was thinking too.
Aleluya!, Nice approach! this gives a lot of versatility during development! Ty
Login with SensioLabsConnect to post a comment