Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Coding Standard Laravel Package

symplify/coding-standard

Symplify Coding Standard provides 23 fixer rules for clean, consistent PHP code, covering array formatting, line length, and strict types. It works best with Easy Coding Standard but is deprecated in favor of using ECS directly.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a bundle of ECS (Easy Coding Standard) fixers — it does not run on its own. The only realistic setup is alongside symplify/easy-coding-standard.

composer require --dev symplify/coding-standard symplify/easy-coding-standard

Minimal ecs.php at the project root:

<?php

declare(strict_types=1);

use Symplify\EasyCodingStandard\Config\ECSConfig;

return ECSConfig::configure()
    ->withPaths([__DIR__ . '/src', __DIR__ . '/app', __DIR__ . '/tests'])
    ->withPreparedSets(symplify: true);

Then the two commands you will live in:

vendor/bin/ecs          # dry-run: lists every diff, exits non-zero if anything would change
vendor/bin/ecs --fix    # rewrites files

Where to look first: the rule list in the README is the de-facto documentation — each entry shows the class name and a before/after diff. Skim it once and note the handful you actually want; the class names are what you need later for withSkip() and withConfiguredRule().

First use case — safe legacy cleanup. Don't enable symplify: true on a large existing codebase on day one. Start with the annotation/docblock rules only, on a directory you own, and commit the diff as a single mechanical "chore: normalize docblocks" commit. These rules are the lowest-risk entry point because they only touch comments:

return ECSConfig::configure()
    ->withPaths([__DIR__ . '/app'])
    ->withRules([
        \Symplify\CodingStandard\Fixer\Commenting\AddMissingParamNameFixer::class,
        \Symplify\CodingStandard\Fixer\Commenting\FixParamNameTypoFixer::class,
        \Symplify\CodingStandard\Fixer\Commenting\RemoveDeadParamFixer::class,
        \Symplify\CodingStandard\Fixer\Commenting\SwitchedTypeAndNameFixer::class,
        \Symplify\CodingStandard\Fixer\Annotation\RemovePHPStormAnnotationFixer::class,
        \Symplify\CodingStandard\Fixer\Commenting\RemoveUselessDefaultCommentFixer::class,
    ]);

RemoveUselessDefaultCommentFixer alone tends to delete hundreds of lines of // TODO: Implement whatever() method. and Class representing X noise in codebases that were scaffolded by generators.

Implementation Patterns

Composer scripts as the daily interface. Hide the vendor path so nobody has to remember flags:

{
    "scripts": {
        "cs": "ecs",
        "cs:fix": "ecs --fix",
        "cs:check": "ecs --no-progress-bar"
    }
}

Developers run composer cs:fix before committing; CI runs composer cs:check (no --fix) and lets the non-zero exit fail the build. Never let CI auto-fix — a bot commit of formatting changes destroys git blame and creates merge conflicts across every open branch.

CI job. Keep it a separate, fast job that runs in parallel with tests:

- run: composer install --no-interaction --prefer-dist
- run: vendor/bin/ecs --no-progress-bar

Because ECS is cache-backed, persist the cache directory between runs (~/.cache/ecs or wherever withCache() points) — otherwise full-project analysis on every push gets slow.

Scoped rule sets per directory. withPaths() can be called more than once and combined with withSkip(), which is how you adopt the standard incrementally:

return ECSConfig::configure()
    ->withPaths([__DIR__ . '/app', __DIR__ . '/src'])
    ->withPreparedSets(symplify: true)
    ->withSkip([
        // legacy folder: only docblock rules for now
        \Symplify\CodingStandard\Fixer\ArrayNotation\ArrayListItemNewlineFixer::class => [
            __DIR__ . '/app/Legacy',
        ],
        \Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer::class => [
            __DIR__ . '/app/Legacy',
            __DIR__ . '/src/Generated',
        ],
        // generated / vendored code fully opted out
        __DIR__ . '/src/Generated',
    ]);

Shrink the skip list one directory per sprint; the skip list doubles as a TODO tracker.

Pair the docblock rules with static analysis. These fixers are only worth it if @param/@var tags actually mean something to you. In a Laravel project running PHPStan at level 5+, AddMissingParamNameFixer + SwitchedTypeAndNameFixer + FixParamNameTypoFixer eliminate the "PHPStan reports a parameter name that doesn't exist" class of false positives in bulk. Run ecs --fix first, then PHPStan, and the diff stays comment-only.

Git hook integration. Symplify's own captainhook works well here: run ecs --fix on staged files and re-stage them. Simpler still, run ecs (dry) in a pre-push hook, since it's whole-project and cheap when cached.

