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

lychee-org/phpstan-lychee

PHPStan extension for Lychee that adds custom rules, stubs, and type information to improve static analysis of Lychee-based Laravel applications. It helps catch Lychee-specific errors earlier, enforce coding standards, and keep analysis consistent across projects.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a PHPStan ruleset, not an application package — the only thing it does for you is add custom rules to an existing PHPStan setup. Install it as a dev dependency and include its config file; there is nothing to boot, register in a service provider, or publish.

composer require --dev lychee-org/phpstan-lychee

First, look at what you actually got — the neon file name and the rule list are the whole API surface:

ls vendor/lychee-org/phpstan-lychee/
cat vendor/lychee-org/phpstan-lychee/*.neon
ls vendor/lychee-org/phpstan-lychee/src/Rules   # rule classes + identifiers

Then include it from your project's phpstan.neon (or phpstan.neon.dist):

includes:
    - vendor/lychee-org/phpstan-lychee/extension.neon
    # likely also: rules.neon / config/extension.neon — use whatever ships

Run your normal analysis:

vendor/bin/phpstan analyse --memory-limit=1G

First use case: run it as a diff against your existing config before committing. Add the include on a branch, run PHPStan, and count how many new errors appear. If the count is large, you'll want a baseline segment (see below) rather than fixing everything at once. Check whether the rules are scoped to namespaces that exist in your repo — a Lychee-specific ruleset may assume Lychee\ namespaces and silently do nothing (or mis-fire) in a differently-namespaced project.

Implementation Patterns

Separate the ruleset into its own include. Keep your base config clean so you can toggle the package on/off in CI or in a legacy subdirectory:

# phpstan-lychee.neon
includes:
    - vendor/lychee-org/phpstan-lychee/extension.neon
# phpstan.neon
includes:
    - phpstan-base.neon
    - phpstan-lychee.neon     # delete this line to opt out

Scope with paths per rule set. If only part of the codebase is expected to comply (new modules, app/Domain, etc.), give the strict config its own paths and run it as a second PHPStan invocation rather than bending the global rule level.

Use rule identifiers for surgical ignores. Custom rules ship an identifier (visible in the error output in parentheses, e.g. (Lychee.SomeRule), or readable from the getRuleIdentifier()/RuleErrorBuilder calls in the rule source). Ignore by identifier, never by message text — messages change between releases:

ignoreErrors:
    - identifier: Lychee.SomeRule
      path: src/Legacy/*

Wire into CI as a gate, with a baseline for the backlog. This is the pattern that actually sticks:

vendor/bin/phpstan analyse --configuration=phpstan.neon --error-format=github

Generate the initial baseline once, commit it, and treat "no new baseline entries" as the review rule:

vendor/bin/phpstan analyse --generate-baseline

Pair it with Larastan/larastan for Laravel repos. Load order matters: put your framework config first, then this package, so the Lychee rules see accurate types from the Laravel extension (model property types, facade return types, etc.). A custom rule that inspects an Eloquent model is only as useful as the type information reaching it.

Treat it as an architecture guardrail. The day-to-day value in a ruleset like this is usually enforcing a house convention — strict types declared, no env() outside config, enums instead of magic constants, controller/model boundaries. Those are the rules you want to fail early, so run PHPStan in a pre-push hook alongside Pint/PHP-CS-Fixer to keep feedback local:

"scripts": {
    "lint:php": ["pint --test", "phpstan analyse --memory-limit=1G"]
}

Gotchas and Tips

Rule inclusion is the entire integration. There's no config/app.php entry and no service provider. If you see no new errors after including, the include path is almost certainly wrong, or the rules are namespace-scoped and your code doesn't match. Verify with phpstan analyse -v and confirm the extension is listed, and temporarily write a deliberate violation that a rule should catch.

Version-couple PHPStan deliberately. PHPStan's Rule interface and RuleErrorBuilder API have moved across major versions (notably the 1.x → 2.x line). With a ruleset this small and niche (1 star, 0 dependents), expect it to track a narrow PHPStan range. Pin both, and let Composer's conflict resolution — not hope — tell you if they disagree:

composer why-not phpstan/phpstan ^2.0

If you're on PHPStan 2.x and the package requires 1.x (or vice versa), you'll get rules that load but never fire, or a hard class-not-found. Don't fight it; check the package's own composer.json constraints first.

reportUnmatchedIgnoredErrors will bite you. When a custom rule is renamed or removed between releases, your identifier-scoped ignoreErrors entries become unmatched and the build fails. Keep the default (true) because that's the signal you want, but budget time for cleanup on every bump of this package — that's the real upgrade cost.

--generate-baseline can swallow your new rules. Generating a baseline after adding this package lumps every new error into phpstan-baseline.neon, where it's invisible in review. Generate the baseline first, then add the include, then look at the real diff. Otherwise you've paid for the ruleset and get zero signal.

Custom rules can't see what PHPStan can't infer. Most surprising "this rule never fires" bugs are typing problems, not rule bugs. Check with vendor/bin/phpstan analyse --debug or a temporary dumpType() — if a model property is mixed, the rule has nothing to reason about. Loading Larastan or adding @property docblocks usually fixes it.

Read the rule sources; that's the documentation. At this size there is unlikely to be thorough docs, and rule behavior is often configurable through neon parameters. Grep for parameters: in the shipped neon and for %...% interpolation in src/ to find tunables:

grep -rn "parameters:" vendor/lychee-org/phpstan-lychee/*.neon
grep -rn "%" vendor/lychee-org/phpstan-lychee/src --include=*.php | head -30

Fork-and-own is a legitimate strategy here. With a single-digit star count and no dependents, maintenance risk is the main concern. Because the extension surface is a handful of Rule classes plus a neon file, vendoring the rules into your own tools/phpstan/ directory (or a replace in composer.json) is cheap insurance and lets you adjust messages and thresholds to your codebase. Do that as soon as you find yourself writing ignoreErrors for the same identifier more than a couple of times — you're fighting the rule instead of using it.

Memory and parallelism. Custom rules that walk the AST over a large Laravel codebase push PHPStan past the default memory limit and can be slow. Set --memory-limit=1G (or higher) in CI and the composer script so failures are real rule violations, not OOM kills that look like timeouts.

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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package