应将后台控制器迁至 app/Http/Controllers/Backend 并配置 PSR-4 自动加载,路由需显式指定命名空间,权限控制须在模型作用域中实现行级过滤,避免中间件遗漏导致数据越权。

直接在 app/Http/Controllers 下堆控制器,很快就会失控——尤其是当后台要支持多角色、多模块、多数据权限时。Laravel Admin 本身不强制分层,但真实项目里必须分,否则 AdminController 会变成“上帝类”,改一个字段都得测全站。
用命名空间 + 目录结构做物理隔离
不要依赖 Laravel Admin 自带的单层 Admin 控制器目录(如 app/Admin/Controllers),它默认不支持子目录自动注册。正确做法是:把后台控制器迁到 app/Http/Controllers/Backend(或 Admin,但必须和路由命名空间对齐),并配合 PSR-4 自动加载。
- 运行
php artisan make:controller Backend/UserController,生成路径为app/Http/Controllers/Backend/UserController.php - 确认该文件顶部有
namespace AppHttpControllersBackend; - 在
composer.json的"autoload"→"psr-4"中加入:"App\Http\Controllers\Backend\": "app/Http/Controllers/Backend/" - 执行
composer dump-autoload,否则类找不到
常见错误现象:Class AppHttpControllersBackendUserController does not exist —— 多半是漏了 autoload 配置或没跑 dump-autoload。
路由注册必须显式指定完整命名空间
Laravel Admin 的 admin/routes.php 默认不读取 routes/web.php,也不能直接用 Route::resource() 指向 Backend* 类,除非你手动引入命名空间。
- 在
routes/admin.php(或admin/routes.php)开头加:use AppHttpControllersBackend; - 写路由时用数组语法:
Route::get('users', [BackendUserController::class, 'index']); - 避免字符串语法:
'BackendUserController@index'—— 容易因自动加载失败静默报错,且 IDE 不识别 - 如果用了 Laravel Admin 的
Grid/Form,确保控制器方法返回的是Grid或Form实例,而不是视图;否则会跳转 404 或空白页
权限与数据过滤不能只靠中间件
后台控制器分层后,最容易被忽略的是行级权限的耦合点——比如 BackendOrderController@show 要确保当前管理员只能看自己部门的订单,这个逻辑不能只塞在中间件里,否则 Grid 查询、导出、API 接口都会绕过。
- 在模型中定义作用域(scope):
public function scopeForCurrentDepartment($query),然后在控制器里统一调用Order::forCurrentDepartment()->find($id) - 不要在每个
index/show/export方法里重复写where('department_id', ...) - 如果用了 Laravel Admin 的
grid()->model(),记得链式调用作用域:$grid->model()->forCurrentDepartment() - 测试时务必用非超级管理员账号验证,因为中间件可能放行了
role:super_admin,但模型作用域不会自动跳过
真正麻烦的不是怎么分目录,而是分完之后——所有 use 语句、路由引用、模型关联、权限判断点,都得跟着命名空间走一遍。漏掉任意一处,就表现为“页面能打开但数据为空”或“404 不报错”。建议分层前先 grep 全局所有 AppHttpControllersAdmin,再批量替换。


















