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

Technical Evaluation

Verdict: Do not adopt for new Laravel work. If already in the tree, freeze and schedule an exit. This is an archived, self-deprecated rule set (23 fixers) that only runs as an input to ECS, in a market where Laravel ships Pint as the default formatter. The package's own README redirects users to ECS, and the repository is archived — so any value here is time-boxed and the ownership burden transfers entirely to us.

Architecture fit

  • These are PHP-CS-Fixer AbstractFixer subclasses, not Laravel-aware tooling. They know nothing about Blade, Eloquent conventions, Artisan, or Laravel's own style baseline. Value is generic PSR-adjacent hygiene: array/argument line breaking, method-chain newlines, constructor promoted-property layout, and ten narrow docblock @param/@return/@var normalizers.
  • It hard-depends on symplify/easy-coding-standard (also deprecated) as the runner. That is a second archived dependency in the dev chain, and ECS is a competitor to Pint/PHP-CS-Fixer's native CLI rather than a complement.
  • Fit with a standard Laravel image (pint in CI, composer cs script, pre-commit hook) is poor: Pint cannot load ECS config, and ECS cannot consume pint.json. Adopting this means running two formatters over one codebase — a direct source of rule conflicts and non-deterministic --fix output.
  • The genuinely interesting rules (the docblock malform family, StandaloneLinePromotedPropertyFixer, RemoveUselessDefaultCommentFixer) are individually useful but are not worth an entire parallel toolchain.

Integration feasibility

  • Mechanically trivial: composer require --dev, one ecs.php with ->withPreparedSets(symplify: true), run vendor/bin/ecs --fix. Half a day end to end on a mid-size app.
  • Composer will surface an "abandoned package" warning on install and on every subsequent composer update. Many hardened CI pipelines and dependency-review bots treat abandoned transitives as a finding to justify.
  • Real blocker is not installation but output: the first --fix run against an existing Laravel codebase will rewrite arrays, chained calls, and constructor signatures repo-wide. That is a large, low-signal diff landing on top of in-flight feature branches.
  • The docblock fixers mutate annotations that PHPStan/Larastan and Psalm consume for type narrowing. RemoveSuperfluousVarNameFixer, SwitchedTypeAndNameFixer, and RemoveDeadParamFixer can silently change what static analysis infers — a behavioural risk disguised as a formatting change.

Technical risk

  • Archived upstream, zero dependents. No security response, no PHP-version compatibility work, no bug triage. New PHP syntax (property hooks, asymmetric visibility, readonly classes, PHP 8.4+ constructs) may be mis-parsed by older fixer token logic, and --fix on unparseable tokens is how you get corrupted source.
  • Deprecation is intentional and directional. The maintainer's stated path is "use ECS," and ECS itself is superseded. Betting a repo's style contract on a two-level-deep abandoned chain is a compounding liability.
  • Rule collisions. Formatting rules here (method chaining on own line, array opener/closer on own line) fight common PSR-12/Pint defaults. Whichever runs last wins, which makes CI and local runs disagree.
  • Blame/review tax. Repo-wide reformatting destroys git blame on the exact files engineers are actively debugging; without .git-blame-ignore-revs this is a lasting productivity drag.
  • Zero-dependency signal. 377 stars and 0 dependents is a small, essentially unmaintained user base — no downstream bug reports to lean on, no community fork likely.

Key questions to answer before any decision

  1. Is this already in composer.json on any repo we own? If yes, which PHP versions and which Pint version are in play, and are they conflicting today?
  2. Does our CI fail on Composer's abandoned-package warning, or on composer audit/dependency-review policy?
  3. Do we rely on docblock @var/@param annotations for Larastan narrowing? If so, which of the ten docblock fixers are safe against our baseline?
  4. What is the actual pain we're solving — docblock hygiene, or line-length/array layout? If the latter, Pint already covers it.
  5. Who owns the fork if we vendor these fixers? Naming a maintainer is the price of admission for archived code.

Integration Approach

Stack fit

  • Laravel's native answer is Pint (PHP-CS-Fixer under the hood, vendor/bin/pint, pint.json). Anything we standardise should land there. This package has no path into Pint: Pint exposes only built-in PHP-CS-Fixer rules and has no plugin API for custom fixers.
  • If we specifically want the docblock malform rules, the correct fit is raw PHP-CS-Fixer with vendored fixer classes (they extend AbstractFixer, so they register with $config->registerCustomFixers()), not ECS. That keeps one runner in the repo.
  • Recommended default: use Pint exclusively; treat this package as a reference implementation to copy rule semantics from, not a runtime dependency.

