php-static-analysis/attributes
PHP attributes that let you annotate classes, methods, and properties with metadata for static analysis tools, improving type inference, purity checks, and IDE support. Lightweight, framework-agnostic, and easy to drop into existing codebases.
Architecture fit. This is a declarative-only package: a set of PHP 8 attribute classes that carry metadata consumed by static analysis tooling rather than by the runtime. That makes it architecturally almost weightless — no service provider, no container bindings, no request lifecycle hooks, no config surface. The trade-off is that it also delivers no functionality on its own. Its entire value is contingent on (a) your analyzer — PHPStan, Psalm, or a vendor-specific tool — actually recognising the specific attributes shipped, and (b) your team writing annotations that are true. Treat it as a dev-dependency that improves the signal quality of an existing analysis gate, not as a capability you are adding to the application. For a Laravel codebase the natural home is domain and service-layer classes where invariants (purity, immutability, side-effect freedom) are otherwise only expressible in docblocks.
Integration feasibility. Mechanically trivial: a single composer require --dev, PHP 8.1+ (attributes require PHP 8.0, the package likely targets 8.1+), and zero application code changes to install. Real effort sits downstream — you must confirm which attributes your analyzer version honours, whether the package ships companion extensions/rules or only marker classes, and then actually apply them across the codebase. Budget the work as a refactoring and code-review initiative, not a dependency install. A pilot on one bounded module will answer the recognition question in a day; the rollout across a mature Laravel application is measured in engineer-weeks.
Technical risk. Low blast radius, meaningful confidence risk. The dangerous failure mode is not a broken build — it is a silently ignored attribute: the annotation looks like an enforced guarantee but the analyzer never reads it, so reviewers relax scrutiny for no benefit. The inverse is worse: a wrong attribute (marking a method pure when it logs or mutates) suppresses exactly the findings you installed the tool to catch. Secondary risks are organisational: 94 stars and an unknown repository suggests a small maintainer base and possible single-maintainer bus factor; the 0.47 score argues for due diligence before making it a load-bearing part of your CI contract. Licence is MIT, so forking is a viable escape hatch.
Key questions.
@phpstan-pure, @psalm-immutable) or with Psalm's own attribute namespace? Is the migration path to native equivalents documented?Stack fit. Framework-agnostic and version-tolerant: it should install cleanly alongside Laravel 9–12 on PHP 8.1+, with no conflict against framework internals because it adds no runtime surface. Confirm the PHP constraint against your lowest-supported runtime before committing, since a --dev package with a tight PHP floor will break CI on legacy matrix legs even though production is unaffected.
Migration path. No data migration and no cutover — adoption is purely additive and reversible by removing the dependency and the annotations. The one-way door is cultural: once reviewers internalise "the attribute says it's pure," removing the attributes later feels like a regression even if they were never enforced. Prefer the analyzer's native annotations where they exist and reserve this package for the gaps.
Compatibility. Two axes to validate in a spike: analyzer version compatibility (attribute recognition is typically implemented in the analyzer, so the package's value is bound to your PHPStan/Psalm version, not its own) and coexistence with existing docblock annotations. Run the pilot with --level held constant so you can attribute any new findings to the package rather than to a config change.
Sequencing.
Maintenance. Near-zero ongoing effort in the good case — a composer update a few times a year, provided the package keeps pace with PHP and analyzer releases. The real maintenance load is the human kind: annotations rot when the code beneath them changes, and nothing fails loudly when they do. Assign ownership of the attribute vocabulary to one team so it does not drift into per-developer dialects.
Support. Assume community-only support with no SLA and an unknown maintainer. Given MIT licensing and the small surface area (attribute class definitions), the pragmatic contingency is vendoring or forking — a two-hour exercise, which materially de-risks the adoption decision. Escalate the decision to architecture review only if the package becomes a required part of the merge gate.
Scaling. No runtime scaling implications whatsoever — zero cost per request, zero memory footprint, no effect on queue or worker behaviour. CI is the only place it scales, and only linearly: stricter analysis raises build time modestly. On a large monorepo, scope the analyzer to changed paths to keep pipeline latency flat.
Failure modes.
Ramp-up. Low technical ramp-up, moderate discipline ramp-up. Any PHP developer understands attributes within an hour; the harder skill is knowing which invariants are worth asserting and how to prove them. Plan a single brown-bag session, a short written guideline in the repo, and one exemplar module that demonstrates both correct use and the analyzer catching a violation — that exemplar does more for adoption than any amount of documentation.
How can I help you explore Laravel packages today?