patchlevel/coding-standard
A shared PHP coding standard configuration for the Patchlevel ecosystem, bundling rule sets and fixer presets so teams can enforce consistent code style with minimal setup. Add it as a dev dependency and extend the ready-made config in your PHP-CS-Fixer or ECS setup to keep projects aligned without...
What it actually is. patchlevel/coding-standard is not an application library — it is a thin, opinionated PHP_CodeSniffer ruleset (XML rule config plus a small set of custom sniffs) layered on top of squizlabs/php_codesniffer and slevomat/coding-standard. Architecturally it is a development-time tooling dependency only (require-dev), with no runtime footprint, no service provider, no autoload surface, and no effect on production code paths. That is the single most important fact for the assessment: the blast radius is confined to CI and developer laptops.
What changed in 1.3.0. A minor "feature" release containing exactly one merged PR — #13 "re-copy doctrine standard" — from one contributor. Zero issues resolved. There are no new sniffs, no dependency or constraint changes announced, no PHP/PHPCS version-matrix expansion, and no deprecations. Substantively this is a ruleset content refresh, not a capability release. Two signals are worth recording: (a) the package is not fully abandoned — it shipped after a long gap, and (b) it is still maintained by re-copying an upstream standard rather than by authoring or modernizing rules, which tells you the maintainer's model is vendoring, not product stewardship.
Architecture fit. Good, with one caveat. A ruleset package is exactly the right shape for a shared standard across multiple Laravel/PHP repos — one versioned constraint, uniform enforcement. The caveat is ecosystem overlap: Laravel's default is Pint (PHP-CS-Fixer), not PHPCS. Adopting this package means running two formatters or replacing Pint. Slevomat does add value beyond formatting (strict types enforcement, unused imports, dead code, type-hint discipline), so the two are not strictly redundant — but the team must decide explicitly, or it will end up with both and neither enforced. Note that 1.3.0 pushing Doctrine conventions further reinforces that this is a generic PSR-12/Slevomat/Doctrine-flavored standard, not a Laravel-specific one — worth confirming before you sell it internally as "the Laravel standard."
Integration feasibility. Mechanically trivial: composer require --dev, reference the standard in phpcs.xml, add a CI step. The real friction is version pinning. Expect this package to constrain PHPCS and Slevomat versions tightly; with 0 dependents and a single star, those constraints have never been exercised against the wider ecosystem. Constraint conflicts with other dev tooling remain the most likely first failure. 1.3.0 does not visibly relax any constraints, so this risk is unchanged by the release.
Technical risk. Still dominated by staleness, but the picture is now marginally less bleak than at the last assessment:
| Risk | Severity | Notes |
|---|---|---|
| Content lags PHP 8.3/8.4, PHPCS 4.x, current Slevomat majors | High | 1.3.0 refreshed Doctrine rules only; no indication of platform modernization |
| Constraint conflicts | High | Pinned PHPCS/Slevomat can block org-wide composer update |
| Bus factor ~1 | High | Still one effective owner; 1.3.0 brought the first outside contributor, a genuine but small positive |
| Release cadence | Medium | Multi-year gap then a single-PR release — cannot be planned against |
| False positives on new syntax | Medium | Enums, readonly, property hooks can still trip stale sniffs |
| No upstream support | Medium | You remain the maintainer if you adopt it |
| License | Negligible | MIT, permissive, clean |
Key questions to answer before commitment. Who at Patchlevel owns this ruleset, and is it maintained internally even when public releases stall? Did 1.3.0 change any Composer constraints, and against which PHP/PHPCS/Slevomat matrix was it validated? Is the value in the rules or the packaging — given the maintainer's own workflow is "re-copy an upstream standard," could we copy the ruleset XML and drop the dependency? What is the one-time diff size on our largest repo, and is the Doctrine flavoring compatible with our existing conventions? And critically: are we proposing to replace Pint, or run alongside it?
Stack fit. Native. Composer, PHP 8.x, Laravel — no adapters needed. It slots into the standard places: a composer lint / composer lint:fix script pair, a CI job (phpcs --report=checkstyle for inline PR annotations), and optionally a pre-commit hook via GrumPHP or CaptainHook. Recommend PHPCS for correctness sniffs and Pint for formatting, if the team can tolerate two tools; otherwise pick one and delete the other from the repo to avoid ambiguity.
Consume vs. fork — the decisive choice. Still the central decision, and 1.3.0 does not change it. A single-PR release that re-copies a third-party standard confirms rather than refutes the "copy the ruleset, own the config" path:
phpcs.xml, add PHPCS and Slevomat directly. Zero dependency risk, at the cost of duplicating config across repos. This is functionally what 1.3.0 itself did upstream.Compatibility checks. Re-validate against 1.3.0 specifically rather than assuming prior behavior: diff the ruleset against whatever version you spiked on, since a Doctrine re-sync can silently change or add sniffs and create new violations on existing code. Confirm the Composer constraints against your current PHP matrix and PHPCS version before rollout, and check whether the pinned Slevomat version lags PHPStan/Psalm in a way that produces conflicting opinions about the same code.
Sequencing. Stage the rollout so churn and constraint risk surface early:
phpcs without fixes, and measure violation count and diff size. This is the go/no-go data point — and now also the 1.2.x→1.3.0 delta check.phpcbf commit recorded in .git-blame-ignore-revs.CONTRIBUTING.md, wire auto-fix into the pre-commit hook.Maintenance. This is the crux, and 1.3.0 is the clearest evidence yet of the shape of the cost. The package is not dead — but it is maintained episodically, in bursts, by vendoring an upstream ruleset. You cannot plan a dependency-upgrade window around that cadence, and you cannot assume a breakage you report will be fixed on any timeline. Adopting this package is not "consuming a library," it is acquiring a lightly-maintained internal tool. Budget a few hours per quarter for dependency bumps plus a multi-hour session whenever PHPCS or Slevomat ships a major. If you fork: ~1 day initial for constraint loosening and CI wiring, then 1–2 days per year steady state. If you consume as-is, that cost lands anyway — as a blocked composer update at the worst possible time.
Support. No external support, but the support signal improved slightly: 1.3.0 is the first release with an outside contributor, which is weak evidence of a functioning contribution path. It is not evidence of a support commitment — one PR, zero issues resolved, and no published triage or SLA. Internal ownership remains mandatory: name a maintainer and a backup. Ramp-up for that maintainer is meaningful — PHPCS sniff architecture, Slevomat rule semantics, and custom sniff authoring are specialized skills, roughly 1–2 weeks to competence. For ordinary developers ramp-up is near zero: they run composer lint:fix and move on, which is the package's main virtue.
Scaling. Runtime cost is nil (dev-only, never deployed). Scaling cost is organizational: the standard's value is directly proportional to how uniformly it is applied. Across N repos, config drift is the default outcome unless the ruleset is versioned centrally and pinned consistently — and a ruleset whose content can shift under you in a minor release makes that pinning more important, not less. Decide up front whether the standard is mandatory or advisory; a half-enforced standard generates friction without producing consistency.
Failure modes to design against.
composer update org-wide. Mitigation: pin loosely in your fork; test upgrades on a schedule, not under pressure.phpcs:ignore rather than fix. Mitigation: require justification on suppressions and review them.Decision framing. 1.3.0 does not change the recommendation; it sharpens it. The release confirms the package is alive but vendored — the artifact is worth less than its ideas. Recommended path remains: run the two-day spike to quantify churn against 1.3.0 specifically, then fork it internally or inline the ruleset rather than consuming patchlevel/coding-standard as a live, loosely-pinned dependency. The MIT license and trivial integration cost make either option cheap; the episodic cadence, effectively single-owner stewardship, and rule-content churn inside a minor release make unqualified adoption the one choice that quietly converts a convenience into a recurring liability.
How can I help you explore Laravel packages today?