Nicolas Grekas
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 is a medium-term priority for us. We could switch today 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 future Symfony 4 applications, but we'll stick to YAML for a while. In the meantime you can test this new format in your applications and give us feedback about it.

Update: in the first version of this blog post, it was implied that this new format would replace YAML in Symfony 4.0 version. This is wrong. Instead, this new format could (or could not) replace YAML as the default format in a future Symfony version.

Published in #Living on the edge