artisanpack-ui/code-style
A custom PHP_CodeSniffer standard for ArtisanPack UI projects, with 16+ sniffs enforcing consistent formatting, naming, security, and best practices. Install via Composer, add a phpcs.xml ruleset, and run phpcs to check your code.
What the package actually is. artisanpack-ui/code-style is not a library or framework integration — it is a ruleset artifact: a Composer dev dependency that registers a PHP_CodeSniffer standard named ArtisanPackUIStandard, composed of ~16 custom sniffs plus an inherited base. From a TPM perspective this places it in the developer tooling / quality gate category, not the application runtime category. That has three consequences worth stating up front:
phpcs runs in CI and/or pre-commit and the team acts on the output. Adoption is therefore a process investment, not a dependency investment.Architecture fit. Good on mechanics, contentious on policy.
ControlStructures sniff (alternative syntax if : endif; in templates, braces elsewhere) and the PhpTags rule (no PHP tags in Blade) are genuinely useful and are the kind of thing a generic formatter will not give you. If Blade-heavy code review friction is a real pain point for us, this is the strongest technical justification for choosing PHPCS-over-Pint, and this package is a ready-made starting point.if ( $x ) { (violates PSR-12 and Laravel conventions); tabs for indentation (PSR-12 mandates 4 spaces); Yoda conditionals (widely regarded as hostile to readability and actively discouraged in many style guides); uppercase magic methods __CONSTRUCT() (legal — PHP magic methods are case-insensitive — but surprising, and likely to trip IDEs, static analysers, and reviewers); mandatory type declarations across all functions and properties. The TypeDeclaration sniff does carve out an exception for Laravel Models (property types break Eloquent's magic attribute handling), which shows the author understands Laravel — but that carve-out is a signal that more exceptions will be needed (facades, macros, Blade components, form requests, closures in config files, migrations).Integration feasibility. Technically trivial, organisationally non-trivial.
composer require --dev, one phpcs.xml, one CLI invocation. Any engineer can have it running in ten minutes.Indentation (if we are a spaces shop, every line of every file is a violation) and Spacing (the parenthesis-space rule hits nearly every control structure). This is the crux of the go/no-go decision, and it must be measured before it is debated.phpcs.xml that starts by exclude-ing the sniffs we cannot afford to retrofit, then ratchets them on per-directory. That is workable but requires ongoing ownership.Technical risk. Rated low-to-moderate, and almost entirely supply-chain and governance risk rather than engineering risk.
Key questions to resolve before commitment.
--report=summary plus a per-sniff tally.)composer.json constrain PHP_CodeSniffer to ^3 or ^4? This determines whether we can use a baseline and whether a future PHPCS major breaks us.TypeDeclaration survive contact with our framework code beyond Models — facades, macros, Blade components, service providers, config closures? Expect to need additional exclusions.Stack fit. Composer-native, dev-only, zero runtime footprint — fits any Laravel 10/11/12 or standalone PHP 8.2+ project. It sits alongside, not inside, the application. The only genuine differentiation versus the ecosystem default (Laravel Pint) is Blade-aware sniffing and custom organisational rules; on pure PHP formatting, Pint is more idiomatic, faster, and first-party. Frame the decision as: "Do we need Blade-template enforcement and custom naming rules badly enough to run PHPCS as well as, or instead of, Pint?"
Make the formatter decision first. Three viable end states, in ascending order of cost:
ArtisanPackUIStandard but exclude Indentation, Spacing, YodaConditionals, and MagicMethods so PHP-CS-Fixer and PHPCS do not fight over the same tokens, keeping ControlStructures, PhpTags, ImportOrdering, ClassStructure, DisallowedFunctions, and NamingConventions. This captures most of the differentiated value at a fraction of the remediation cost.Migration path. Treat this as a ratchet, never a big bang.
phpcs.xml with explicit per-sniff exclusions and the rationale in a comment block — the config file becomes the record of the decision.phpcbf in dedicated, isolated formatting-only commits (no functional changes, added to .git-blame-ignore-revs). Never mix a reformat with a feature branch.Compatibility considerations.
"artisanpack-ui/code-style": "1.x.y", not ^1.0). Ruleset content is the contract; float is drift.Indentation reformats every file and creates merge conflicts across every open branch. Sequence it for a quiet period, or exclude it permanently and let Pint own whitespace.--extensions=php behaviour against .blade.php files and verify the Blade sniffs do not false-positive on heavy @directive usage or inline Alpine/JS. This is the sniff-set most likely to crash or misfire and it is also the one we care most about — test it explicitly.vendor/bin/phpcs and the standard name) as in CI, or the gate feels arbitrary. Budget for a short setup guide and verify it during ramp-up.--cache, --report=summary for the always-on job, split by directory across parallel jobs if wall-clock matters, and keep the full report for nightly.Sequencing recommendation. Pilot on one repo, warn-only, trimmed ruleset (option B), pinned version, four weeks, with a written exit criterion. Do not roll to the fleet until the violation-count trend and false-positive rate are known.
Maintenance. Ongoing cost is low in absolute terms but concentrated in one place: the phpcs.xml file. That file, not the package, is the operational asset — it encodes which opinions we have adopted and why. Assign a named owner (a platform/tooling engineer or the tech lead on the pilot repo) and put phpcs.xml and the CI lint job under CODEOWNERS. Without a named owner, the ruleset silently rots: someone adds an exclude to unblock a PR and the standard quietly erodes. Budget roughly 1–2 days per quarter for sniff upgrades, false-positive triage, and exception requests.
Support. Three tiers to plan for:
Spacing, Indentation, and YodaConditionals. A one-page internal cheat-sheet with correct/incorrect examples (the README's sniff reference is a good base, but write our own covering our exclusions) will absorb most of it.Scaling. Scales fine on the dependency axis (dev-only, no runtime load, adding repos is one phpcs.xml each). It scales poorly on two axes:
phpcs.xml.dist distributed to repos over per-repo hand-maintained copies, so the standard stays one thing rather than fifteen.Failure modes to pre-plan.
| Failure mode | Symptom | Response |
|---|---|---|
| Standard not registered | ERROR: the 'ArtisanPackUIStandard' coding standard is not installed |
Documented in the troubleshooting guide: check vendor/bin/phpcs -i, reinstall the dev dependency. Cosmetic, high-frequency during onboarding. |
| Upstream ruleset change | Build red on untouched code after a Composer update | Pinned version makes this deliberate; treat rule changes as reviewed upgrades in a dedicated PR. |
| Formatter conflict | Pint and phpcbf fight over the same lines, diffs churn |
The reason to exclude formatting sniffs from PHPCS and let one tool own whitespace. Decide this up front. |
| Blade false positives | Sniffs crash or misfire on templates | Quarantine Blade paths behind an exclusion while triaging; report upstream, work around locally. |
| Mass reformat collateral | Formatting commit collides with in-flight feature branches | Isolate reformats into formatting-only commits, record them in .git-blame-ignore-revs, schedule in a quiet window. |
| Unblock-by-exclusion creep | Standard degrades to nothing within two quarters | CODEOWNERS on phpcs.xml, require a justification comment on every exclude. |
| Security theatre | Team believes "we have security linting" | Explicitly document that security sniffs are pattern-matching, not taint analysis; keep the SAST conversation separate. |
Ramp-up. Plan for two to four weeks of warning-period operation before the gate becomes blocking, and roughly 3–8 engineer-days total for the pilot: ~1 day audit, ~1 day ruleset authoring and CI wiring, ~1 day IDE setup guide and team comms, and the remainder for triage and iteration. Fleet rollout is dominated by remediation effort, not integration effort, and its size is knowable only after the audit step. A fully greenfield project can compress this to 2–3 days.
Bottom line for the decision record. The integration is cheap and the exit is cheap, which argues for piloting rather than debating. The package's genuine, defensible value is Blade-aware enforcement plus custom naming/structure rules that Pint cannot express; its weakest aspects are opinionated formatting choices that collide with the ecosystem and a near-zero community footprint. Recommend option B — trimmed ruleset, warn-only pilot, pinned version, named owner, pre-agreed fork escape hatch — and gate fleet rollout on the measured violation trend. If the audit shows the differentiated sniffs catch little real review friction, reject cleanly and stay on Pint; the sunk cost is a few days.
How can I help you explore Laravel packages today?