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

Phpcsextra Laravel Package

phpcsstandards/phpcsextra

PHPCSExtra is a collection of extra sniffs and coding standards for PHP_CodeSniffer, including Modernize, NormalizedArrays, and Universal rules to help enforce consistent, modern PHP code. Requires PHP 5.4+ and PHPCS 3.13.6/4.x.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What this package actually is. PHPCSExtra is not an application library — it is a static-analysis ruleset bundle for PHP_CodeSniffer. It ships three registered standards (Modernize, NormalizedArrays, Universal) plus a PHPCSUtils helper dependency. There is no runtime code path in the product; the only artifact that reaches production is developer discipline. That framing matters for every downstream decision: value is realized entirely through CI enforcement and developer habit, not through deployment.

Architecture fit. Strong fit for any PHP codebase already standardizing on PHPCS — Laravel included, since Laravel projects are plain PHP and PHPCS scans app/, routes/, tests/, database/ normally. The value proposition is the gap PHPCS's bundled standards (PSR-12, PEAR, Generic) leave open: modern-PHP modernization (dirname(__FILE__) → __DIR__, nested dirname() collapsing), array normalization, and semantic "correctness" sniffs PHPCS native rulesets do not cover (DuplicateArrayKey, ForeachUniqueAssignment, NoDoubleNegative, NoEchoSprintf, StaticInFinalClass). Several sniffs include auto-fixers and honor a php_version runtime setting, which means the ruleset can be tuned to a minimum-supported-PHP floor rather than the team's newest local PHP.

The Universal trap. Universal is explicitly not a standard — it is a sniff collection containing mutually contradictory rules (Classes.DisallowFinalClass vs Classes.RequireFinalClass, Attributes.DisallowAttributeParentheses vs RequireAttributeParentheses, Classes.DisallowAnonClassParentheses vs RequireAnonClassParentheses). It must never be adopted wholesale. Adoption is therefore a product decision exercise — someone must pick a coherent policy set and document the rationale. This is the single largest effort driver and the main reason a "just install it" rollout fails.

Integration feasibility. Low technical friction, high organizational friction.

  • Install is a single Composer dev dependency; registration is automatic via dealerdirect/phpcodesniffer-composer-installer, which must be allowed in config.allow-plugins (a common first-run failure in locked-down CI images).
  • Dependency surface is small: PHP 5.4+, PHPCS 3.13.6/4.0.2+, PHPCSUtils 1.2.3+. The README advises removing direct pins on PHPCS/PHPCSUtils from the root composer.json and letting the standards manage them — good hygiene, but it means version resolution is delegated to a third party and can shift on composer update, which is exactly the kind of thing that breaks CI on an unrelated PR.
  • Conflict risk with existing tooling is the real feasibility question. Laravel shops typically run Laravel Pint (PHP-CS-Fixer under the hood). Pint and PHPCS overlap heavily on formatting. Running both creates fixer ping-pong and review churn unless responsibilities are split cleanly.

Technical risk.

  • Risky fixers. Universal.Classes.RequireFinalClass is flagged by the maintainers as potentially behavior-changing; auto-fixing it across a codebase can break mocking/proxying patterns silently. Any fixer marked risky needs a human-reviewed, single-purpose commit.
  • Style-policy collision with Laravel conventions. Universal.Arrays.DisallowShortArraySyntax is directly at odds with idiomatic Laravel/Pint output; NormalizedArrays overlaps with what Pint already enforces. Enabling these without a decision creates hundreds of "violations" that are really tool-policy disagreements, and developers learn to ignore the linter.
  • LGPL-3.0. Fine as a dev-only, non-distributed tool in almost all interpretations, but it needs a legal/policy check before it lands in a monorepo template, especially where dev dependencies get vendored or images are redistributed.
  • Adoption signal is ambiguous. 104 stars and "0 dependents" understate reality — PHPCS standards are rarely declared as Composer dependents, they are pulled in via ruleset references. But it also means there is no large public user base to shake out edge cases. The maintainer is the same organization behind PHPCS itself and PHPCSUtils, which is a stronger trust signal than the star count.
  • PHPCS major-version churn. Requiring 3.13.6/4.0.2+ puts the org on a path to PHPCS 4, which may itself break other standards (Slevomat, PHPCompatibility) in the same ruleset. This is a portfolio-wide toolchain decision, not a per-repo one.

