8000 Replace the fluent PHP config format by the array-shape one by nicolas-grekas · Pull Request #21511 · symfony/symfony-docs · GitHub
[go: up one dir, main page]

Skip to content

Conversation

@nicolas-grekas
Copy link
Member
@nicolas-grekas nicolas-grekas commented Oct 17, 2025

Related to symfony/symfony#62092 symfony/symfony#62129 and https://symfony.com/blog/new-in-symfony-7-4-deprecated-xml-configuration

The diff itself isn't really interesting. What's interesting is comparing yaml to php arrays.

This can give a nice overview of the new format.

@carsonbot carsonbot added this to the 8.0 milestone Oct 17, 2025
@carsonbot carsonbot changed the title Replace the fluent PHP config format by the array-shape one Replace the fluent PHP config format by the array-shape one Oct 17, 2025
@nicolas-grekas nicolas-grekas force-pushed the php-array branch 4 times, most recently from dc1e644 to 730f41f Compare October 18, 2025 16:44
@nicolas-grekas
Copy link
Member Author
nicolas-grekas commented Oct 18, 2025

PR ready.
This took me quite some time to do manually, but with some LLM help, I shouldn't have made much mistakes.

@nicolas-grekas nicolas-grekas force-pushed the php-array branch 2 times, most recently from 097460b to 776698b Compare October 19, 2025 16:46
@javiereguiluz
Copy link
Member

Thanks for this! We should merge this soon to aovid merge conflicts with other PRs.

However, GitHub shows errors on these 5 files, so we should fix those:

  • logging/channels_handlers.rst
  • logging/monolog_console.rst
  • service_container/import.rst
  • configuration.rst
  • http_client.rst

@nicolas-grekas
Copy link
Member Author

PR updated after symfony/symfony#62129

nicolas-grekas added a commit to symfony/symfony that referenced this pull request Oct 23, 2025
… to assist in writing and discovering app's configuration (nicolas-grekas)

This PR was squashed before being merged into the 7.4 branch.

Discussion
----------

[FrameworkBundle] Auto-generate `config/reference.php` to assist in writing and discovering app's configuration

| Q             | A
| ------------- | ---
| Branch?       | 7.4
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Doc PR | symfony/symfony-docs#21511
| License       | MIT

This PR reverts #61490 and #61885, and builds on #61894.
These reverts explain a big chunk of the attached patch.

This adds a compiler pass that generates a `config/reference.php` file.
This file contains two classes that define array-shapes for app's and routing configuration.
Part of these shapes are auto-generated from the list of bundles found in `config/bundles.php`.

The `config/reference.php` file should be loaded by a new line in the "autoload" entry of composer.json files: `"classmap": ["config/"]` - recipe update pending. This means that the file should be committed. This is on purpose: as the name suggests, this file is also a config reference for human readers. Having to commit the changes is also a nice way to convey config improvements to the community - at least for ppl that review their commits ;). It also solves a discovery problem that happens with phpstan/etc having a hard time to find the classes currently generated for config builders in the cache directory.

With this PR, `config/services.php` could start as such:

```php
<?php

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

return App::config([
    'services' => [
        'App\\' => [
            'resource' => '../src/'
        ],
    ],
]);
```

and `config/routes.php` would start as:

```php
<?php

namespace Symfony\Component\Routing\Loader\Configurator;

return Routes::config([
    'controllers' => [
        'resource' => 'attributes',
        'type' => 'tagged_services',
    ]
]);
```

The generated shapes use advanced features that are not fully supported by phpstan / phpstorm. But the gap should be closed soon.

PS: https://symfony.com/blog/new-in-symfony-7-4-deprecated-xml-configuration will need an update.

Commits
-------

22349f5 [FrameworkBundle] Auto-generate `config/reference.php` to assist in writing and discovering app's configuration
@nicolas-grekas nicolas-grekas force-pushed the 8000 php-array branch 2 times, most recently from 2ae8fe4 to a042e8c Compare October 23, 2025 18:07
@nicolas-grekas
Copy link
Member Author
nicolas-grekas commented Oct 23, 2025

I replaced examples that used config/package/env/ pattern to when@env. This topic would deserves closer attention after merging. I think we can stop telling so much bout the subdir pattern.

twig:
strict_variables: true
# config/packages/twig.yaml
when@test:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice update 👍🏻
Consistent with the Twig recipe.

