Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Phpstan Rules Laravel Package

rector/phpstan-rules

PHPStan rules for Rector projects that catch common mistakes in Rector rules and configuration, helping you keep automated refactorings safer and more consistent. Use these ready-made checks to validate custom rules and configs before they rewrite your codebase. Ideal for teams maintaining custom Re...

View on GitHub
Deep Wiki
Context7

Getting Started

This is a narrow, opinionated package: it ships PHPStan rules that encode Rector's own design conventions and its static-reflection discipline. It is not a general-purpose rule pack for application code — it exists so that Rector core and third-party Rector extension packages stay consistent.

Minimal setup:

composer require --dev rector/phpstan-rules

If phpstan/extension-installer is allowed in your project, the rules register automatically. Otherwise include the config manually:

# phpstan.neon
includes:
    - vendor/rector/phpstan-rules/config/config.neon

Where to look first:

  1. vendor/rector/phpstan-rules/src/Rules/ — every rule is a small, readable class; this is the real documentation.
  2. vendor/rector/phpstan-rules/config/ — the registration file shows the exact service IDs to reference or exclude.
  3. Rector's own phpstan.neon in the rectorphp/rector repository — canonical real-world usage.

First use case: you maintain a Rector rule package (or a project with custom AbstractRector subclasses). Point PHPStan at that directory and let the package enforce two things:

  • Static reflection: no new \ReflectionClass(...), \ReflectionMethod, etc. Rector analyses source that may not be autoloadable, so reflection must go through PHPStan's ReflectionProvider / Scope.
  • Rule design: every rule declares getNodeTypes(), returns Node|null from refactor(), is stateless/final, and doesn't reach for Rector config or getName()-style shortcuts.

A baseline-level phpstan.neon for a rule package:

includes:
    - vendor/rector/phpstan-rules/config/config.neon
    - vendor/phpstan/phpstan-strict-rules/rules.neon

parameters:
    level: 8
    paths:
        - src
        - rules

Run vendor/bin/phpstan analyse and treat the first output as an inventory of legacy patterns, not as errors to silence one by one.

Implementation Patterns

Scope rules by path, not by disabling them. The reflection rules belong on src/Rules/** (where Rector code lives); the design rules belong on the same tree. If you have non-Rector code in the same PHPStan run, use per-path includes in separate config files and analyse each in its own PHPStan invocation rather than excluding rule classes globally.

Layer configs per package stage. A common layout:

  • phpstan.neon — base, strict rules, level
  • phpstan-rector.neon — includes rector/phpstan-rules, paths limited to rule directories
  • phpstan-baseline.neon — only for pre-existing debt, regenerated via --generate-baseline

Wire it into CI as a separate job. Because these rules are structural, they fail fast and cheaply; running them alongside (not inside) your unit-test matrix keeps signal clear:

- run: composer install --no-interaction
- run: vendor/bin/phpstan analyse -c phpstan-rector.neon --no-progress --error-format=github

Model your own rules on the shipped ones. When you need a house rule ("every rule must be final", "no ContainerInterface in a rule"), open the closest rule in src/Rules/, copy its shape (implements Rule, getRuleDefinition(), processNode(Node, Scope)), and register it in your own services block. The package doubles as a worked example of the Rule API.

Migrate reflection incrementally. Replace new ReflectionClass($fqcn) with $scope->getClassReflection($fqcn) or the injected ReflectionProvider one call site at a time, running PHPStan after each; the rule messages name the offending line, so the loop is tight. Keep reflectionProvider->hasClass() guards near the call site rather than centralising them.

Test custom rules with PHPStan's own harness. Use PHPStan\Testing\RuleTestCase and construct the container (or StaticReflectionProvider) explicitly — the package's reflection rules assume a container is present, and your tests must mirror that.

Gotchas and Tips

  • It is not a general PHPStan pack. Rules are keyed to Rector interfaces (AbstractRector, RectorConfig, the Rule contract). Applied to a Laravel or Symfony app, you will get false positives. Scope paths aggressively or don't install it there at all.
  • It often arrives transitively. rector/rector pulls this in as a dev dependency; you may already have it under vendor/. Check before adding a duplicate requirement — and expect the bundled version to move with Rector majors.
  • PHPStan version coupling. The static-reflection API (ReflectionProvider, ClassReflection, ExtendedMethodReflection) has shifted signatures across PHPStan majors. Pin phpstan/phpstan and this package together, and re-run after any PHPStan bump before trusting a green build.
  • Static reflection ≠ native reflection in tests. Native ReflectionClass works on test fixtures; ReflectionProvider needs a configured container and autoload map. Fixtures that pass under native reflection can silently resolve to null class reflections in tests — assert on hasClass() before getClass().
  • Don't baseline structural rules. Baselines hide exactly the drift these rules catch; a baselined "missing getNodeTypes()" will stay missing. Fix or exclude the path.
  • Include order matters if you also load phpstan-strict-rules or phpstan-deprecation-rules; duplicate service IDs produce confusing "service already registered" errors. Let extension-installer handle registration when possible.
  • Debugging false positives: run with -v --debug, then check whether the rule is path-scoped correctly. Excluding a rule by class name is a last resort — prefer narrowing paths.
  • Extension points: the practical one is authorship, not configuration. Write your own Rule implementations that follow the shipped conventions; the package gives you the pattern vocabulary (getRuleDefinition() with a code sample, getNodeTypes(), stateless refactor()), not a plugin surface.
  • Version pinning: given zero direct dependents and a fast-moving upstream, pin to a Rector-compatible tag rather than dev-main, and revisit on each Rector upgrade.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect