8 News in Config Transformer that Converts Symfony YML to PHP

If you have not switched your Symfony configs from YAML to PHP, there no better time like present.

This month we tested the ConfigTransformer to its limit. It had to deal with edge-cases from Symfony 2.8 all the way through Symfony 3.4. With features that were removed for years. As a result, we added default processing of *.yaml and .yml syntax at the same time and support for scalars like ::hi and 'hello::'.

That's just the tip of the iceberg. What are the 5 new features you'll be able to enjoy in the upcoming release?

1. New Support for Directory Loader

Since Symfony 2.8, it is possible to load configs from a single directory. That means you can use the shorter syntax...

-    - { resource: packages/doctrine.yml }
-    - { resource: packages/framework.yml }
-    - { resource: packages/security.yml }
+    - { resource: packages/ }

...with the same effect. Now you won't forget to include the config here. It's pretty rare with legacy projects, but still possible syntax.

In the new ConfigTransformer version, we cover directory loading out of the box ✅

2. New Defaults Extensions Autoloaded

The directory loading opened a complete feature list we can cover. E.g., now it's possible to load extensions from these imported configs:

    key: value

We've added the list of 10 default extensions to cover - 'doctrine', 'framework', 'monolog', 'security', 'twig' and more. Including the deprecated ones, e.g. 'assetic'.

This allows us converting a much lower Symfony version than ever - Symfony 2.8 ✅

3. Added Support for autowiring_types

This option was deprecated in Symfony 3.3. If any config contained it, it was skipped.

It was quite a complex challenge because the code is removed in Symfony 6, and ConfigTransformer is built on that version.

But in the end, we managed to add it:

        class: App\SomeClass
        autowiring_types: App\SomeInterface

use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use App\SomeClass;
use App\SomeInterface;

return static function (ContainerConfigurator $containerConfigurator): void {
    $services = $containerConfigurator->services();

    $services->set('some_service', SomeClass::class)

Now it's covered as expected ✅

4. Add Support for Unquoted Scalars

Unquoted scalars were deprecated in Symfony 3.1. If your config had it, the conversion crashed:

    secret: %secret%

Are you using a Symfony version where this is still valid syntax? We have good news for you.

We added automated pre-quoting of scalar so this can be parsed with ease ✅

5. Skip PHP Configs Loading

Usually, we take many little steps when it comes to huge changes. We don't convert all the files at once, but rather one group at a time, e.g. first parameters, then services, then extensions.

That means in certain point of time, we have part configs in PHP and part in YAML:


Before, the ConfigTransformer tried to load the PHP configs and invoked a bunch of class loading and config interpretation, that could crash.

Now it will skip PHP and focuses solely on the YAML files ✅

6. Informative Output with Beautiful Colored Diff

Do you want first to try it on a single file? That's completely normal. I often do that, too, to verify the output is the same as I expect.

At the moment, we can run a --dry-run so we see what changes:

We see some files are removed, and other files are added. Okay, but what about content? At this point, the --dry-run does not change anything, which is correct. But it also doesn't give us any indices to decide to run a command without it. We can do better.

That's why we've redesigned the output to provide the following:

Beautiful and clear ✅

7. Improved Support for when@env

Thanks to Tofandel you can enjoy this impressive feature that handles complex cases of conditional environments:

        toolbar: true
        intercept_redirects: false

        profiler: true

use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
    if ($containerConfigurator->env() === 'local') {
        $containerConfigurator->extension('web_profiler', [
            'toolbar' => true,
            'intercept_redirects' => false,
        $containerConfigurator->extension('framework', [
            'profiler' => true

8. Refactored Constant Support

Last but not least is a feature that focuses on constant. Constants were one of the weakest parts of ConfigTransformer, with a lot of hacking. It was prone to error on non-existing or non-autoloaded constants, which should not happen as the scope of this tool is entirely static.

Again, big thanks to Tofandel, who refactorted it into a smooth solution. It now handles any constant possible:

    class_constant: !php/const App\SomeConst::TEST
    class: !php/const App\SomeConst::class
    unexisting_constant: !php/const App\MissingClass::NOT_HERE
    another_key: '%env(string:default::CODE_EDITOR)%'

use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
    $parameters = $containerConfigurator->parameters();

    $parameters->set('class_constant', App\SomeConst::TEST);
    $parameters->set('class', App\SomeConst::class);
    $parameters->set('unexisting_constant', App\MissingClass::NOT_HERE);
    $parameters->set('another_key', '%env(string:default::CODE_EDITOR)%');

As a bonus, it cut down the converting speed on one project from 3 seconds to 200 ms. That's 1500 % faster.

Thank you ✅

Start Now to Save Work

I'm proud of this leap forward and better support for older Symfony versions. It allows to convert configs to a broader range of projects and start using PHP in earlier stages. That brings Rector, ECS, and PHPStan to help as well, as they cover any PHP file, even configs.

Now it's the best time to switch - here is how

Happy coding!

Do you learn from my contents or use open-souce packages like Rector every day?
Consider supporting it on GitHub Sponsors. I'd really appreciate it!