Laravel Blade 模板中多对多关系中的嵌套查询
Laravel Nested Query in Many to Many Relationship from within Blade Template
我正在尝试根据角色隔离不同的团队成员,在 blade 视图的 $teams 中将他们过滤为 $team @foreach 循环。输出将是具有给定角色的团队成员的简单列表。几天来我一直在网上搜索这方面的线索,我确信答案就在我面前——我只是还没有看到。理想情况下,我希望能够在逻辑上让 api 流动,例如类似于以下内容:
$team->user->role('manager')
Team、User、Role的关系class都是many-to-many
Team.php
public function users()
{
return $this->belongsToMany(User::class, 'team_user', 'team_id', 'user_id')->withTimestamps();
}
User.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();
}
Role.php
public function users()
{
return $this->belongsToMany(User::class, 'role_user', 'role_id', 'user_id')->withTimestamps();
}
Admin/TeamsController.php
public function index()
{
$teams = Team::with('users')->orderBy('location', 'asc')->paginate(10);
return view('admin.teams.index')->with([
'teams' => $teams,
]);
}
那么,为了在 blade 视图中隔离给定团队的每个成员的角色,人们必须做些什么来加载像这样的多个关系?
编辑以显示最终解决方案(下面来自@wschopohl 的强大输入):
在Team.php class:
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
这实际上比我想象的要复杂。
我现在能想到的最好的事情是:
$users = $team->users()->whereHas('roles', function($query) {
$query->where('name', 'manager');
})->get();
当然,在 blade 模板中使用这很丑陋。这就是为什么我会在 Team
模型
上使用这样的方法
public function usersWithRole($role) {
return $this->users()->whereHas('roles', function($query) use($role) {
$query->where('name', $role);
})->with('roles')->get();
}
所以现在在您的 blade 模板中您可以:
@foreach($team->usersWithRole('manager') as $user)
我正在尝试根据角色隔离不同的团队成员,在 blade 视图的 $teams 中将他们过滤为 $team @foreach 循环。输出将是具有给定角色的团队成员的简单列表。几天来我一直在网上搜索这方面的线索,我确信答案就在我面前——我只是还没有看到。理想情况下,我希望能够在逻辑上让 api 流动,例如类似于以下内容:
$team->user->role('manager')
Team、User、Role的关系class都是many-to-many
Team.php
public function users()
{
return $this->belongsToMany(User::class, 'team_user', 'team_id', 'user_id')->withTimestamps();
}
User.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();
}
Role.php
public function users()
{
return $this->belongsToMany(User::class, 'role_user', 'role_id', 'user_id')->withTimestamps();
}
Admin/TeamsController.php
public function index()
{
$teams = Team::with('users')->orderBy('location', 'asc')->paginate(10);
return view('admin.teams.index')->with([
'teams' => $teams,
]);
}
那么,为了在 blade 视图中隔离给定团队的每个成员的角色,人们必须做些什么来加载像这样的多个关系?
编辑以显示最终解决方案(下面来自@wschopohl 的强大输入):
在Team.php class:
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
这实际上比我想象的要复杂。
我现在能想到的最好的事情是:
$users = $team->users()->whereHas('roles', function($query) {
$query->where('name', 'manager');
})->get();
当然,在 blade 模板中使用这很丑陋。这就是为什么我会在 Team
模型
public function usersWithRole($role) {
return $this->users()->whereHas('roles', function($query) use($role) {
$query->where('name', $role);
})->with('roles')->get();
}
所以现在在您的 blade 模板中您可以:
@foreach($team->usersWithRole('manager') as $user)