How to Migrate From PHP CS Fixer to ECS in 6 Steps
What is new?
Switched deprecated --set
option to ecs.php
config.
Switched YAML to PHP configuration.
We looked at how to migrate from PHP_CodeSniffer to Easy Coding Standard on Monday. But what if your weapon of choice is PHP CS Fixer and you'd to run also some sniffs?
There are a few simple A → B changes, but one has to know about them or will get stuck. Let's learn about them.
ECS is a tool build on Symfony components that combines PHP_CodeSniffer and PHP CS Fixer. It's easy to use from scratch:
composer require symplify/easy-coding-standard --dev
ECS uses standard Symfony PHP config:
// ecs.php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symplify\EasyCodingStandard\ValueObject\Set\SetList;
return function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->import(SetList::PSR_12);
};
And runs as CLI command:
vendor/bin/ecs check src
But what if you already have PHP CS Fixer on your project and want to switch?
1. From String Codes to Autocompleted Classes
You use string references like strict_types
in your .php_cs
file. You need to remember them, copy paste them from README and copy-paste them right.
return PhpCsFixer\Config::create()
->setRules([
'strict_types' => true,
])
->setFinder($finder);
That can actually cause typos like:
return PhpCsFixer\Config::create()
->setRules([
- 'strict_types' => true,
+ 'declare_strict_types' => true,
])
->setFinder($finder);
How to do that in ECS? Copy paste the fixer name, capitalize first letter and remove _
:
Then hit the "ctrl" + "space" for class autocomplete in PHPStorm (it works even now when I write this post in markdown, nice!).
// ecs.php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use PhpCsFixer\Fixer\Strict\DeclareStrictTypesFixer;
return function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(DeclareStrictTypesFixer::class);
};
No more typos with strong over string typing.
2. From notPath()
to skip
Parameter
If you'd like to skip nasty code from being analyzed, you'd probably use this in PHP CS Fixer.
$finder = PhpCsFixer\Finder::create()
->exclude('somedir')
->notPath('my-nasty-dirty-file.php')
->in(__DIR__);
Do you need DeclareStrictTypesFixer
to skip this file? Sorry, PHP CS Fixer will skip it for ever rule.
ECS solves this common case - to skip a file, just use skip
parameter:
// ecs.php
use PhpCsFixer\Fixer\Strict\DeclareStrictTypesFixer;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symplify\EasyCodingStandard\ValueObject\Option;
return function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::SKIP, [
DeclareStrictTypesFixer::class => [
__DIR__ . '/my-nasty-dirty-file.php',
// you can add more files
__DIR__ . '/Legacy/too-legacy-to-look-at.php',
// or directories
__DIR__ . '/Legacy',
// or mask paths with fnmatch()
__DIR__ . '/*/Command',
]
]);
};
Do you really want to skip 1 fixer for all files?
// ecs.php
use PhpCsFixer\Fixer\Strict\DeclareStrictTypesFixer;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symplify\EasyCodingStandard\ValueObject\Option;
return function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::SKIP, [
DeclareStrictTypesFixer::class => null,
]);
};
For all other skip
options, see README.
3. From .php_cs
to PHP Config
PHP CS Fixer looks for .php_cs
file in the root directory by default.
And ECS looks for ecs.php
What about non-default locations or names?
From:
vendor/bin/php-cs-fixer fix /path/to/project --config=custom/location.yml --dry-run
to:
vendor/bin/ecs check /path/to/project --config custom/location.php
4. Configuring Fixer Values
From PHP configuration in PHP CS Fixer:
return PhpCsFixer\Config::create()
->setRules([
'array_syntax' => ['syntax' => 'short'],
])
->setFinder($finder);
to explicit Symfony service parameters in EasyCodingStandard:
use PhpCsFixer\Fixer\ArrayNotation\ArraySyntaxFixer;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(ArraySyntaxFixer::class)
->call('configure', [[
'syntax' => 'short'
]]);
};
Nice and clear!
5. From no --dry-run
to --fix
option
From PHP CS Fixer:
vendor/bin/php-cs-fixer fix /path/to/project --dry-run
vendor/bin/php-cs-fixer fix /path/to/project
to ECS equivalent:
vendor/bin/ecs check /path/to/project
vendor/bin/ecs check /path/to/project --fix
6. From @Rules
to imports
Do you like to use standards like PSR-2 or even PSR-12?
From @strings
in PHP CS Fixer:
$config = PhpCsFixer\Config::create()
->setRules([
'@PSR2' => true,
]);
to autocompleted set constant in PHP file in ECS:
// ecs.php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symplify\EasyCodingStandard\ValueObject\Set\SetList;
return function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->import(SetList::PSR_12);
};
Give it a Try...
...and you won't regret it. Sylius, PestPHP, LMC, Shopsys and Nette did and never came back.
Did I forget a step that you had to fight with? Please, let me know in the comments or just send PR to this post to add it, so we help other readers.
Happy coding!
Have you find this post useful? Do you want more?
Follow me on Twitter, RSS or support me on GitHub Sponsors.