刀片模板中的多对多关系中的 Laravel 嵌套查询

Posted

技术标签:

【中文标题】刀片模板中的多对多关系中的 Laravel 嵌套查询【英文标题】:Laravel Nested Query in Many to Many Relationship from within Blade Template 【发布时间】:2020-11-08 14:23:45 【问题描述】:

我试图根据角色隔离不同的团队成员,在刀片视图的 $teams 中将它们过滤为 $team @foreach 循环。输出将是具有给定角色的团队成员的简单列表。几天来,我一直在网上寻找线索,我确信答案就在我面前——我只是还没有看到。理想情况下,我希望能够使 api 流在逻辑上,例如类似于以下内容:

$team->user->role('manager')

Team、User 和 Role 类之间的关系都是多对多的

团队.php

public function users()
    
        return $this->belongsToMany(User::class, 'team_user', 'team_id', 'user_id')->withTimestamps();
    

用户.php

    public function teams()
    
        return $this->belongsToMany(Team::class, 'team_user', 'user_id', 'team_id')->withTimestamps();
    

    public function roles()
    
        return $this->belongsToMany(Role::class, 'role_user', 'user_id', 'role_id')->withTimestamps();
    

角色.php

    public function users()
    
        return $this->belongsToMany(User::class, 'role_user', 'role_id', 'user_id')->withTimestamps();
    

管理员/TeamsController.php

    public function index()
    
        $teams = Team::with('users')->orderBy('location', 'asc')->paginate(10);

        return view('admin.teams.index')->with([
            'teams' => $teams,
        ]);
    

那么,为了在刀片视图中隔离给定团队的每个成员的角色,我们必须做些什么来加载这样的多个关系?


编辑以显示最终解决方案(来自下面@wschopohl 的强大输入):

在 Team.php 类中:

    public function userWithRole($role)
    
        return $this->users()->whereHas('roles', function ($query) use ($role) 
            $query->where('name', $role);
        )->with('roles')->get();
    

index.blade.php

@foreach ($teams as $team)
    <tr>
        <td class="px-4 py-2 border"> $team->location </td>
        <td class="px-4 py-2 border">
            @foreach ($team->userWithRole('lead') as $user)
                <li style="list-style: none;"> $user->name </li>
            @endforeach
        </td>
        <td class="px-4 py-2 border">
            @foreach ($team->userWithRole('manager') as $user)
                <li style="list-style: none;"> $user->name </li>
            @endforeach
        </td>
        <td class="px-4 py-2 border">
            @foreach ($team->userWithRole('somethingelse') as $user)
                <li style="list-style: none;"> $user->name </li>
            @endforeach
        </td>
    </tr>
@endforeach

【问题讨论】:

【参考方案1】:

这实际上比我想象的要复杂。

我现在能想到的最好的事情是:

$users = $team->users()->whereHas('roles', function($query) 
    $query->where('name', 'manager');
)->get();

当然,这很难用在刀片模板中。这就是为什么我会在 Team 模型上使用这样的方法

public function usersWithRole($role) 
    return $this->users()->whereHas('roles', function($query) use($role) 
        $query->where('name', $role);
    )->with('roles')->get();

所以现在您可以在刀片模板中执行以下操作:

@foreach($team->usersWithRole('manager') as $user)

【讨论】:

您的假设是正确的(角色表列称为“名称”),但是这条线(我之前已经尝试过很多次)产生:undefined method Illuminate\Database\Eloquent\Relations\BelongsToMany::roles() 似乎 eloquent 没有动通过与用户的团队关系一直到角色。这是近一周来让我陷入死胡同的部分。 尝试更新的答案,对不起,我现在无法测试自己 无需抱歉。我非常感谢您在这里的投入!这似乎有点进步,因为我现在得到:Trying to get property 'name' of non-object 我刚刚注意到您建议末尾的 ->get() 。当我添加它时,它爆发了:Column not found: 1054 Unknown column 'roles.name' in 'where clause' (SQL: select users.*, team_user.team_id` as pivot_team_id, team_user.user_id as pivot_user_id, team_user.pivot_created_at as pivot_created_at @, team_user.updated_at as pivot_updated_at from users inner join team_user on users.id = team_user.user_id 其中team_user.@107 和team_user.@98 987654348@.name = manager and users.deleted_at is null)`它似乎根本没有在探测角色表。 只是一个愚蠢的问题:你所有的关系都在运作,如果你一个一个地查询它们,对吧?

以上是关于刀片模板中的多对多关系中的 Laravel 嵌套查询的主要内容,如果未能解决你的问题,请参考以下文章

从laravel中的多对多关系中获取单列

如何通过 Laravel 中的多对多关系获取模型

php Laravel中的多对多关系来自一系列ID Raw

如何在Laravel中的多对多关系中添加“别名”?

如何在实例中有自定义 .update() 以更新 DRF 可写嵌套序列化程序中的多对多关系时更新值

Laravel 上的多对多问题关系