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\Option;
use Symplify\EasyCodingStandard\ValueObject\Set\SetList;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::SETS, [
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?
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 static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(DeclareStrictTypesFixer::class);
};
No more typos with strong over string typing.
notPath()
to skip
ParameterIf 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 static 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 static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::SKIP, [
DeclareStrictTypesFixer::class => null,
]);
};
For all other skip
options, see README.
.php_cs
to PHP ConfigPHP 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
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:
<?php
// ecs.php
declare(strict_types=1);
use PhpCsFixer\Fixer\ArrayNotation\ArraySyntaxFixer;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(ArraySyntaxFixer::class)
->call('configure', [[
'syntax' => 'short'
]]);
};
Nice and clear!
--dry-run
to --fix
optionFrom PHP CS Fixer:
vendor/bin/php-cs-fixer fix /path/to/project --dry-run
vendor/bin/php-cs-fixer fix /path/to/project
to EasyCodingStandard equivalent:
vendor/bin/ecs check /path/to/project
vendor/bin/ecs check /path/to/project --fix
@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\Option;
use Symplify\EasyCodingStandard\ValueObject\Set\SetList;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::SETS, [
SetList::PSR_12,
]);
};
...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!