Migration path

  1. New projects: Pint only. No exception. Document the decision in the engineering standards doc so it doesn't get re-litigated.
  2. Projects with ECS + this set today: pin exact versions (composer require --dev symplify/coding-standard:13.1.1 symplify/easy-coding-standard:<exact>), do not run composer update on the dev toolchain without review, and add a SECURITY.md note recording the frozen-toolchain exception and its expiry date.
  3. Exit ramp (quarterly, one repo at a time): snapshot current ECS output → run Pint over the same tree → diff the two outputs → classify each divergence as "keep" (port to pint.json as a built-in rule or a vendored custom fixer) or "drop" (accept Pint's default). This yields a small, defensible rule set rather than a wholesale port.
  4. Vendoring option (only if docblock rules are load-bearing): copy the ~10 docblock fixer classes plus their tests into an internal tools/coding-standard package, keep MIT attribution, register via PHP-CS-Fixer. This converts an abandoned dependency into owned code with a known blast radius.
  5. Never run both formatters in one pipeline. Pick one, gate on it.

Compatibility

  • Verify PHP constraint of the release line against our minimum supported PHP; ECS-era packages typically lag current PHP minor versions and will refuse to install on newer runtimes.
  • Check that the fixer set doesn't contradict pint.json rules we've already committed to (method chaining, array formatting, declare(strict_types=1) spacing are the likely flashpoints).
  • Confirm the pinned versions resolve cleanly alongside Laravel's own dev dependencies (larastan, phpunit, laravel/pint) — abandoned packages are a frequent cause of unsatisfiable dev constraints on the next framework major.
  • Validate on a branch with full test suite + PHPStan run, not just ecs --fix exit code zero.

Sequencing

  1. Inventory: grep every composer.json for symplify/ and every ecs.php in the org.
  2. Baseline: capture current formatting; commit nothing else in the same window.
  3. One-time normalisation commit if adopting — isolated, conventional-commit labelled, added to .git-blame-ignore-revs.
  4. Wire the chosen formatter as a check-only CI step (--dry-run / pint --test) before enabling --fix locally or in hooks.
  5. Only then remove the old runner from composer.json, in a separate PR from the formatting commit.

Operational Impact

Maintenance

  • Maintenance cost is not zero — it is fully internalised. Upstream is archived, so any bug, PHP-version break, or false-positive fix is ours to fix or work around.
  • Pinning buys stability but accrues interest: every future Laravel or PHP upgrade has to be validated against a dead dev dependency, and the pin will eventually block a required bump.
  • Budget roughly: 1–2 engineer-days for the initial rollout, ~0.5 day per repo for the exit migration, and an unbounded tail if a fixer corrupts a file at an inopportune moment.
  • Composer's abandoned-package warning creates recurring low-grade noise that erodes trust in dependency hygiene unless explicitly documented and accepted.

Support

  • No upstream support channel. Issues, PRs, and security reports go nowhere. Internal ownership must be assigned by name before adoption.
  • Developer questions ("why did the formatter mangle my docblock?") route to whichever engineer championed it — a single point of failure and a bus-factor-1 risk on the dev toolchain.
  • Onboarding docs must state clearly that the toolchain is frozen and why, or a future engineer will "helpfully" run composer update and break the build.

Scaling

  • Runtime cost is fine: these are AST/token-level fixers, linear in file count, comparable to Pint. Thousands of files is minutes, not hours.
  • The scaling problem is organisational, not computational: N repos × pinned abandoned toolchain = N migration projects. Solve it once at the org level (one internal standards package, one formatter) rather than repo by repo.
  • Divergent rules across repos is the typical failure at scale — some repos on Pint, some on ECS, diffs churning between them when code is moved.

Failure modes

  • Silent semantic drift — docblock fixers rewriting @var/@param that Larastan relies on, degrading static analysis without failing tests. Highest-severity, lowest-visibility failure.
  • Source corruption on new syntax — a fixer mis-tokenising PHP constructs it predates and emitting non-parseable code. --fix has no rollback; recovery is git checkout.
  • Formatter war — ECS and Pint both wired into hooks/CI, each reverting the other; PRs oscillate and reviewers lose confidence in the gate.
  • Dependency deadlock — pinned abandoned package blocks a required Laravel/PHP upgrade at an inconvenient time, forcing an emergency migration under deadline.
  • Merge-conflict storm — repo-wide --fix landing while branches are open; measurable rework, usually underestimated.
  • CI policy break — dependency scanner or abandoned-package check flips a previously green pipeline to red with no code change.

Ramp-up

  • Engineer ramp-up is genuinely low: install, register the set, run. The README is adequate, and the 23 rules are individually illustrated with diffs.
  • The learning cost is not the tool, it's the diff review burden: reviewers must distinguish formatting churn from real logic changes across a large one-time commit. Mitigate with a formatting-only commit, .git-blame-ignore-revs, and a short team note.
  • Net: ~30 minutes to teach, ~1 sprint of friction to absorb. Acceptable — but only in service of a rule set we intend to keep, which this package is not.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core