在Laravel项目里,基于用户认证和角色权限动态显示UI元素是权限管理系统的常见需求,核心是通过后端获取当前用户的权限信息,再在前端模板中做条件判断来控制元素渲染。

核心实现思路
整个流程分为三个步骤:首先完成用户认证体系的搭建,确保能获取当前登录用户实例;其次设计角色和权限的关联模型,让用户可以绑定对应的角色和权限;最后在前端模板中通过条件判断,根据用户的权限信息决定是否渲染对应的UI元素。
前置准备:搭建认证与权限模型
1. 配置用户认证
Laravel内置了认证脚手架,执行以下命令快速生成认证相关代码:
// 安装认证脚手架 php artisan make:auth // 执行数据库迁移 php artisan migrate
2. 创建角色和权限模型
首先创建角色表和权限表,以及用户、角色、权限的关联表:
// 创建角色表迁移 php artisan make:migration create_roles_table // 创建权限表迁移 php artisan make:migration create_permissions_table // 创建用户角色关联表迁移 php artisan make:migration create_role_user_table // 创建角色权限关联表迁移 php artisan make:migration create_permission_role_table
角色表结构示例:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
class CreateRolesTable extends Migration
{
public function up()
{
Schema::create('roles', function (Blueprint $table) {
$table->id();
$table->string('name')->comment('角色名称');
$table->string('slug')->unique()->comment('角色标识');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('roles');
}
}
权限表结构示例:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
class CreatePermissionsTable extends Migration
{
public function up()
{
Schema::create('permissions', function (Blueprint $table) {
$table->id();
$table->string('name')->comment('权限名称');
$table->string('slug')->unique()->comment('权限标识');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('permissions');
}
}
3. 定义模型关联
在User模型中定义与角色的关联:
<?php
namespace AppModels;
use IlluminateFoundationAuthUser as Authenticatable;
class User extends Authenticatable
{
// 用户关联角色 多对多关系
public function roles()
{
return $this->belongsToMany(Role::class);
}
// 判断用户是否拥有指定角色
public function hasRole($roleSlug)
{
return $this->roles()->where('slug', $roleSlug)->exists();
}
// 判断用户是否拥有指定权限
public function hasPermission($permissionSlug)
{
// 遍历用户的所有角色,检查角色是否包含对应权限
foreach ($this->roles as $role) {
if ($role->permissions()->where('slug', $permissionSlug)->exists()) {
return true;
}
}
return false;
}
}
在Role模型中定义与权限的关联:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Role extends Model
{
// 角色关联权限 多对多关系
public function permissions()
{
return $this->belongsToMany(Permission::class);
}
}
前端模板动态显示UI元素
1. 基础条件判断
在Blade模板中,可以通过auth()->user()获取当前登录用户,结合模型中的权限判断方法控制元素显示:
<!DOCTYPE html>
<html>
<head>
<title>权限控制示例</title>
</head>
<body>
<div class="sidebar">
<!-- 所有登录用户都能看到的菜单 -->
<a href="/home">首页</a>
<!-- 仅管理员角色可见的菜单 -->
@if(auth()->check() && auth()->user()->hasRole('admin'))
<a href="/admin/dashboard">管理后台</a>
@endif
<!-- 仅拥有文章创建权限的用户可见的按钮 -->
@if(auth()->check() && auth()->user()->hasPermission('article_create'))
<a href="/articles/create" class="btn">发布文章</a>
@endif
</div>
<div class="content">
<h1>文章列表</h1>
<!-- 仅拥有文章删除权限的用户可见的删除按钮 -->
@if(auth()->check() && auth()->user()->hasPermission('article_delete'))
<button class="delete-btn">删除选中文章</button>
@endif
</div>
</body>
</html>
2. 封装Blade指令简化判断
如果多个页面都需要做权限判断,可以封装自定义Blade指令减少重复代码。在AppServiceProvider的boot方法中添加:
<?php
namespace AppProviders;
use IlluminateSupportServiceProvider;
use IlluminateSupportFacadesBlade;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
// 自定义角色判断指令
Blade::if('role', function ($roleSlug) {
return auth()->check() && auth()->user()->hasRole($roleSlug);
});
// 自定义权限判断指令
Blade::if('permission', function ($permissionSlug) {
return auth()->check() && auth()->user()->hasPermission($permissionSlug);
});
}
public function register()
{
//
}
}
封装后模板中的判断可以简化为:
@role('admin')
<a href="/admin/dashboard">管理后台</a>
@endrole
@permission('article_create')
<a href="/articles/create" class="btn">发布文章</a>
@endpermission
注意事项
- 前端仅做UI显示控制,后端接口必须也要做权限校验,避免用户通过直接访问接口绕过前端限制
- 权限标识建议使用统一的命名规范,比如
module_action格式,方便管理和排查问题 - 如果用户未登录,
auth()->user()会返回null,判断前一定要先调用auth()->check()确认用户已登录
总结
基于用户认证和角色权限动态显示UI元素的核心是打通用户、角色、权限的关联关系,再在前端模板中通过条件判断控制元素渲染。通过封装自定义Blade指令可以进一步简化代码,提升开发效率。实际项目中可以根据需求扩展权限模型,比如支持用户直接绑定权限、添加权限分组等功能,满足更复杂的业务场景。