0

当用户的角色 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');
    }

我的网络中间件组有

\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);
    }
}
4

1 回答 1

2

不要将我的答案标记为用户Autista_z告诉你修复的正确答案,我将分享一些东西以获得更好的代码,非常简单和“Laravel 方式”的东西要做。

正如用户Autista_z所说:“问题将出现在foreach用于Gate定义的循环中。在循环的第一次迭代中(基于您的示例数组),您将拥有$action = 0and $roles = 'admin_role_manage'。所以门的名称将是0。所以当然,然后@can('admin_role_manage')false“。


因此,您正在设置或获取很多不需要的东西,或者以其他方式措辞,您可以拥有更清晰的代码(至少对于您的Middleware班级而言)。

如果您知道(也许您不知道),您可以模型属性转换为您想要的类型,因此json_decode($user_role->permissions)您可以简单地做而不是这样做foreach ($user_role->permissions as $role),但在这样做之前您需要转换它。

因此,您的模型将具有$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 $rolesto的措辞$role->permissions as $permission,您role可以是“作家”,您的权限是newsletter_manage, brand_logos,quote_manage等等。所以这不是角色而是权限。

另外请记住,我认为您甚至可以为该foreach/define部分编写更好的代码。

于 2021-04-08T23:51:50.443 回答