I use a polymorphic relationship, where the subject (morphTo()) may have various relationships (so they are not the same on each one of them). Their existence depends on morphed model.
I need to retrieve related models.
whereHas() won't help, because ones without particular relationship would be missing.
with() won't work either, because given relationship doesn't always exist, so it would throw an error on models where the relationship isn't defined.
Now, I am almost sure there is now way around it, because when you think about it, Laravel doesn't know of what type the morphed object is. That information is stored in the DB (object is defined by [whatever]able_type and [whatever]able_id). So the only way to find out is to look it up in DB. And that's a query.
But that's maybe just my limited mind, and I know you guys probably know better. It wouldn't be my first time with Laravel when I thought it's impossible/beyond framework's edge, just to find out it's perfectly possible and even pretty common + well documented :).
Here's some example code for better understanding:
<?php
...
class Post extends Model
{
/**
* Get all of the post's comments.
*/
public function comments()
{
return $this->morphMany('App\Comment', 'commentable');
}
/**
* This relationship is available for Post model only
*/
public function relationA()
{
// return $this->hasMany(...);
}
}
class Video extends Model
{
/**
* Get all of the video's comments.
*/
public function comments()
{
return $this->morphMany('App\Comment', 'commentable');
}
/**
* This relationship is available for Video model only
*/
public function relationB()
{
// return $this->hasMany(...);
}
}
class Comment extends Model
{
/**
* Get all of the owning commentable models.
*/
public function commentable()
{
return $this->morphTo();
}
public static function feed()
{
return self::with('commentable')
->withIfExists(['commentable.relationA', 'commentable.relationB'])
// ...
->get();
}
public function scopeWithIfExists($query, $relations = [])
{
// There is likely no way to implement such a scope
// in order to reduce number of queries by eager loading relations
// as we don't know of what type the subject is
// without looking it up in database
// I'll be very thankful if you could prove I am wrong
}
}