You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 19:27:31