I have a projects table that either can be assigned to a user or a team, this is the structure:
id
assignable_id
assignable_type
class Project extends Model {
public function assignable(): MorphTo
{
return $this->morphTo();
}
}
and my team table contains members with a pivot table:
id
class Team extends Model {
public function users(): BelongsToMany
{
return $this->belongsToMany(User::class);
}
public function projects(): MorphMany
{
return $this->morphMany(Project::class, 'assignable');
}
}
// team_user table
team_id
user_id
and finally my user table:
id
class User extends Model {
public function teams(): BelongsToMany
{
return $this->belongsToMany(Team::class);
}
public function projects(): MorphMany
{
return $this->morphMany(Project::class, 'assignable');
}
}
Now the problem is I want to get all projects that have been assigned to a user either directly or through a team, as expected $user()->projects return the ones that directly have been assigned to the user.
I tried many solutions but none has worked for me yet.
So you actually need something like this:
public function project()
{
return $this->hasManyThrough('App\Project', 'App\User', 'assignable_id')
->where(
'assignable_type',
array_search(static::class, Relation::morphMap()) ?: static::class
);
}
or
public function project()
{
return $this->belongsToMany(Project::class, 'assignable', 'assignable_id', 'project_id')
->where('assignable_type', static::class);
}
Ref: Laravel Polymorphic Relations Has Many Through
Your working solution:
public function projects() {
return $this->hasManyThrough(
Project::class,
User::class,
'id',
'assignable_id',
)->where(
'assignable_type', User::class
)->orWhere(function ($q) {
$q->where('assignable_type', Team::class)
->whereIn('assignable_id', $this->teams->pluck('id'));
});
}