Laravel ACL系统使用Gate报错:Call to a member function getKey() on bool
Laravel Gate 报错:Call to a member function getKey() on bool
问题原因
这个错误是因为你在Gate回调中给hasRole方法传入了错误的参数类型,或者User模型的hasRole方法未正确处理集合类型参数,导致返回的布尔值被框架后续逻辑错误地调用了getKey()方法。
你的代码里$permission->roles是Eloquent集合(通过with('roles')预加载得到),但通常hasRole方法是用来检查用户是否拥有单个角色(传入角色名称、ID或单个模型),而非直接传入集合。
解决方案
1. 修正Gate回调的参数传递
将集合转换为角色名称/ID数组,适配hasRole方法的参数要求:
Gate::define($permission->name , function ($user) use($permission){ // 传递角色名称数组给hasRole return $user->hasRole($permission->roles->pluck('name')->toArray()); });
如果你的hasRole方法支持通过ID检查,也可以用:
return $user->hasRole($permission->roles->pluck('id')->toArray());
如果hasRole仅支持单个角色检查,改用集合的some方法验证用户是否拥有任意关联角色:
Gate::define($permission->name , function ($user) use($permission){ return $permission->roles->some(function ($role) use ($user) { return $user->hasRole($role); }); });
2. 优化getPermissions方法
get()已经返回Eloquent集合,无需调用all()转数组,简化代码:
protected function getPermissions(): \Illuminate\Database\Eloquent\Collection { return Permission::with('roles')->get(); }
3. 确保User模型的hasRole方法兼容多参数类型
如果是自定义的hasRole方法,建议完善逻辑以支持单个角色、数组、模型等多种参数类型:
public function hasRole($role) { // 处理字符串类型(角色名称) if (is_string($role)) { return $this->roles->contains('name', $role); } // 处理数组类型(角色名称/ID数组) if (is_array($role)) { return $this->roles->pluck('name')->intersect($role)->isNotEmpty(); } // 处理模型实例 return $this->roles->contains($role); }
验证
修改完成后,重新请求接口或页面,authorize('show-users')即可正常验证权限,不会再出现getKey()调用错误。
内容的提问来源于stack exchange,提问作者Aliizi
相关产品推荐
相关产品推荐

