Gate Define 不适用于 role_id 为 1 的其他用户
Gate Define not working for other users except whose role_id is 1
当用户具有 role_id 1 时,中间件中的以下代码工作正常,当我在角色-> 权限上执行 dd 时,我得到的响应是数组。
但是在这条中间件线上
if (in_array($role->permissions, $permission)) {
对于 role_id 不同的所有其他用户,我收到此错误
in_array(): 参数 #2 ($haystack) 必须是数组类型,在传递数组的地方给定字符串
我的角色模型有
protected $casts = [
'permissions' => 'array',
];
我的用户模型有
protected function role()
{
return $this->hasOne(Roles::class, 'id', 'role_id');
}
我的 web 中间件组有
\App\Http\Middleware\RolePermissionCheck::class,
我的 Meddlware 有
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;
class RolePermissionCheck
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!empty(Auth::user()->role_id)) {
$role = Auth::user()->role;
Gate::before(
function () {
if (Auth::user()->role_id === 1) {
return true;
}
}
);
// dd($role->permissions);
foreach ($role->permissions as $permission) {
Gate::define(
$permission,
function ($role) use ($permission) {
if (in_array($role->permissions, $permission)) {
return true;
}
}
);
}
}
return $next($request);
}
}
不要将我的答案标记为正确,因为用户 Autista_z 告诉你修复方法,我将分享一些东西以获得更好的代码,非常简单和“Laravel 方式”的东西.
正如用户 Autista_z 所说:“问题将出现在 foreach
循环中 Gate
定义。在循环的第一次迭代中(基于您的示例数组),您将有 $action = 0
和 $roles = 'admin_role_manage'
。所以门的名称将是 0
。所以当然,那么 @can('admin_role_manage')
就是 false
"。
因此,您正在设置或获得很多不需要的东西,或者换句话说,您可以拥有更清晰的代码(至少对于您的 Middleware
class)。
如果您知道(也许您不知道),您可以 cast 将属性建模为您想要的类型,因此您可以简单地 foreach ($user_role->permissions as $role)
而不是 json_decode($user_role->permissions)
,但在你这样做之前你需要施放它。
所以你的模型会有一个 属性 $casts
这样的:
protected $casts = [
'permissions' => 'array',
];
这将允许您执行 $model->permissions = ['role_1', 'role_2', ...];
而无需执行 $model->permissions = json_encode(['role_1', 'role_2', ...]);
(这也是 Laravel 处理此问题的方式)。
所以你的中间件会像这样结束:
namespace App\Http\Middleware;
use App\Models\User;
use App\Models\Roles;
use Closure;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;
class RolePermissionCheck
{
public function handle($request, Closure $next)
{
if ($role = Auth::user()->role)) {
Gate::before(
function (User $user) {
if ($user->role_id === '1') {
return true;
}
}
);
foreach ($role->permissions as $permission) {
Gate::define(
$permission,
function ($role) use ($permission) {
if (in_array($permission, $role->permissions)) {
return true;
}
}
);
}
}
return $next($request);
}
}
看到我把$role->permissions as $roles
的措辞改成了$role->permissions as $permission
,你的role
可能是“作者”,你的权限是newsletter_manage
,brand_logos
、quote_manage
,等等。所以这不是角色而是权限。
还要记住,我认为您甚至可以为 foreach/define
部分编写更好的代码。
当用户具有 role_id 1 时,中间件中的以下代码工作正常,当我在角色-> 权限上执行 dd 时,我得到的响应是数组。
但是在这条中间件线上
if (in_array($role->permissions, $permission)) {
对于 role_id 不同的所有其他用户,我收到此错误
in_array(): 参数 #2 ($haystack) 必须是数组类型,在传递数组的地方给定字符串
我的角色模型有
protected $casts = [
'permissions' => 'array',
];
我的用户模型有
protected function role()
{
return $this->hasOne(Roles::class, 'id', 'role_id');
}
我的 web 中间件组有
\App\Http\Middleware\RolePermissionCheck::class,
我的 Meddlware 有
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;
class RolePermissionCheck
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!empty(Auth::user()->role_id)) {
$role = Auth::user()->role;
Gate::before(
function () {
if (Auth::user()->role_id === 1) {
return true;
}
}
);
// dd($role->permissions);
foreach ($role->permissions as $permission) {
Gate::define(
$permission,
function ($role) use ($permission) {
if (in_array($role->permissions, $permission)) {
return true;
}
}
);
}
}
return $next($request);
}
}
不要将我的答案标记为正确,因为用户 Autista_z 告诉你修复方法,我将分享一些东西以获得更好的代码,非常简单和“Laravel 方式”的东西.
正如用户 Autista_z 所说:“问题将出现在 foreach
循环中 Gate
定义。在循环的第一次迭代中(基于您的示例数组),您将有 $action = 0
和 $roles = 'admin_role_manage'
。所以门的名称将是 0
。所以当然,那么 @can('admin_role_manage')
就是 false
"。
因此,您正在设置或获得很多不需要的东西,或者换句话说,您可以拥有更清晰的代码(至少对于您的 Middleware
class)。
如果您知道(也许您不知道),您可以 cast 将属性建模为您想要的类型,因此您可以简单地 foreach ($user_role->permissions as $role)
而不是 json_decode($user_role->permissions)
,但在你这样做之前你需要施放它。
所以你的模型会有一个 属性 $casts
这样的:
protected $casts = [
'permissions' => 'array',
];
这将允许您执行 $model->permissions = ['role_1', 'role_2', ...];
而无需执行 $model->permissions = json_encode(['role_1', 'role_2', ...]);
(这也是 Laravel 处理此问题的方式)。
所以你的中间件会像这样结束:
namespace App\Http\Middleware;
use App\Models\User;
use App\Models\Roles;
use Closure;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;
class RolePermissionCheck
{
public function handle($request, Closure $next)
{
if ($role = Auth::user()->role)) {
Gate::before(
function (User $user) {
if ($user->role_id === '1') {
return true;
}
}
);
foreach ($role->permissions as $permission) {
Gate::define(
$permission,
function ($role) use ($permission) {
if (in_array($permission, $role->permissions)) {
return true;
}
}
);
}
}
return $next($request);
}
}
看到我把$role->permissions as $roles
的措辞改成了$role->permissions as $permission
,你的role
可能是“作者”,你的权限是newsletter_manage
,brand_logos
、quote_manage
,等等。所以这不是角色而是权限。
还要记住,我认为您甚至可以为 foreach/define
部分编写更好的代码。