Reviewing the output. Rule fixers are mostly independent, so treat the first big --fix run as N separate mechanical changes. git add -p and commit per rule family (arrays, docblocks, annotations, spacing). That way if one rule turns out to be wrong for your team, git revert is a one-liner rather than a surgical unpick.

The spacing rules that matter with dependency injection. StandaloneLineConstructorParamFixer and StandaloneLinePromotedPropertyFixer force one constructor parameter per line. This is the single most valuable rule in the set for services with many injected dependencies — it makes every new dependency a one-line diff instead of a reflowed signature, which is exactly what you want in code review.

Gotchas and Tips

This package is deprecated and archived. The README itself says to use ECS, which already bundles the set. Practical consequence: pin the version you install ("symplify/coding-standard": "^13.0") and expect no fixes for new PHP syntax. The fixers are token-based; if you're on PHP 8.4+ with property hooks, asymmetric visibility, or other recent syntax additions, a fixer may mis-parse rather than no-op. Vendor-forking is the escape hatch if that happens — the classes are small and self-contained.

The array rules conflict with Pint / PSR-12 / Laravel conventions. ArrayListItemNewlineFixer and ArrayOpenerAndCloserNewlineFixer will rewrite ['simple' => 1, 'easy' => 2] into a multi-line array, which fights the dominant PHP style and will cause churn every time someone runs Pint afterwards. If your project uses Pint or PHP-CS-Fixer, either drop these three (ArrayListItemNewlineFixer, ArrayOpenerAndCloserNewlineFixer, StandaloneLineInMultilineArrayFixer) via withSkip(), or make ECS the sole formatter and remove Pint. Do not run both in CI — you get a permanently failing check whichever one runs second.

MethodChainingNewlineFixer is opinionated. It breaks every chain onto its own line, including two-call ->where()->get() chains. On Eloquent-heavy code this is extremely noisy. Skip it unless your house style already breaks chains.

LineLengthFixer is the only rule that genuinely needs configuration — and without config it will aggressively inline short multi-line signatures back onto one line, which directly contradicts StandaloneLineConstructorParamFixer. Configure it explicitly:

->withConfiguredRule(
    \Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer::class,
    ['line_length' => 120, 'break_long_lines' => true, 'inline_short_lines' => false]
)

Setting inline_short_lines to false is what stops it from undoing the standalone-line rules.

Run --fix twice (or check the exit code on the second dry run). Some fixers create work for others — a long line gets broken, then the array rule reflows it, then line length re-evaluates. A single pass can leave files dirty. Make it a habit: ecs --fix && ecs --fix, and confirm the second run is clean before committing.

Clear the cache when you change ecs.php. ECS caches file hashes and applied-rule results; rule additions or withConfiguredRule changes sometimes don't invalidate properly. If a rule you just enabled seems to be silently ignored, vendor/bin/ecs --clear-cache is the first thing to try — before you start debugging your config.

Docblock fixers need real, reflectable parameters. Rules like FixParamNameTypoFixer and AddMissingParamNameFixer compare the tag against the actual signature. They will skip variadics, __call/__get magic, closures in some contexts, and methods whose docblock describes a @param for a parameter that no longer exists. Don't assume a clean run means your docblocks are correct — spot-check the file you expected to change.

Multiline array<...> generics were historically skipped by the malform worker (per the 12.4.3 release notes), so nested generics in @param tags may not be normalized. Same for interpolation strings inside arrays with ArrayListItemNewlineFixer. Both are deliberate skips to avoid corrupting valid code — treat "fixer did nothing here" as a known limitation, not a bug to work around.

SpaceAfterCommaHereNowDocFixer is dead weight on PHP 7.3+. It exists to avoid a pre-7.3 heredoc parsing bug. Skip it unless you actually support old runtimes.

Extension point: AbstractDocBlockFixer. The 13.1.1 release split the old monolithic ParamReturnAndVarTagMalformsFixer into ten single-task fixers sharing this base class. That's your template if you need a house-specific docblock rule (@property normalization, for instance) — extend it, ship it in your own package, and register with withRules(). Each fixer also handles the @phpstan-/@psalm- prefixed variants, so your custom rule should too for consistency.

RemovePropertyVariableNameDescriptionFixer can strip comments you wanted. It removes docblock descriptions that merely duplicate the property name. If your team writes terse but intentional one-liners like /** The name of the user. */, this rule will eat them. Review that specific rule's diff carefully the first time it runs.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource