I just saw the post about the new PHP configuration format and it felt like going back in time.
The PHP configuration evolution.
Before Symfony 5.3
return static function (ContainerConfigurator $container) {
$array = [
'firewalls' => [
'main' => [
'pattern' => '^/*',
'lazy' => true,
'anonymous' => [],
],
],
'access_control' => [
['path' => '^/admin', 'roles' => 'ROLE_ADMIN'],
],
];
$container->extension('security', $array);
}
From Symfony 5.3 until the removal
return static function (SecurityConfig $security) {
$security->firewall('main')
->pattern('^/*')
->lazy(true)
->anonymous();
$security
->accessControl(['path' => '^/admin', 'roles' => 'ROLE_ADMIN']);
};
The new format.
return App::config([
'security' => [
// ...
'firewalls' => [
'main' => [
'pattern' => '^/*',
'lazy' => true,
'anonymous' => true,
],
],
'access_control' => [
['path' => '^/admin', 'roles' => 'ROLE_ADMIN'],
],
]
]);
The research and thoughts
Based purely on syntax you can't deny it is very close to the Symfony 5.2 code.
The reason they give in the blog post to make the move is that generics are supported by enough tools to make it a viable solution.
I'm not a big fan of using tools to help you to write the correct code, if it is possible to write correct code without the need of tools.
I don't care if the config builder goes away. The fluent API pattern is a convenient way to write code, but it makes it easy to cause side effects while manipulating the object with the methods.
I have read the PR for more background information. And I agree that creating a configuration tree is very difficult and a more relaxed format removes edge cases.
My solution
While I didn't put that much thought into as the Symfony people, I'm thinking about PDO(like) objects.
The config example my way.
return [
new Config\Security\Firewall('main')
->properties(pattern: '^/*', lazy: true, anonymus: true),
new Config\Security\AccessControl(path: '^/admin', roles: 'ROLE_ADMIN'),
]
The idea is to just return a flat array with specific Config types.
The constructor can accept global value(s).
If the settings are too much to add them all to the constructor use one or more methods to give them more context.
To avoid edge cases the constructor and/or methods could have a spread operator argument to accept configuration settings that are more niche.
This way builds on the strengths of the current PHP version:
- type hinted arguments
- named arguments
- the spread operator
I also read one of the reasons of the change is to make it easier to go from YAML to PHP. And that is something that will be harder to do with my solution.
All in all, I think the new format is the best compromise to go forward. But it doesn't mean I don't see room for improvement.
Top comments (4)
I like the "new" (array-based) config syntax - looks clean, simple and readable ... the "builder" pattern thing looks more complex, and harder to learn.
But, I'm probably biased ;-) because the new (array-based) config syntax looks very similar to Laravel's config syntax :-)
You made me realize, it is not the builder pattern but the fluent API pattern. So I had to change that in the post before I reacted.
But Laravel is full of fluent API pattern classes, so it is not that complex. It is the reason some people prefer Laravel.
Interesting perspective. Disagree on avoiding tools: generics + IDE/static analysis are mainstream and provide safety without custom config classes. The array format mirrors YAML, easing DX. Would a PDO-like layer add boilerplate and fragment third‑party bundle configs? Any concrete builder side effects seen?
It was a broader comment on the use of the builder pattern. I haven't noticed side effects when using the PHP config builder.
The idea is to have a base class or an attribute that identifies a class as a specific config type.
It is not far off from the generated builder config classes in that regard.
The builder classes create a multi branch portion of the tree, while I see my config classes as single branches. This gives more room for manipulation when the tree is generated.
I don't know what the effect is on third-party configs. I didn't think that far.