Key questions.

  1. What is the enforceable minimum PHP version (--runtime-set php_version), and does it match our actual support matrix per service?
  2. Which specific Universal sniffs do we adopt, and who signs off on each policy? Who owns the ruleset file?
  3. Does PHPCS become the source of truth for formatting, or do we keep Pint for formatting and use PHPCSExtra only for semantic checks? (Recommendation: the latter.)
  4. Are we on PHPCS 3 or 4, and does that align with every other standards package we depend on?
  5. What is the baseline/ignore policy for legacy code — block-the-world gate, or incremental on changed files?
  6. Has legal cleared LGPL-3.0 for dev tooling in the relevant repos?

Integration Approach

Stack fit. Treat PHPCSExtra as a dev-only quality gate, layered as: laravel/pint (formatting, unchanged) → phpcsstandards/phpcsextra + internal ruleset (semantics and modernization) → CI. Concretely, one small internal Composer package (e.g., acme/phpcs-standard) that requires phpcsstandards/phpcsextra and defines a single AcmeStandard ruleset. That package is the delivery vehicle; individual repos only add acme/phpcs-standard and a phpcs.xml.dist that references it. This avoids each repo inventing its own policy and avoids every repo resolving PHPCS/PHPCSUtils versions independently.

Ruleset scoping — the actual design work. Start from Modernize as a whole (low controversy, high value, mostly auto-fixable, PHP-version-aware). For NormalizedArrays, adopt only after confirming it doesn't fight Pint — likely enable CommaAfterLast for multi-line arrays and skip brace-spacing if Pint already owns it. For Universal, cherry-pick: high-value/low-controversy first (DuplicateArrayKey, ForeachUniqueAssignment, NoDoubleNegative, NoEchoSprintf, ConstructorDestructorReturn, LowercaseClassResolutionKeyword); explicitly exclude DisallowShortArraySyntax, RequireFinalClass, DisallowFinalClass, and the attribute/anonymous-class parentheses pairs unless a policy decision says otherwise. Document exclusions in the ruleset file with one-line justifications — future maintainers will otherwise re-litigate them.

Migration path.

  1. Spike (1 sprint, one repo). Install as dev dependency, run phpcs -i to confirm the three standards register, run phpcs --standard=Modernize --report=summary on app/ only, and estimate violation volume. Deliverable: a written recommendation on which sniffs to adopt and which to exclude, plus a measured CI runtime number.
  2. Baseline-free adoption on new code. Add the ruleset to CI for changed files only (or a diff-aware invocation) so existing debt doesn't block merges. Greenfield services adopt the full agreed set immediately.
  3. Legacy remediation as a dedicated workstream. Run phpcbf per sniff family, one commit per sniff, no functional changes. Add a .git-blame-ignore-revs entry so git blame stays usable. Risky fixers (RequireFinalClass) are manual-review only, never auto-applied.
  4. Promote to the shared standard. Move the agreed ruleset into acme/phpcs-standard, version it, and roll it out repo by repo. Treat ruleset changes like any other dependency change: changelog, review, and a "this will surface N new violations" note.

Compatibility considerations. Pin the internal standard package's constraints rather than the underlying tools; avoid direct require-dev on squizlabs/php_codesniffer or phpcsstandards/phpcsutils in app repos (per the README's own guidance) unless a repo consumes them directly. Verify allow-plugins is set in both local and CI Composer configs. Confirm the PHP version used in CI matches the php_version runtime setting, otherwise sniffs will report modernizations the deployed runtime can't support.

