在 Laravel 项目里,经常遇到用户创建或编辑表单需要根据所选部门、用户组或其他条件,动态展示可选的角色列表。如果直接把所有角色都查出来放在下拉框,不仅体验差,还可能暴露无权限的角色。下面介绍一种前后端配合的完整实现方式。

一、数据库与模型准备
假设系统中角色 roles 表与部门 departments 表存在多对多关系,另外用户表 users 包含 department_id 字段。我们可以在 Role 模型中定义查询作用域,方便后续复用。
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Role extends Model
{
// 只返回某个部门可见的角色
public function scopeForDepartment($query, $departmentId)
{
if ($departmentId) {
return $query->whereHas('departments', function ($q) use ($departmentId) {
$q->where('departments.id', $departmentId);
});
}
return $query;
}
}
二、控制器返回筛选接口
新建一个角色控制器方法,接收 department_id 参数,返回 JSON 格式的角色数据,供前端动态调用。
<?php
namespace AppHttpControllers;
use AppModelsRole;
use IlluminateHttpRequest;
class RoleController extends Controller
{
public function filter(Request $request)
{
$departmentId = $request->input('department_id');
$roles = Role::forDepartment($departmentId)->select('id', 'name')->get();
return response()->json($roles);
}
}
三、注册 API 路由
在 routes/api.php 中添加一个轻量接口,注意此处仅做演示,实际项目请加上相应中间件与权限校验。
<?php
use IlluminateSupportFacadesRoute;
use AppHttpControllersRoleController;
Route::get('/roles/filter', [RoleController::class, 'filter']);
四、前端表单动态刷新
在 Blade 模板中,监听部门下拉框变化,通过原生 fetch 请求获取角色并填充到角色选择框。这里使用 <select> 标签作为示例。
<!DOCTYPE html>
<html>
<body>
<label>部门</label>
<select id="department">
<option value="">请选择</option>
<option value="1">技术部</option>
<option value="2">运营部</option>
</select>
<label>角色</label>
<select id="role"></select>
<script>
document.getElementById('department').addEventListener('change', function () {
var depId = this.value;
fetch('/api/roles/filter?department_id=' + depId)
.then(function (res) { return res.json(); })
.then(function (data) {
var roleSel = document.getElementById('role');
roleSel.innerHTML = '';
data.forEach(function (item) {
var opt = document.createElement('option');
opt.value = item.id;
opt.text = item.name;
roleSel.appendChild(opt);
});
});
});
</script>
</body>
</html>
五、注意事项与优化
- 接口必须做权限控制,防止普通用户获取高权限角色。
- 如果角色数据量大,可在 Role 模型加上缓存,避免频繁查询。
- 前端可结合 Laravel 的表单验证,确保提交的 role_id 确实属于该部门。
通过上述方式,我们能在 Laravel 中优雅地实现表单内动态筛选角色,既保证了灵活性,也兼顾了安全与可维护性。