Skip to content

Support static calls to #[Scope] attribute methods #634

@alies-dev

Description

@alies-dev

Problem

When a model method has the #[Scope] attribute, Laravel handles static calls via Model::__callStatic()query()Builder::__call()callNamedScope(). So Post::popular() works at runtime.

However, Psalm sees popular() as a real instance method and reports InvalidStaticInvocation before any plugin handler gets a chance to intercept. This is a false positive.

#[Scope]
public function popular(Builder $query): void { ... }

Post::popular(); // ❌ InvalidStaticInvocation — works at runtime
Post::query()->popular(); // ✅ Fixed in #633

Legacy scopes (scopeActivePost::active()) work because active() doesn't exist as a real method — the plugin's existence handler confirms it. #[Scope] methods are different because they exist as real instance methods.

Suggested fix

Implement BeforeAddIssueInterface to suppress InvalidStaticInvocation for #[Scope] methods on Model subclasses. The detection logic already exists in BuilderScopeHandler::hasScopeMethod().

~40 lines in a new handler + registration in Plugin.php + test updates.

Context

Discovered during #633. Currently documented as a known limitation in both CustomQueryBuilderTest.phpt and ModelStaticBuilderMethodsTest.phpt.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions