表为空主因是未执行迁移导致表不存在,或外键顺序错误、Laravel 10+ 调用方式不当;Migration 负责建表,Seeder 仅填充数据,二者职责分明不可替代。

直接跑 php artisan db:seed 表还是空的?不是代码写错,大概率是迁移没执行、外键顺序乱了,或者 Laravel 10+ 里调用方式变了。Migration 管建表改结构,Seeder 管插数据,两者职责分明,不能混用,也不能跳步。
Migration:先让表存在,再谈填数据
Seeder 插不了数据,最常见原因是表压根不存在——因为 migration 没跑。Laravel 不会自动建表,Seeder 也不负责建表。
- 必须先执行
php artisan migrate(或migrate:fresh重置),确保表已创建 - 检查
database/migrations/下文件是否已生成,且up()方法中正确定义了字段(比如$table->string('email')->unique()) - 用
php artisan migrate:status确认哪些迁移已生效;用--pretend预览 SQL,但注意它不显示外键/索引隐式变更 - 别在 migration 的
up()里写DB::table()->insert()——那是 Seeder 的活,破坏职责分离
Seeder:安全填充 ≠ 自动清空
运行 db:seed 后表为空,除了表不存在,还常因唯一约束冲突中断插入,且 Laravel 默认静默失败(尤其 Laravel 9+)。
- 确认
DatabaseSeeder.php中已显式调用子 Seeder:(new UserSeeder())->run();(Laravel 10+ 必须 new 实例,$this->call(UserSeeder::class)已失效) - 检查类名、命名空间、文件路径是否完全一致(
UserSeeder↔UserSeeder.php↔use Database\Seeders\UserSeeder;) - 想“重跑”前清空数据?
--force不会自动 truncate,得手动加:DB::table('users')->truncate();(跨数据库兼容)或DB::statement('TRUNCATE TABLE users');(MySQL 更快) - 有外键时,先关检查:
DB::statement('SET FOREIGN_KEY_CHECKS=0');,truncate 后再开
批量插入别循环 create(),性能差还易崩
100 条数据用 User::create() 还行,1000 条就会卡顿甚至内存溢出——每条都走模型生命周期、验证、事件、单条 SQL。
- 提速首选:
DB::table('users')->insert($data);,其中$data是二维数组,字段名必须和数据库列名严格一致 - 需触发模型事件(如
creating)?改用User::insert($data),并提前User::unguard()(确保$fillable正确) - 超 500 条建议分批:
collect($data)->chunk(500)->each(fn ($chunk) => DB::table('users')->insert($chunk)); - Laravel 10+ 已移除
factory()函数,改用fake()->email()等 fake 实例生成假数据
协同部署:本地开发 & CI/CD 安全要点
Migration 和 Seeder 在不同环境用途不同:migration 通常上线必跑,seeder 只用于本地、测试或 CI 初始化,绝不用于生产。
- CI 流水线慎用
migrate:fresh --seed:它读取DB_DATABASE,若未隔离库名,可能误删共享测试库 - 外键依赖顺序要显式控制:在
DatabaseSeeder::run()中按依赖顺序调用,比如先(new RoleSeeder())->run();,再(new UserSeeder())->run();,别靠文件名自动排序 - 线上部署脚本只包含
migrate,seeder 命令应限制在APP_ENV=local或testing下运行 - Seeder 中避免硬编码敏感数据(如管理员密码),改用
Hash::make()动态生成


















