Eloquent generics #54590
Replies: 11 comments 1 reply
-
@calebdw you will probably have a good starting point on this |
Beta Was this translation helpful? Give feedback.
-
i suspect this is the related PR... |
Beta Was this translation helpful? Give feedback.
-
You need the generics on the input parameter: /**
* @param Builder<static> $query
* @return Builder<static>
*/
public function scopeSearch(Builder $query, ?string $search = null): Builder
{
return $query->whereHas('user', static function (Builder $query) use ($search): void {
$query->search($search);
});
} |
Beta Was this translation helpful? Give feedback.
-
Hi, I did that but now it says this:
|
Beta Was this translation helpful? Give feedback.
-
I have a Larastan PR to be able to detect the dynamic generic type: larastan/larastan#2048 It hasn't been merged yet but I've also published it on my fork if you'd like to check it out: https://github.com/calebdw/larastan |
Beta Was this translation helpful? Give feedback.
-
A few more notes:
All that said, something like this should work out of the box /**
* @param Builder<static> $query
* @return Builder<static>
*/
public function scopeSearch(Builder $query, ?string $search = null): Builder
{
$user = $query->getModel()->user();
return $query->whereHas($user, fn ($q) => $q->search($search));
} |
Beta Was this translation helpful? Give feedback.
-
Hi, I'll try it out later today and let you know.. thx! |
Beta Was this translation helpful? Give feedback.
-
HI, I tried the second approach that you mentioned and I managed to fix most of the problems. However, morph relations are still a problem. Given the example: public function item(): MorphTo
{
return $this->morphTo();
}
public function scopeAvailable(Builder $query): Builder
{
/**
* @var Builder<static> $query
*/
return $query->whereHas($query->getModel()->item(), static function (Builder $query): void {
$query->available();
});
}
It's the same when Builder generic is typed as a function input param. |
Beta Was this translation helpful? Give feedback.
-
/** @return MorphTo<Model1|Model2> */
public function item(): MorphTo
{
return $this->morphTo();
} however, you will have to manually ignore the warning that is produced by doing so. You might have better mileage using the return $query->whereHasMorph($query->getModel()->item(), [Model1::class, Model2::class], static function (Builder $query): void {
$query->available();
}); This however, will require the Larastan PR (or my fork) to be able to properly detect the builder type. This is not a framework issue, but just has to do with properly typing the generics in your code. This issue can be closed but feel free to open discussions at the Larastan repo if you have more questions---I'm happy to help 😃 |
Beta Was this translation helpful? Give feedback.
-
Thanks for the explanation. So you're saying that there's no way to properly type morphs for now? |
Beta Was this translation helpful? Give feedback.
-
Morphs are dynamic...how can you know what model it is and that is has the scope you're trying to call? You can always just manually ignore the PHPStan warning with |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Laravel Version
11.42.0
PHP Version
8.4.3
Database Driver & Version
No response
Description
Hi,
With the latest update we started to receive these errors.
This scope is a part of the trait that any model can use.
Steps To Reproduce
Copy this code in a trait and use it on some model.
Beta Was this translation helpful? Give feedback.
All reactions