laravel权限动态显示菜单以及按钮

1,331 阅读1分钟

这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战

一、修改增加节点信息

按照如下表进行添加 在这里插入图片描述

在这里插入图片描述

二、基础模型添加数组多层级

/**
     * 数组多层级
     * @param array $data
     * @param int $pid
     * @param array
     */
    public function subTree(array $data, int $pid = 0) {
        $arr = [];
        foreach ($data as $val) {
            // 给定的pid是当前记录的上级id
            if ($pid == $val['pid']) {
                // 递归
                $val['sub'] = $this -> subTree($data, $val['id']);
                $arr[] = $val;
            }
        }
        return $arr;
    }

在这里插入图片描述

三、权限(节点)模型进行菜单层级化

    // 获取有层级的数据
    public function treeData() {
        $menuData = Node::where('is_menu', '1') -> get() -> toArray();
        return $this -> subTree($menuData);
    }

在这里插入图片描述

四、后台首页控制器修改

读取菜单控制器

    // 后台首页显示
    public function index() {

        // 读取菜单
        $menuData = (new Node()) -> treeData();
        // dump($menuData);

        return view('admin.index.index', compact('menuData'));
    }

在这里插入图片描述

五、修改后台首页模版

将读取到的菜单进行循环展示:

@foreach($menuData as $item)
		<dl id="menu-admin">
			<dt><i class="Hui-iconfont">&#xe62d;</i>{{$item['name']}}<i class="Hui-iconfont menu_dropdown-arrow">&#xe6d5;</i></dt>
			<dd>
				<ul>
					@foreach($item['sub'] as $subItem)
					<li><a data-href="{{route($subItem['route_name'])}}" data-title="{{$subItem['name']}}" href="javascript:void(0)">{{$subItem['name']}}</a></li>
					@endforeach
			</ul>
		</dd>
		</dl>
	@endforeach

在这里插入图片描述

六、效果

在这里插入图片描述

七、动态读取用户菜单

7.1 配置超级管理员

.env文件夹下配置超级管理员账号为admin在这里插入图片描述

7.2 在用户登陆时读取角色

LoginController.php登陆控制器中在用户登陆成功时读取用户权限:

        // 判断是否登录成功 
        if ($bool) {
            // 得到用户权限
            // 判断以下是否是超级管理员
            if (env('SUPER') != $post['username']) {
                $userModel = auth() -> user();
                // dump($userModel);
                $roleModel = $userModel -> role;
                $nodeArr = $roleModel -> nodes() -> pluck('name', 'id') -> toArray();
                // dump($nodeArr);
                // 权限保存到session中  
                session(['admin.auth' => $nodeArr]);
            }
            else {
                session(['admin.auth' => true]);
            }

            return redirect(route('admin.index'));
        }

在这里插入图片描述


7.3 修改权限模型层级方法

    /**
     * 获取有层级的数据
     * @param $allow_node 用户有的权限
     * @return array
     */
    public function treeData($allow_node) {
        $query = Node::where('is_menu', '1');
        if ($allow_node !== true) {
            // 不是超级管理员
            $query -> whereIn('id',array_keys($allow_node));
        }
        $menuData = $query -> get() -> toArray();
        
        return $this -> subTree($menuData);
    }

在这里插入图片描述

7.4 修改后台首页显示控制器

    // 后台首页显示
    public function index() {
        // 权限
        $auth = session('admin.auth');


        // 读取菜单 将当前角色的菜单id传过去
        $menuData = (new Node()) -> treeData($auth);
        // dump($menuData);

        return view('admin.index.index', compact('menuData'));
    }

在这里插入图片描述

7.5 效果

在这里插入图片描述

7.6 权限不彻底问题

我们会发现当我记住添加节点的路由地址http://laravelproject.com/admin/node/create,我们退出管理员的账号,随便登一个没有这个权限的账号,去访问这个添加节点的路由地址,发现也能访问的到。所以第二小节来解决这个问题。

八、权限路由问题

8.1 配置文件修改

config文件夹下新建rbac.php文件,将权限配置写入:

<?php

return [
    'super' => 'admins', // 超级管理员
    'allow_route' => [ // 不验证到路由
        'admin.welcome',
        'admin.index',
        'admin.logout'
    ],
];

在这里插入图片描述 更改LoginController.php中配置: 在这里插入图片描述


8.2 登陆中间件

Middleware文件下修改CheckAdminLogin.php中间件

<?php

namespace App\Http\Middleware;

use Closure;

class CheckAdminLogin
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        // 用户是否登录检查
        if (!auth() ->check()) {
            return redirect(route('admin.login')) -> withErrors(['error' => '未登录,请登录']);
        }

        // 访问到权限

        $auths =  is_array(session('admin.auth')) ? array_filter(session('admin.auth')) : [];  // 数组去空
        $auths = array_merge($auths, config('rbac.allow_route'));
        // dump($auths);

        // 当前访问的路由
        $currentRoute = $request -> route() -> getName();
        if (auth() -> user() -> username != config('rbac.super') && !in_array($currentRoute, $auths)) {
            exit('没有权限');
        }

        // 如果没有停止则向后执行
        return $next($request);
    }
}

8.3 修改登录控制器

LoginController.php

$nodeArr = $roleModel -> nodes() -> pluck('route_name', 'id') -> toArray();

在这里插入图片描述 效果: 在这里插入图片描述

九、非菜单权限隐藏

使用多继承来控制非菜单权限隐藏 在Models文件夹下创建Traits文件夹,在这个文件夹下创建Btn.php:

<?php
// 按钮
namespace App\Models\Traits;

trait Btn {
    public function editBtn (string $route) {

        // dd(request() -> auths);
        if (auth() -> user() -> username != config('rbac.super') && !in_array($route, request() -> auths)) {
            return '';
        }
        
            return '<a href="'.route($route, $this).'">修改</a>';
        

    }
}

在这里插入图片描述 以修改用户按钮演示,其他按钮雷同: 在用户User.php模型下使用多继承: 在这里插入图片描述 在用户列表显示模版中修改 修改按钮:

{!! $item -> editBtn('admin.user.edit') !!}

在这里插入图片描述 效果: 用非超级管理账号登陆: 在这里插入图片描述 可以看到修改按钮已经不见了。


用超级管理员账号登陆: 在这里插入图片描述 可以看到修改按钮存在。 至此laravel 后台菜单权限已完成。

在学习的php的路上,如果你觉得本文对你有所帮助的话,那就请关注点赞评论三连吧,谢谢,你的肯定是我写博的另一个支持。