1

我有一个可以分配给用户或团队的项目表,这是结构:

id
assignable_id
assignable_type

class Project extends Model {
    public function assignable(): MorphTo
    {
        return $this->morphTo();
    }
}

我的团队表包含带有数据透视表的成员:

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

最后是我的用户表:

id

class User extends Model {

    public function teams(): BelongsToMany
    {
        return $this->belongsToMany(Team::class);
    }

    public function projects(): MorphMany
    {
        return $this->morphMany(Project::class, 'assignable');
    }
}

现在的问题是我想直接或通过团队获取已分配给用户的所有项目,正如预期的那样 $user()->projects 返回直接分配给用户的项目。

我尝试了很多解决方案,但没有一个对我有用。

4

2 回答 2

1

使用whereHasMorph

$user = ...

$projects = Project::whereHasMorph(
    'assignable',
    [Team::class, User::class],
    function ($query, $type) use($user) {
        if($type === Team::class){
            $query->whereRelation('users', 'id', $user->id);
        }else{
            $query->where('id', $user->id);
        } 
    }
)->get();

或拆分为 2 个查询并合并在一起:

$projects = $user->projects;
$teams = $user->teams()->with('projects')->get();
$teams_projects = $teams->pluck('projects')->collapse();
$projects = $projects->merge($teams_projects);
于 2022-02-13T13:10:27.880 回答
1

所以你实际上需要这样的东西:

public function project()
{
    return $this->hasManyThrough('App\Project', 'App\User', 'assignable_id')
        ->where(
            'assignable_type', 
            array_search(static::class, Relation::morphMap()) ?: static::class
        );
}

或者

public function project()
{
    return $this->belongsToMany(Project::class, 'assignable', 'assignable_id', 'project_id')
        ->where('assignable_type', static::class);
}

参考:Laravel 多态关系有很多通过

您的工作解决方案:

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'));
    });
}
于 2022-02-13T11:10:39.733 回答