Laravel 9从上级目录调用Seeder报错,求排查解决
场景说明
我的Laravel 9项目中,Seeder的存放路径如下:
- Database/Seeders/Production/Permissions/UserManagement/UserPermissionsTableSeeder
- Database/Seeders/Production/Permissions/PermissionsGeneratorTableSeeder
我需要在UserPermissionsTableSeeder中调用PermissionsGeneratorTableSeeder,编写的代码如下:
<?php namespace Database\Seeders\Production\Permissions\UserManagement; use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; class UserPermissionsTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run($companyId = null) { $roles = [ 'super_admin' => [ 'user_index', 'user_show', 'user_store', 'user_update', 'user_destroy' ], 'admin' => [ 'user_index', 'user_show', 'user_store', 'user_update' ] ]; $this->call( Database\Seeders\Production\Permissions\PermissionsGeneratorTableSeeder::class, false, ['roles' => $roles] ); } }
调用时出现以下错误:
Target class [Database\Seeders\Production\Permissions\UserManagement\Database\Seeders\Production\Permissions\PermissionsGeneratorTableSeeder] does not exist.
更新内容
以下是PermissionsGeneratorTableSeeder的代码:
<?php namespace Database\Seeders\Production\Permissions; use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; use Spatie\Permission\Models\Role; use Spatie\Permission\Models\Permission; class PermissionsGeneratorTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run($roles = []) { if (!$roles) { return; } foreach ($roles as $key => $permissions) { $role = Role::query(); $role = $role->where('name', $key); if ($key != 'super_admin') { $role = $role->where('company_id', $companyId); } $role = $role->first(); if (!$role) { continue; } foreach ($permissions as $permission) { $discoveredPermission = Permission::where('name', $permission)->first(); if ($discoveredPermission) { $discoveredPermission->assignRole($role); continue; } $permissionCreated = Permission::create([ 'name' => $permission, 'guard_name' => config('auth.defaults.guard') ]); $permissionCreated->assignRole($role); } } } }
问题原因与解决方法
核心错误原因
当前UserPermissionsTableSeeder的命名空间是Database\Seeders\Production\Permissions\UserManagement,调用call方法时直接写完整类名,Laravel会将其视为相对命名空间,自动拼接当前类的命名空间,导致生成了错误的类路径(两个命名空间叠加)。
两种解决方式
方式一:通过use引入目标类
在UserPermissionsTableSeeder的顶部添加use语句,引入目标Seeder的命名空间:
<?php namespace Database\Seeders\Production\Permissions\UserManagement; use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; // 新增引入语句 use Database\Seeders\Production\Permissions\PermissionsGeneratorTableSeeder; class UserPermissionsTableSeeder extends Seeder { // ... 其他代码不变 public function run($companyId = null) { // ... 其他代码不变 $this->call( PermissionsGeneratorTableSeeder::class, false, ['roles' => $roles] ); } }
方式二:使用绝对命名空间
在目标类名前添加反斜杠\,告诉Laravel从根命名空间开始查找,避免拼接当前命名空间:
$this->call( \Database\Seeders\Production\Permissions\PermissionsGeneratorTableSeeder::class, false, ['roles' => $roles] );
额外注意事项
在PermissionsGeneratorTableSeeder的代码中,run方法里用到了$companyId变量,但方法参数未定义该变量,会触发变量未定义错误。需要修改run方法的参数定义:
public function run($roles = [], $companyId = null) { // ... 后续代码不变 }
内容的提问来源于stack exchange,提问作者Ryan H

