laravel-quality
Installation
SKILL.md
Laravel Quality
Four tools keep a codebase consistent: Pint formats it, Rector refactors and upgrades it, Pest type coverage reports what's untyped, and one architecture test keeps debug calls out of committed code. Write code that already satisfies them, so running them changes nothing. PHPStan isn't part of the default stack.
Rules
declare(strict_types=1)in every PHP file. App code, tests, config, migrations, routes. Pint'sdeclare_strict_typesadds it, but write it yourself so a file is right before Pint runs. Strict mode turns a silently coerced scalar into aTypeErrorat the call.- A return type on every method, function and closure,
voidincluded, except controller methods. Controller methods omit them (see laravel-controllers). Type coverage counts every missing one. - Type every parameter and property. Nullable is
?Order, neverOrder|null. - Generics go in PHPDoc, only where a native type can't say it.
/** @var Collection<int, OrderLineData> */above a promoted property,@return Collection<int, Order>,array<string, mixed>. NeverOrder[]. Don't repeat a native type in a docblock: Rector's dead-code set deletes it. - One house pint.json, references/pint.json. Every project formats the same way, so code moves between them without a style diff. Read it when creating or changing a project's Pint config; don't add per-project rules.
- Rector is run by hand, not on commit. It rewrites logic, so its diff gets reviewed:
composer rector-dryto review,composer rectorto apply, thencomposer pint. Read references/rector.php when creating the config or upgrading PHP or Laravel; bumpLevelSetList::UP_TO_PHP_84andLaravelSetList::LARAVEL_120to the project's versions, and pointwithPaths()at the project's source roots. - Format on commit, nothing else. lint-staged runs
composer pint-dirtyon staged PHP files, so no commit carries style noise. The test suite runs on demand, not as a commit hook. - One architecture test: no
dd,dumporray. Service providers are exempt: that's where local Ray debugging is wired (see laravel-providers). - Framework glue is excluded from coverage. Service providers and console commands carry a class-level
@codeCoverageIgnoredocblock, so coverage measures the code that holds logic. - No coverage or type-coverage minimum. Both are reports to read, not gates: no
--min.