packagist psalm/plugin-laravel v4.13.0
v4.13.0 - Named Scopes

latest release: v3.13.0
5 hours ago

What’s Changed

This release brings names scope support into a brand new level!

  • #1032 — Instance scope calls on Builder resolve to Builder<Model> instead of mixed
    Customer::query()->active() now returns Builder<Customer>; arguments are type-checked against the scope's declared params (minus the leading $query). Covers both legacy scopeXxx() and #[Scope]-attributed methods on the base builder.

  • #1033 — Scope self/static parameters pin to the correct class
    Scope params typed self resolve to the trait's composing class (not the queried subclass), and static/$this resolve to the queried model. Eliminates false-positive InvalidArgument when a sibling child is passed to a trait-hosted scope.

  • #1034 / #1036 — Direct scope calls use the real method signature
    Calling a #[Scope] method directly ($this->otherScope($query, ...) or any accessible bare-name call) no longer shifts arguments left or fabricates Builder<Model> as the return type. The isDirectScopeCall classifier decides by PHP dispatch semantics, not argument shape — nullable ?Builder, variadic scopes, non-variable expressions all classify correctly.

  • #1039 — Variadic and named-arg scope calls work on forwarded path
    A scope with a variadic tail keeps its variadic flag after $query is stripped; zero-arg calls are valid and extra args don't draw TooManyArguments.

  • #1039 — Scope names that collide with real Eloquent\Builder methods no longer mask the real return type
    Model::query()->find(1) now correctly returns Model|null even when scopeFind() exists on the model. Names that route through __call (like count/sum passthru aggregates) remain scope-eligible.

  • #1031 / #1043 — Trait-hosted scope self resolves to the composing class, not the subclass (behavior change: InvalidArgument message shifts from the queried child to the abstract parent when the trait is composed on a parent)
    Querying Contract::query()->rankedAbove($receipt) — where Contract inherits ComparesRank from its abstract parent — now accepts sibling children instead of rejecting them with a false positive.

  • Consume-once hand-off for scope params (#1042)
    A scope call on one model no longer leaks its zero-arg signature into a subsequent same-named SoftDeletes macro call on a different model.

  • SuppressHandler correctly treats private #[Scope] methods as unused (not silenced as scope entry points).

Full Changelog: v4.12.4...v4.13.0

Don't miss a new plugin-laravel release

NewReleases is sending notifications on new releases.