我有3个表:user
, role
和pivot user_role
。用户和角色之间存在多对多关系。
还有一个细节,每个分配(角色到用户)在user_role
表中都有timestamp
,所以我可以找到最近为用户添加了什么角色。
是否有可能编写一个雄辩的查询,以获得所有用户,其中最近分配的角色有e.g. id = 5?
我需要以某种方式从timestamp
订购的pivot
中获得最后一条记录,然后在whereHas
语句中使用它。但是如何得到最后一张唱片呢?
编辑
谢谢你的回答。但我想让它更复杂一点。如果我们添加表system
,现在system
和user
之间是一对多的关系,这样用户可以属于一个系统,系统可以有多个用户。
现在,如何获得例如system
的id,其中包含用户的最后一个角色id = 5(如开始)。
首先,您需要确保您的关系包含枢轴时间戳:
public function users()
{
return $this->belongsToMany('User')->withTimestamps();
}
那么你可以在你的代码中使用下面的查询来获取最近接收了特定角色的所有用户(例如id=5)。
$role = Role::with(['users', function($query) {
$query->orderBy('pivot_created_at', 'DESC');
}])->find(5);
// all users with (role_id = 5) ordered by (user_role.created_at DESC)
$users = $role->users;
可以向关系中添加透视列,如下所示:
/**
* The roles that belong to the user.
*/
public function roles()
{
return $this->belongsToMany('App'Role')->withPivot('timestamp');
}
如果你想检查用户最近是否有一个特定的角色,我会这样做
public function hasRecentRole($roleId, $howRecently = 'last week')
{
return $this->roles()->where('id', $roleId)->wherePivot('timestamp', '>', new Carbon'Carbon($howRecently))->count();
}
EDIT:试着这样做。
$systems = System::whereHas('users', function ($query) {
$query->whereHas('roles', function ($query) {
$query->where('id', 5)
->whereRaw('timestamp = (select max(`timestamp`) from user_roles WHERE user_id = role_user.user_id'));
});
})->get();
如果没有,也许你应该一步一步地工作。例如获取最新角色5的用户,然后获取至少包含其中一个用户的系统
这给出了user_role
表中timestamp
列排序的最后一个用户。
$user->roles()->withPivot('timestamp')->orderBy('user_role.timestamp','desc')->first();
更新:
$users=User::with(['system','role'=>function($query)
{
$query->orderBy('pivot_timestamps','desc');
}])->get();
那么,这就给出了数据透视表中所有用户按时间戳排序的系统id。
foreach($users as $user)
{
$user->system->id;
}
确保您在用户和角色模型withPivot.
中有关系,以便您可以使用pivot_timestamps
return $this->belongsToMany('users')->withPivot('timestamps');