迁移失败报错“Base table or view not found”源于未发布并执行迁移文件,需先运行php artisan vendor:publish命令再执行migrate;同时Laravel 5.5需适配低版本MySQL设置defaultStringLength(191)。

安装后迁移失败报错 Base table or view not found
这是最常卡住的第一步:表根本没建出来,但错误不显眼,Role::create() 直接抛出 SQL 异常。根本原因是迁移文件没发布或没执行。
- 必须先运行
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="migrations",否则database/migrations下不会生成建表文件 - 再跑
php artisan migrate—— 缺一不可,跳过任一环节都会导致roles、permissions等五张表缺失 - Laravel 5.5 默认使用
utf8mb4字符集,若 MySQL 版本低于 5.7.7 或 MariaDB 低于 10.2.2,需在AppServiceProvider::boot()中加\Schema::defaultStringLength(191)
User 模型配置错误导致 assignRole 静默失效
即使表存在、代码看着没问题,$user->assignRole('admin') 也可能完全没写入数据库,查 model_has_roles 表为空——问题往往出在模型绑定或守卫配置上。
- 确认
App\Models\User(或你实际使用的 User 类路径)已引入HasRolestrait:use Spatie\Permission\Traits\HasRoles;并在 class 中声明use HasRoles; - 检查
config/auth.php中'providers.users.model'是否指向你当前使用的 User 类,比如App\Models\User,而不是旧的App\User - 如果用了自定义 guard(如
admin),调用$user->assignRole()前要确保该用户实例是从对应 guard 加载的,否则关联会写到默认 guard 的中间表
权限校验时 $user->can() 总是返回 false
明明角色和权限都分配好了,$user->can('edit posts') 却始终为 false,大概率是缓存没清或权限没挂到角色上。
- 开发中每次修改权限或角色关系后,必须手动清缓存:
php artisan cache:forget spatie.permission.cache,否则can()读的是旧快照 - RBAC 分层逻辑要求:权限 → 角色 → 用户。不要直接对用户调
$user->givePermissionTo('edit posts'),这会绕过角色管控,且$user->hasRole('editor')查不到关联 - 验证权限是否真挂到了角色上:用
$role = Role::findByName('editor'); dd($role->permissions->pluck('name')),确保输出包含目标权限名
中间件里用 role 或 permission 报错 Undefined index: guard
在路由中写 middleware => ['role:admin'] 却提示 guard 键不存在,说明中间件没拿到当前请求的 guard 实例。
- 确保
config/auth.php中该 guard 的provider配置完整,且 provider 对应的model路径正确 - 如果用的是非默认 guard(比如
admin),中间件参数要显式指定 guard:role:admin,admin(第一个admin是角色名,第二个是 guard 名) - 别在未登录状态下测试 —— 中间件依赖
Auth::user(),未认证用户会触发异常,建议配合auth中间件前置:auth:admin,role:admin


