return App::config([
'services' => [
// ...
'Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler' => [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a use statement for this class:

Suggested change
'Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler' => [
RedisSessionHandler::class => [

// ['prefix' => 'my_prefix', 'ttl' => 600],
],
],
'Redis' => [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'Redis' => [
\Redis::class => [

'services' => [
'_defaults' => [
'autowire' => true, // Automatically injects dependencies in your services.
'autoconfigure' => true, // Automatically registers your services as commands, event subscribers, etc.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the default values for App::config(), you may comment them here?

return static function (ContainerConfigurator $container): void {
$container->extension('acme_something', [
// ...
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either we keep these ellipses in all formats, or we remove them. Let's be consistent.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's remove them from this example, that better matches the prepend example before this configuration block.

$twig->debug('%kernel.debug%');
};
return App::config([
'twig' => $1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parameter missing here.
You could use the param function.

Suggested change
'twig' => $1,
'twig' => param('kernel.debug'),

Comment on lines +208 to +210
return App::config([
KernelEvents::EXCEPTION => 'onKernelException',
];
]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a config file.

Suggested change
return App::config([
KernelEvents::EXCEPTION => 'onKernelException',
];
]);
return [
KernelEvents::EXCEPTION => 'onKernelException',
];

$twig->defaultPath('%kernel.project_dir%/resources/views');
};
return App::config([
'twig' => $1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'twig' => $1,
'twig' => '%kernel.project_dir%/resources/views',

;
};
return App::config([
'doctrine' => $1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'doctrine' => $1,
'doctrine' => env('DATABASE_PASSWORD'),

Comment on lines +210 to +216
return App::config([
'content' => 'This is my custom problem normalizer.',
'exception'=> [
'message' => $exception->getMessage(),
'code' => $exception->getStatusCode(),
],
];
]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a config file.

Suggested change
return App::config([
'content' => 'This is my custom problem normalizer.',
'exception'=> [
'message' => $exception->getMessage(),
'code' => $exception->getStatusCode(),
],
];
]);
return [
'content' => 'This is my custom problem normalizer.',
'exception'=> [
'message' => $exception->getMes 67DE sage(),
'code' => $exception->getStatusCode(),
],
];

};
return App::config([
'doctrine' => [
'orm' => [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation

Suggested change
'orm' => [
'orm' => [

Copy link
Member
@GromNaN GromNaN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I stopped at "security/".

'services' => [
AutoCommitListener::class => [
'tags' => [
['doctrine.event_listener' => ['event' => Events::onMigrationsMigrated]],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we copy the Yaml format, it should be like this: what is correct?

Suggested change
['doctrine.event_listener' => ['event' => Events::onMigrationsMigrated]],
[
'name' => 'doctrine.event_listener',
'event' => Events::onMigrationsMigrated
],

# config/packages/doctrine.yaml
doctrine:
dbal:
url: '%env(DATABASE_URL)%'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be consistent with the PHP example:

Suggested change
url: '%env(DATABASE_URL)%'
url: '%env(resolve:DATABASE_URL)%'

'assets' => [
'packages' => [
'avatars' => [
'base_urls' => ['http://static_cdn.example.com/avatars'],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'base_urls' => ['http://static_cdn.example.com/avatars'],
'base_urls' => ['https://static_cdn.example.com/avatars'],

assets:
packages:
avatars:
base_urls: 'http://static_cdn.example.com/avatars'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's apply security best practices.

Suggested change
base_urls: 'https://static_cdn.example.com/avatars'

'cache' => [
'pools' => [
'cache.mycache' => [
'adapter' => 'cache.adapter.redis',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a service id, but we could update the config to accept a Reference: symfony/symfony#62142

Comment on lines +1233 to +1235
'headers' => [
'X-Powered-By' => 'ACME App',
],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the Yaml example, this is inlined.

Suggested change
'headers' => [
'X-Powered-By' => 'ACME App',
],
'headers' => ['X-Powered-By' => 'ACME App'],

Just to highlight the difference, you can discard the suggestion.

'services' => [
AvatarPackage::class => [
'tags' => [
['assets.package' => ['package' => 'avatars']],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both syntaxes work. which one should be documented?

Suggested change
['assets.package' => ['package' => 'avatars']],
['name' => 'assets.package', 'package' => 'avatars'],

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

0