- What is canvural/larastan-strict-rules?
- It is a dev-only PHPStan rules plugin that adds extra strict, opinionated checks on top of Larastan for Laravel projects. The eight rules ban dynamic where* calls, facades including real-time facades, Laravel global helper functions, request validation inside controllers, property accessors, and local model query scopes, while also requiring scopes to return an Eloquent Builder and event listeners to declare a void return type. Architecturally it is a lint policy pack rather than a runtime library: it ships PHPStan Rule implementations plus a rules.neon fragment and never executes in the request lifecycle. There is no service provider, no database or queue surface, and no boot-time cost.
- How do I install larastan-strict-rules in a Laravel project?
- Install it as a dev dependency with composer require --dev canvural/larastan-strict-rules, then add the package's rules.neon to the includes section of your project's phpstan.neon, pointing at vendor/canvural/larastan-strict-rules/rules.neon. Once included, all eight rules are active by default. You should already have PHPStan and Larastan configured, since this package extends Larastan's analysis rather than replacing it. That single include line is the entire happy path for most teams.
- Can I enable the rules one at a time instead of all at once?
- Yes, and this is the package's most important feature for real-world adoption. Set larastanStrictRules.allRules to false to switch every rule off, then re-enable individual rules by name, for example setting noDynamicWhere to true. Each of the eight rules has its own boolean parameter, so you can roll out a phased, reversible policy without forking the package. Two rules need additional configuration: allowedGlobalFunctions for the global helper rule and listenerPaths for the event listener rule.
- Which PHPStan and Larastan versions does this package support?
- Compatibility is tied to Larastan and PHPStan majors rather than to your Laravel version directly, so check the constraint matrix in composer.json before upgrading. The 3.x line targets Larastan 3 and PHPStan 2, while the 2.x line covers earlier Larastan and PHPStan releases. The changelog is largely compatibility churn, including fixes for PHPStan 1.9.0 and repeated Larastan compatibility patches, so every PHPStan or Larastan major upgrade becomes a coordinated three-way upgrade between PHPStan, Larastan, and this package. Pin versions and upgrade them together rather than independently.
- Does installing this package affect production performance?
- No. It is a dev-only static-analysis plugin with no production dependency, no service provider, and no boot-time cost, so nothing is loaded during a request. It observes code through PHPStan rather than executing in your application, which means the only cost is extra analysis time in CI or local linting. That also means adopting it is a code-standards decision rather than an infrastructure one, and it should be owned by whoever governs engineering standards.
- How do I allow specific Laravel global helpers like app or event?
- The NoGlobalLaravelFunctionRule accepts an allowedGlobalFunctions parameter listing the helper names you want to permit. In the README example, app and event are passed as a list under parameters. Anything not listed is reported, so start from an explicit whitelist based on what your codebase genuinely needs. Reviewing that list periodically is worthwhile, because it is effectively a written statement of which Laravel magic your team tolerates.
- What does NoFacadeRule check, and does it catch real-time facades?
- NoFacadeRule disallows usage of Laravel facades, and it also checks for real-time facade usage, such as importing a class through the Facades namespace prefix. In practice it pushes your code toward explicit constructor injection and away from statically resolved service access. That is a defensible hygiene stance, but it is a genuine architectural policy, so make sure your team agrees with it before enabling the rule. If the standard is not endorsed, the rule will simply be suppressed under delivery pressure.
- Why does the listener rule need listenerPaths configured?
- The listenerShouldHaveVoidReturnType rule needs to know which directories contain your event listeners so it can resolve those classes and verify their handle methods return void. You supply those locations through the listenerPaths parameter; without them the rule cannot reliably identify listeners. Before rolling it out, confirm how the rule behaves when a configured directory does not exist. A silent no-op is dangerous because teams would believe the listener rule is enforced when it is not, so a loud failure is strongly preferable.
- Can I adopt larastan-strict-rules gradually in an existing large Laravel codebase?
- Yes, and that is the intended path: disable everything with allRules: false, enable one rule, fix or baseline the findings, then move to the next. Do this on a branch first, because these rules are opinionated and have historically produced false positives on idiomatic code, including a fix for dynamic where checks on relations and a fix for model scopes being misclassified as dynamic where. Check whether the rules emit stable PHPStan error identifiers, since baselining or ignoring by identifier survives upgrades far better than matching message strings. Finally, get a written engineering standard on facades, global helpers, and accessors before enabling those rules, otherwise you are making a policy decision by tooling accident.
- What happens if the package is abandoned or a PHPStan upgrade breaks it?
- The exit cost is low: the package is MIT licensed, dev-only, and has a small rule surface, so you can fork it, vendor it, or drop it with no production impact. The realistic risk is version coupling rather than lock-in, since custom rules depend on PHPStan reflection and type APIs that move between majors, plus a bus factor of one primary maintainer. Pin the package alongside PHPStan and Larastan, and treat upgrades as a three-way coordinated change. If maintenance stalls, forking the handful of rule classes you actually enabled is a practical fallback.