The Easiest way to use Coding Standard
September 9, 2026 · View on GitHub
Easy Coding Standard (ECS) is a single tool that runs PHP_CodeSniffer and PHP-CS-Fixer rules together, configured through one simple PHP file.
Note
This is the deployed package. Development happens in the ecs-src repository - report issues and send pull requests there.
Killer Features
- Install on any PHP 7.2-PHP 8.5 project with any dependencies
- Blazing fast with parallel run out of the box
- Use PHP_CodeSniffer or PHP-CS-Fixer - anything you like
- Use prepared sets and PHP CS Fixer sets to save time
Install
composer require symplify/easy-coding-standard --dev
Usage
vendor/bin/ecs
On the first run, ECS creates ecs.php config file with directories and first rule to kick off.
Then you can run again to see the suggested diffs:
vendor/bin/ecs
Want to check specific paths instead of the configured ones? Pass them as arguments:
vendor/bin/ecs src tests
To actually fix your code, add --fix:
vendor/bin/ecs --fix
That's it!
Configure
Most of the time, you'll be happy with the default configuration. The most relevant part is configuring paths, checkers and sets:
use PhpCsFixer\Fixer\ArrayNotation\ArraySyntaxFixer;
use PhpCsFixer\Fixer\ListNotation\ListSyntaxFixer;
use Symplify\EasyCodingStandard\Config\ECSConfig;
return ECSConfig::configure()
->withPaths([__DIR__ . '/src', __DIR__ . '/tests'])
// start slow with sole rules
->withRules([
ListSyntaxFixer::class,
])
->withConfiguredRule(
ArraySyntaxFixer::class,
['syntax' => 'long']
)
// apply full set
->withPreparedSets(psr12: true);
Do you want to check all *.php files in your root (ecs.php, rector.php etc.)? Instead of listing them one by one, use ->withRootFiles() method:
use Symplify\EasyCodingStandard\Config\ECSConfig;
return ECSConfig::configure()
->withPaths([__DIR__ . '/src', __DIR__ . '/tests'])
->withRootFiles();
Prepared Sets
->withPreparedSets() bundles curated rule sets. Enable the whole common set, or pick single topics:
use Symplify\EasyCodingStandard\Config\ECSConfig;
return ECSConfig::configure()
->withPaths([__DIR__ . '/src', __DIR__ . '/tests'])
->withPreparedSets(
arrays: true,
spaces: true,
namespaces: true,
docblocks: true,
controlStructures: true,
comments: true,
casing: true,
cleanup: true,
);
| Set | What it covers |
|---|---|
arrays | array syntax, spacing, trailing commas, indentation |
spaces | whitespace, operator/type spacing, blank lines |
namespaces | imports ordering, unused/needless-alias imports |
docblocks | phpdoc tags, types, alignment, cleanup |
controlStructures | control flow, casing, operators, class structure |
comments | comment style, spacing, empty-comment cleanup |
casing | native function/type, magic method, literal casing |
cleanup | dead statements, useless returns/casts, unused closure imports |
Or enable everything at once with ->withPreparedSets(common: true).
Standalone presets are also available: psr12: true, perCs: true, and laravel: true (the Laravel Pint ruleset):
use Symplify\EasyCodingStandard\Config\ECSConfig;
return ECSConfig::configure()
->withPaths([__DIR__ . '/src', __DIR__ . '/tests'])
->withPreparedSets(laravel: true);
Gradual Adoption with Levels
Want to adopt a coding standard step by step instead of all at once? Use with*Level() methods to start from the safest rules and raise the level as your codebase catches up:
use Symplify\EasyCodingStandard\Config\ECSConfig;
return ECSConfig::configure()
->withPaths([__DIR__ . '/src', __DIR__ . '/tests'])
->withSpacesLevel(0)
->withArrayLevel(0)
->withControlStructuresLevel(0)
->withDocblockLevel(0);
Each level enables the first N+1 rules from a curated list, ordered from safest to most invasive. Bump the number once your codebase is clean on the current level.
How to Skip Files/Rules?
Love the sets of rules, but want to skip single rule or some files?
use Symplify\EasyCodingStandard\Config\ECSConfig;
return ECSConfig::configure()
->withSkip([
// skip single rule
ArraySyntaxFixer::class,
// skip single rule in specific paths
ArraySyntaxFixer::class => [
__DIR__ . '/src/ValueObject/',
],
// skip directory by absolute or * mask
__DIR__ . '/src/Migrations',
// skip directories by mask
__DIR__ . '/src/*/Legacy',
]);
Less Common Options
You probably won't use these, but they can give you more control over the internal process:
use Symplify\EasyCodingStandard\Config\ECSConfig;
use Symplify\EasyCodingStandard\ValueObject\Option;
return ECSConfig::configure()
// file extensions to scan
->withFileExtensions(['php'])
// configure cache paths and namespace - useful e.g. Gitlab CI caching, where getcwd() produces always different path
->withCache(
directory: sys_get_temp_dir() . '/_changed_files_detector_tests',
namespace: getcwd() // normalized to directory separator
)
// print contents with specific indent rules
->withSpacing(indentation: Option::INDENTATION_SPACES, lineEnding: PHP_EOL)
// modify parallel run
->withParallel(timeoutSeconds: 120, maxNumberOfProcess: 32, jobSize: 20);
Mentioned values are default ones.
Controlling Output Format
You may want to use ECS to generate reports for third-party tooling.
We currently provide formatters for:
console: Human-oriented printing à la PHP CS Fixer.json: A custom JSON blob for arbitrary tooling.
You can use the output format option as below
vendor/bin/ecs --output-format=json
FAQ
How do I clear cache?
vendor/bin/ecs --clear-cache
How can I see all used rules?
vendor/bin/ecs list-checkers
Do you look for json format?
vendor/bin/ecs list-checkers --output-format json
How to Migrate from another coding standard tool?
Do you use another tool and want to migrate? It's pretty straightforward - here is "how to":
- for PHP_CodeSniffer
- and PHP CS Fixer.