How to Migrate From PHP_CodeSniffer to EasyCodingStandard in 7 Steps

Last year, I helped Shopsys Coding Standards and LMC PHP Coding Standard to migrate from PHP_CodeSniffer to EasyCodingStandard.

There are a few simple A → B changes, but one has to know about them or will get stuck.

Do you also use PHP_CodeSniffer and give it EasyCodingStandard a try? Today we look at how to migrate step by step.

ECS is a tool build on Symfony 3.4 components that combines PHP_CodeSniffer and PHP CS Fixer. It's super easy to start to use from scratch:

composer require symplify/easy-coding-standard --dev
vendor/bin/ecs check src --level psr12 # yes 12!

But what if you already have PHP_CodeSniffer on your project and want to switch?

1. From String Codes to Autocompleted Classes

You probably use string references to sniffs in your *.xml configuration for PHP_CodeSniffer. You need to remember them, copy paste them and copy-paste them right.

<!-- phpcs.xml -->
<rule ref="Generic.Comenting.DocComment"/>

That can actually cause typos like:

-<rule ref="Generic.Comenting.DocComment"/>
+<rule ref="Generic.Commenting.DocComment"/>

How to do that in EasyCodingStandard? Copy paste the last name DocComment, add "Sniff" and ::

# ecs.yml
services:
    DocCommentSniff<cursor-here>:

Then hit the "ctrl" + "space" for class autocomplete in PHPStorm.

services:
    PHP_CodeSniffer\Standards\Generic\Sniffs\Commenting\DocCommentSniff: ~

That way Symfony plugin will autocomplete the class for you:

No more typos with strong over string typing.

2. From @codingStandardsIgnoreStart to skip Parameter

If you'd like to skip nasty code from being analyzed, you'd use @codingStandardsIgnoreStart in PHP_CodeSniffer.

#  packages/framework/src/Component/Constraints/EmailValidator.php

private function isEmail($value)
{
    // @codingStandardsIgnoreStart
    $atom = "[-a-z0-9!#$%&'*+/=?^_`{|}~]"; // RFC 5322 unquoted characters in local-part
    // @codingStandardsIgnoreEnd
}

One big cons of this is that all sniffs will skip this code, not just one. So even if here we need to only allow double quotes ", all other checks will miss it.

To skip this in EasyCodingStandard just use skip parameter:

parameters:
    skip:
        PHP_CodeSniffer\Standards\Squiz\Sniffs\Strings\DoubleQuoteUsageSniff:
            - 'packages/framework/src/Component/Constraints/EmailValidator.php'

Do you have more such cases?

parameters:
    skip:
        PHP_CodeSniffer\Standards\Squiz\Sniffs\Strings\DoubleQuoteUsageSniff:
            - 'packages/framework/src/Component/Constraints/EmailValidator.php'
            - 'packages/framework/src/Component/Constraints/NameValidator.php'
            - 'packages/framework/src/Component/Constraints/SurnameValidator.php'

You don't have to list them all like a typing monkey. Just use fnmatch() format instead:

parameters:
    skip:
        PHP_CodeSniffer\Standards\Squiz\Sniffs\Strings\DoubleQuoteUsageSniff:
            - '*packages/framework/src/Component/Constraints/*Validator.php'

3. From <severity>0</severity> and <exclude name="..."> to skip Parameter

Do you need to skip only 1 part of the sniff? In PHP_CodeSniffer:

<rule ref="Generic.Commenting.DocComment.ContentAfterOpen">
    <severity>0</severity>
</rule>

or

<rule ref="Generic.Commenting.DocComment">
    <exclude name="Generic.Commenting.DocComment.ContentAfterOpen"/>
</rule>

In EasyCodingStandard, we put that again under skip parameter in format <Sniff>.<CodeName>:

parameters:
    skip:
        PHP_CodeSniffer\Standards\Generic\Sniffs\Commenting\DocCommentSniff.ContentAfterOpen: ~

For all other skip options, see README.


In case you need to skip the whole sniff:

<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="ruleset">
    <rule ref="Generic.Commenting.DocComment">
        <severity>0</severity>
    </rule>
</ruleset>

or

<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="ruleset">
    <rule ref="ruleset.xml">
        <exclude name="Generic.Commenting.DocComment"/>
    </rule>
</ruleset>

Put it under exclude_checkers:

parameters:
    exclude_checkers:
        PHP_CodeSniffer\Standards\Generic\Sniffs\Commenting\DocCommentSniff: ~

4. From XML to YML Config Paths

These names are looked for in the root diretory by PHP_CodeSniffer:

- .phpcs.xml
- phpcs.xml
- .phpcs.xml.dist
- phpcs.xml.dist

And these by EasyCodingStandard:

- ecs.yml
- ecs.yaml
- easy-coding-standard.yml
- easy-coding-standard.yaml

What about non-default locations or names?

From:

vendor/bin/phpcs /path/to/project --standard=custom/location.xml

to:

vendor/bin/ecs check /path/to/project --config custom/location.yml

5. Configuring Sniff Values

From XML configuration in PHP_CodeSniffer:

<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="ruleset">
    <rule ref="Generic.Metrics.CyclomaticComplexity">
        <properties>
            <property name="complexity" value="13"/>
            <property name="absoluteComplexity" value="13"/>
        </properties>
    </rule>
</ruleset>

to YML parameters in EasyCodingStandard:

services:
    PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\CyclomaticComplexitySniff:
        complexity: 13
        absoluteComplexity: 13

6. From Severity and Warning to Just Errors

There are different levels in PHP_CodeSniffer. You can set severity, make sniff report as warning or as an error.

<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="ruleset">
    <rule ref="Generic.Commenting.DocComment">
        <severity>5</severity>
    </rule>
</ruleset>

This complex matrix leveling lead to confused questions for many people:

And so on.

Thus these confusing options are not supported and EasyCodingStandard simplifies that to errors only CI server either passes or not. The rule is required and respected or removed. Simple, clear and without any confusion.

Saying that you don't need to fill values for warning properties:

 services:
     PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\CyclomaticComplexitySniff:
-        complexity: 13
         absoluteComplexity: 13

7. From Beautifier to --fix option

Do you need to fix the code? From 2 commands in PHP_CodeSniffer:

vendor/bin/phpcs /path/to/project --standard=custom/location.xml
vendor/bin/phpcbf /path/to/project --standard=custom/location.xml

to 1 in EasyCodingStandard:

vendor/bin/ecs check /path/to/project --config custom/location.yml
vendor/bin/ecs check /path/to/project --config custom/location.yml --fix


Give it a Try...

...and you won't regret it. Sylius, LMC, Shopsys, Nette and SunFox 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.



In the next post we look on how to migrate from PHP CS Fixer!


  Continue Learning


Typo? Fix it, please  and join 47 people who build this website

GitHub RSS @votrubaT Runs on Statie Hosted on GitHub Build by 48 people

Like what I write about? Hire me & we can work together