Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eloquent with #17

Open
makroxyz opened this issue Sep 17, 2024 · 5 comments
Open

Eloquent with #17

makroxyz opened this issue Sep 17, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@makroxyz
Copy link

makroxyz commented Sep 17, 2024

  • Larastan Version: 2.10.8
  • Laravel Version: 11.23.*

Description

Starting from Laravel 11.23.* the following error

Parameter 1 $relations of method Illuminate\Database\Eloquent\Builder<Domain\Monitor\Models\MonitorResource>::with() expects array<array|(Closure(Illuminate\Database\Eloquent\Relations\Relation<*, *, *>):  mixed)|string>|string, array{monitorable: Closure(Illuminate\Database\Eloquent\Relations\MorphTo): void} given

Laravel code where the issue was found

$resources = Resource::whereIn('resource_id', $requestResources)
    ->with([
        'monitorable' => function (MorphTo $morphTo) {
             $morphTo->morphWith([
                 Service::class => [
                     'relation1',
                     'relation2',
                 ],
             ]);
          },
     ]);
@makroxyz makroxyz added the bug Something isn't working label Sep 17, 2024
@calebdw
Copy link
Owner

calebdw commented Sep 17, 2024

Hello!

Thanks for your report, however, this is expected as closure parameter types are invariant. See:

I thought this would be fine since most methods you need are defined on the Relation but morphWith is only defined on the MorphTo relation so you do need to type it.

I'll open an issue with PHPStan to see if there's a way to solve this problem. In the meantime you can override the type inside the closure:

$resources = Resource::query()
    ->whereIn('resource_id', $requestResources)
    ->with([
        'monitorable' => function ($morphTo) {
             /** @var MorphTo $morphTo */
             $morphTo->morphWith([
                 Service::class => ['relation1', 'relation2'],
             ]);
          },
     ]);

@makroxyz
Copy link
Author

Sorry, but workaround doesn't work...

PHPDoc tag @var for variable $morphTo contains generic class Illuminate\Database\Eloquent\Relations\MorphTo but does not specify its types: TRelatedModel, TDeclaringMode

@calebdw
Copy link
Owner

calebdw commented Sep 18, 2024

So then use:

/** @var MorphTo<*, *> $morphTo */

@vixducis
Copy link

I understand the workaround but changing native PHP types to docblocks hampers type checking at runtime and strongly reduces readability (at least in my opinion). This occurs hundreds of times in my codebase, making it a considerable time investment to change the types (and to change them back once this has been resolved).

Is there any option to stub this out until a definite solution is conceived?

@calebdw
Copy link
Owner

calebdw commented Nov 14, 2024

@vixducis, you can just create a regex ignore rule that matches on Builder, ::with\(, MorphType, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants