Laravel Spatie获取带角色用户异常:仅返回单个用户的解决问询
问题
我尝试创建视图以表格形式展示系统中的用户及其角色,但系统内明明有1个超级管理员和多个管理员,查询却仅返回1个用户。以下是我使用的后端查询代码:
$data = User::join('model_has_roles','model_has_roles.model_id','users.id') ->join('roles','model_has_roles.role_id','roles.id') ->join('user_profiles','user_profiles.user_id','users.id') ->select('users.id', 'title', DB::raw("CONCAT(user_profiles.fname, ' ', user_profiles.mname,' ', user_profiles.sname) As name"), 'email', 'gender', 'roles.name As role') ->where('roles.id',8)->orWhere('roles.id',9) ->get();
我怀疑第一个join操作导致了问题,但不确定。因为用的是服务端DataTables,我还尝试在前端处理角色字段:
..., { data: "id", render:function(data){ return( user(data).getRoleNames() ); }, name: "role" }, ...
结果控制台报错:
admins:529 Uncaught ReferenceError: user is not defined at render (admins:529:25) at jquery.dataTables.min.js:115:15 at Ga.b.fnGetData (jquery.dataTables.min.js:28:234) at T (jquery.dataTables.min.js:33:248) at ab (jquery.dataTables.min.js:38:118) at ia (jquery.dataTables.min.js:32:467) at Qb (jquery.dataTables.min.js:53:234) at jquery.dataTables.min.js:50:337 at Object.g [as success] (jquery.dataTables.min.js:49:73) at c (jquery.min.js:2:28327)
请问如何通过User模型的自定义代码或Spatie函数实现需求?
解决方法
1. 修复后端查询的逻辑问题
你当前的where条件写法存在逻辑漏洞,orWhere会打乱join关联的判断逻辑,建议用whereIn或者闭包包裹条件:
// 方案一:用whereIn简化角色ID判断 $data = User::join('model_has_roles','model_has_roles.model_id','users.id') ->join('roles','model_has_roles.role_id','roles.id') ->join('user_profiles','user_profiles.user_id','users.id') ->select('users.id', 'title', DB::raw("CONCAT(user_profiles.fname, ' ', user_profiles.mname,' ', user_profiles.sname) As name"), 'email', 'gender', 'roles.name As role') ->whereIn('roles.id', [8,9]) ->get(); // 方案二:用闭包确保条件逻辑独立 $data = User::join('model_has_roles','model_has_roles.model_id','users.id') ->join('roles','model_has_roles.role_id','roles.id') ->join('user_profiles','user_profiles.user_id','users.id') ->select('users.id', 'title', DB::raw("CONCAT(user_profiles.fname, ' ', user_profiles.mname,' ', user_profiles.sname) As name"), 'email', 'gender', 'roles.name As role') ->where(function($query) { $query->where('roles.id',8)->orWhere('roles.id',9); }) ->get();
如果存在单用户多角色的情况,可追加->distinct()避免重复数据。
2. 使用Spatie关联查询更简洁
如果User模型已引入Spatie的HasRoles trait,直接用Eloquent关联查询更清晰,还能避免join的潜在问题:
// User模型需提前引入:use Spatie\Permission\Traits\HasRoles; $data = User::with(['roles', 'userProfile']) ->whereHas('roles', function($query) { $query->whereIn('id', [8,9]); }) ->get() ->map(function($user) { return [ 'id' => $user->id, 'title' => $user->title, 'name' => $user->userProfile->fname . ' ' . $user->userProfile->mname . ' ' . $user->userProfile->sname, 'email' => $user->email, 'gender' => $user->userProfile->gender, 'role' => $user->roles->pluck('name')->implode(', ') // 处理多角色,用逗号分隔 ]; });
需要确保User模型定义了userProfile关联:
public function userProfile() { return $this->hasOne(UserProfile::class, 'user_id'); }
3. 修复前端DataTables错误
前端报错是因为user(data)并非前端可用函数,前端无法直接调用后端Eloquent方法。正确做法是在后端把角色数据提前处理好并返回,前端直接渲染:
..., { data: "role", name: "role" }, ...
内容的提问来源于stack exchange,提问作者The Only Smart Boy
相关产品推荐
相关产品推荐

