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 Laravel Laravel Package

calebdw/phpstan-laravel

A PHPStan extension for Laravel that teaches static analysis about Laravel’s magic, including facades, helpers, Eloquent models, and container bindings, reducing false positives and surfacing more accurate type errors in Laravel apps.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the extension as a dev dependency alongside PHPStan:

composer require --dev calebdw/phpstan-laravel phpstan/phpstan

Register it in your phpstan.neon (or phpstan.neon.dist):

includes:
    - vendor/calebdw/phpstan-laravel/extension.neon

parameters:
    level: 5
    paths:
        - app
        - routes
        - config

If the package ships a bootstrap helper, point PHPStan at a Laravel-aware bootstrap so the container, facades, and config are available during analysis:

parameters:
    bootstrapFiles:
        - bootstrap/phpstan.php

That bootstrap should boot the application (or at least register the service providers and aliases the extension needs) without hitting the database or external services.

Where to look first:

  1. The package README for the exact includes path and any required bootstrap convention — extension names and paths differ between releases.
  2. vendor/calebdw/phpstan-laravel/extension.neon to see what rules and services are registered.
  3. Any shipped rules.neon, config.neon, or stubs directory for Laravel-specific type definitions.

First use case: run analysis on the smallest meaningful slice before widening scope.

vendor/bin/phpstan analyse app/Models app/Http/Controllers --memory-limit=1G

Start by confirming that facade calls, Eloquent model properties, and app()/container resolutions produce useful types. If they do, the extension is wired correctly; if everything is mixed, the bootstrap or includes are usually the problem.

Implementation Patterns

Adopt incrementally with a baseline. Run at a low level on a small path, generate a baseline, then raise the level and shrink the baseline over time:

vendor/bin/phpstan analyse --generate-baseline

Scope analysis per directory in monorepos. Laravel applications and packages have different bootstrapping needs. Use separate config files:

# packages/billing/phpstan.neon
includes:
    - ../../vendor/calebdw/phpstan-laravel/extension.neon

parameters:
    level: 6
    paths:
        - src
        - tests
    bootstrapFiles:
        - tests/phpstan-bootstrap.php

Then run vendor/bin/phpstan analyse -c packages/billing/phpstan.neon.

Use it in CI with a fixed PHPStan version and cache warmup. A typical job:

- run: composer install --no-interaction --prefer-dist
- run: vendor/bin/phpstan analyse --no-progress --error-format=github

Pin phpstan/phpstan and the extension to compatible major versions in composer.json; PHPStan extensions are tightly coupled to PHPStan internals.

Pair static analysis with Laravel-specific tests. The extension catches type errors, but not runtime container misconfigurations. Keep feature tests for bindings and use PHPStan to catch signatures, nullability, and dead code around them.

Layer custom rules on top. The extension handles framework typing; project conventions (e.g., “controllers must not call repositories directly”) belong in custom PHPStan\Rules\Rule implementations registered in your own neon file. This keeps framework noise separate from domain rules.

Use it for package development. For a Laravel package, analyze src/ with the package’s own service provider registered in a test bootstrap. This catches missing illuminate/* dependencies and incorrect facade/container assumptions that only appear when the package is installed in a host app.

Combine with strict parameters deliberately. Enable checkMissingIterableValueType, checkGenericClassInNonGenericObjectType, and treatPhpDocTypesAsCertain only after the codebase is clean at the current level. Turning them on early produces a wall of framework-related errors that obscures real issues.

Gotchas and Tips

  • Facade and container types depend on bootstrapping. If Auth::user() or app(Foo::class) resolves to mixed, the extension likely isn’t seeing your providers. Fix the bootstrap before adding ignores.
  • Never boot the full HTTP kernel in analysis bootstrap. Avoid middleware, sessions, and database connections. Register providers and aliases only; otherwise PHPStan becomes slow and flaky in CI.
  • Performance and memory. Laravel bootstrap plus a large model graph is memory-hungry. Use --memory-limit=1G or higher, enable resultCachePath, and avoid analyzing storage/, bootstrap/cache/, and generated files.
  • Stale result cache after config changes. If errors appear or disappear inexplicably after changing phpstan.neon, the bootstrap, or the extension version, clear tmpDir/result cache before debugging further.
  • Version alignment is the most common failure mode. Mismatched PHPStan major versions usually surface as container or extension.neon errors at startup, not as analysis errors. Check composer why-not phpstan/phpstan when the extension won’t load.
  • Dynamic Eloquent properties are inferred, not guaranteed. Accessors, casts defined at runtime, and $appends may still need @property annotations. Use model PHPDoc as the source of truth where inference falls short.
  • Macros and runtime extensions are invisible. Builder::macro, custom collection macros, and dynamic facade methods generally require stubs or @method annotations. Add a small stub file and include it via scanFiles rather than suppressing errors globally.
  • Beware IDE helper files. _ide_helper.php and _ide_helper_models.php can conflict with extension-provided stubs or duplicate symbol definitions. Exclude them from paths and scanDirectories unless the extension explicitly expects them.
  • Config values are typed loosely. config('foo.bar') often returns mixed; use Config::get() with a cast or a typed config class when you need precise types. Don’t expect the extension to validate config keys.
  • Prefer targeted ignores over broad ones. Ignore by message and path, not by identifier alone, and document each ignore with a comment explaining the framework limitation.
  • Extension points: custom rules, stub files (stubFiles), and a project bootstrap are the supported levers. If you need new framework inference, check whether the package exposes a service you can decorate before forking it.
  • Release cadence is a risk signal. With a small project, pin exact versions and read the changelog before upgrading; test the upgrade in CI on a branch before rolling it across a monorepo.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console