dave-liddament/phpstan-php-language-extensions
A PHPStan extension that adds support for extra PHP language features and type declarations, widening static analysis coverage so PHPStan understands more of your code. Helps catch bugs earlier and reduces false positives in Laravel and PHP projects.
php-language-extensions attribute family (#[Internal], #[Friend], #[Pure], #[Immutable], #[NamedConstructor], etc.). The decision is a low-cost "buy" (MIT, zero runtime footprint) against an expensive-to-maintain internal alternative.#[Internal] and #[Friend(SomeClass::class)] turn "please don't call this from outside the module" from a wiki page into a CI failure. That makes go/no-go decisions about exposing a class to another team a code change with a reviewable diff, not a social negotiation.#[Friend] entries per module) instead of a subjective "we're more modular now."Adopt it when most of the following hold:
php-language-extensions. The package validates those attributes; without the attributes it does nothing. Treat it as the enforcement half of a two-part adoption.Look elsewhere when:
readonly/final/visibility, or a proper module system.deptrac or phparkitect are the better fit; this package governs class-level access, not architectural layers.For executives (one paragraph): This is a small, free, MIT-licensed plugin that makes our architecture rules enforceable in CI rather than advisory. It costs nothing at runtime, adds no production dependency, and lets us stop paying for custom tooling and manual review to police which teams may use which classes. It directly supports our modularisation work: each boundary we declare becomes a measurable, shrinking list of exceptions instead of an unverifiable claim. The honest caveat is maturity — a single maintainer and a small user base — so we should treat it as a cheap, reversible experiment with a one-sprint spike, not a strategic bet. If it disappoints, we remove one line from CI config.
For engineering (one paragraph): Attributes are inert at runtime, so this adds zero production behaviour. The package is a PHPStan extension that validates php-language-extensions attributes — #[Internal], #[Friend], #[Pure], #[Immutable], #[NamedConstructor] — so the rules you write in code become PHPStan errors, using the CI step you already run. No new pipeline, no new tool for developers to learn. It complements rather than replaces deptrac: this covers class-level access ("who may call this"), deptrac covers layer-level direction ("what may depend on what"). Adopt in a spike: enable it, run it against one module, and measure the violation count before committing. Pin the version and expect a small maintenance touch on PHPStan major upgrades. It is straightforward to vendor or fork if the project stalls, given the license and small surface area.
Recommendation: Time-boxed pilot (one sprint) on a single bounded module, with success defined as: attribute enforcement running in CI, a baseline violation count, and a friend-declaration count we can trend. If the maintainer or PHPStan compatibility looks shaky at review, fall back to a handful of native PHPStan rules — but note that fallback costs more to build and maintain than this package does to adopt.
How can I help you explore Laravel packages today?