You've probably noticed Symfony is moving towards PHP configuration. If you're on XML or YAML, you'll most likely migrate to PHP with upcoming Symfony 6.
There are already tools that can help you migrate today - so it's not a matter of work, but a matter of choice.
Today we look at 10 cool features you get by switching to PHP configs that make you an even lazier programmer.
Do you care why this begun? Be sure to read Symfony issue:
The biggest advantage is IDE auto-completion out of the box,
and one XML/YAML language less to learn.
There are the cool features I've observed from migration of 50+ YAML configs to PHP:
In configs, we often define paths to files or directories. Could you tell me what exact path this is?
parameters:
paths:
- 'src'
%kernel.projectDir%
?%cwd%
?We don't know. It depends on the internal tool implementation and luck.
Now the same config in PHP:
Pretty clear, right?
The YAML config will not show you, if class was deprecated:
PHPStorm will cross the deprecated class and prepare you better for the future:
In YAML, everything is a string by default, so YAML doesn't know that you mean a class.
PHPStorm shows that pretty clearly:
Do you recall YAML struggle, when you want to register a service?
In PHP config you can forget it and just type:
Even with typos like "Application" ;)
calls
Syntax?Do you remember how to set a call on the service setup?
services:
SomeClass:
calls:
# what now?
No, don't Google it! Try from the top of your head.
An intuitive way would be to use the same syntax as properties/arguments:
services:
SomeClass:
calls:
'setValue': [1]
No :( then we have to Google it...
In PHP we can use intuitive approach and see what IDE tells us:
In YAML everything is a string:
parameters:
line_ending: PHP_EOL
Is that PHP_EOL
constant as we know it? No, it's "PHP_EOL"
string.
How can we specify a string that is a constant? (Feels weird for my brain just writing this sentence.)
Symfony 3.2 introduced special prefix: !php/const
parameters:
line_ending: !php/const PHP_EOL
Pretty crazy, right?
How does PHP solve this?
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set('line_ending', PHP_EOL);
};
It just works, no headache!
These 2 files will produce the same configuration:
services:
SomeService:
# silent "arguments" key is omitted
$key: value
services:
SomeService:
arguments:
$key: value
# or was it this?
# key: value
In PHP this is just 1 clear way:
use Symfony\Component\Console\Application;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(Application::class)
->arg('key', 'value');
};
For tags, these 2 files produce the same output:
services:
SomeService:
tags:
- kernel.event_subscriber
# how do we extend this later?
services:
SomeService:
tags:
- { name: 'kernel.event_subscriber' }
In PHP, there is just 1 way for both:
This feature is my favorite by far because it finally opens the door for next-level automation.
YAML doesn't have any static analyzer or instant upgrade tool. This makes the upgrade of Symfony projects double the work - in PHP, in YAML.
Since *.php
is PHP code, all the powerful CI tools have access to it.
Fewer bugs, effortless changes, less upgrade work, new PHPStan rules, more fun coding.
Last but not least. You've probably noticed I hate typos. I'm so used to tool watching my back, that I type much faster than my fingers can. Then I run the tools and code works (usually).
If you give me a choice of "string"
or CONSTANT
, 10 of 10 I pick the CONSTANT
(unless the string is "really sexy and smart, verified"
).
We don't have such a solid choice in YAML. If we want to use a parameter used elsewhere, we need to trust name is somehow validated (it isn't, because exception will tell you anyway).
For example, how do you ignore files in ECS?
parameters:
excluded_files:
# or
excluded_path:
# or
excluded_paths:
None of them :(. It's exclude_files
! It's painful to look for such bugs because you need to analyze the whole project every time the config is changed.
In PHP, we can do this:
Do you need more real-life examples to try it yourself? Learn from merged pull-requests:
bolt/core
migration of ecs.yaml
to ecs.php
symlify/easy-coding-standard
of 20 sets
And of course, don't do it manually. Use automated tool - symplify/config-transformer
- handles YAML/XML to PHP/YAML.
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!