Sequencing rationale. Modernize → semantic Universal sniffs → NormalizedArrays. Formatting-adjacent rules come last because they collide with the existing formatter and generate the most diff noise; semantic rules come first because a violation there is usually a genuine bug or a real maintainability win, which builds credibility for the gate.

Operational Impact

Maintenance. Very low ongoing cost if the shared-standard pattern is used. One ruleset package, one changelog, quarterly dependency refreshes. Without that pattern, N repos each pin their own version and drift into inconsistent enforcement — measurable as "PRs that pass locally but fail CI" and "why did this repo's style change." The upstream maintenance profile is favorable: the package is maintained by the PHPCS Standards organization alongside PHPCSUtils, has an active release cadence, and documents per-sniff properties and error codes, which means ruleset changes are addressable without forking.

Support. Support burden is almost entirely educational, not technical. Expect recurring questions in three buckets: (1) "the fixer rewrote my code and the diff is huge" — mitigated by one-sniff-per-commit policy and blame-ignore; (2) "Pint and PHPCS disagree" — mitigated by the documented division of responsibility; (3) "why is this a violation?" — mitigated by phpcs --generator=Text per sniff, which emits the sniff's own documentation. A short internal style guide page covering adopted sniffs, excluded sniffs, and the two-command workflow (vendor/bin/phpcs, vendor/bin/phpcbf) removes most of it.

Scaling. PHPCS is single-threaded and file-based; runtime scales roughly with scanned file count. At monorepo scale this becomes a CI bottleneck. Mitigations: scan changed files in PRs, run the full scan in a nightly or post-merge job, parallelize in CI via a matrix split by directory or via --parallel, and always exclude vendor/, storage/, bootstrap/cache/, and build artifacts. Cache the Composer layer in CI so the PHPCS install isn't the dominant cost. Budget: expect CI to add low-single-digit minutes for a mid-size app on a changed-files scan; full scans on large repos can reach several minutes and belong off the critical path.

Failure modes to plan for.

  • Plugin not allowed → standards silently missing from phpcs -i, rule appears to pass. Add an assertion step in CI that the expected standards are registered.
  • Formatting tool collision → alternating diffs, developer workarounds, gate disabled. Split responsibilities up front.
  • Risky fixer run at scale → behavioral regression merged under a "style" commit. Require risky fixers to be manual.
  • Dependency drift → an unrelated composer update bumps PHPCS/PHPCSUtils and changes the ruleset. Constrain and renovate deliberately.
  • Policy disagreement surfacing as noise → hundreds of violations on day one, team disables the gate. Prevented by the changed-files rollout and documented exclusions.
  • Version-skew between local and CI PHP → php_version-aware sniffs behave differently. Pin the PHP version in both.
  • LGPL review failing late → rollback after adoption. Clear it before the spike ships.

Ramp-up. Estimate one engineer-week for the spike plus ruleset design, and 2–5 engineer-days per repo for the initial remediation commit depending on size and existing adherence. Developer-facing ramp-up is genuinely small — two commands, one style guide — but the organizational ramp-up (agreeing the policy, legal clearance, deciding the Pint relationship, deciding PHPCS 3 vs 4) is where the calendar time goes and should not be underestimated in the plan. Ramp-up cost is inversely proportional to how early the shared-standard package exists; building it in the spike rather than after three repos have already adopted ad-hoc configs is the highest-leverage sequencing decision.

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.
alphabalex/messaging-made-easy
rawphp/warp
shootkiran/merobug
narakode/fineauth
numencode/wn-syncops-plugin
ibnnajjaar/mib-global-pay
ably/pubsub-server
mstfkhazaal/defender
mfonte/base62x
karnoweb/metapilot
tobya/bcsapiwrapper
swalker2/cpanel
vish4395/laravel-translation-manager
morningtrain/economic
teksite/systeminfo-laravel
atomcms/voting
run6/weather
siokas/laravelembeddirectives
adamlien/pkuuids
gilsonsouza/lara-doc-generator