laravel批量插入应优先使用db::table('table')->insert()分块处理,单次≤1000行,手动补全时间戳、严格匹配字段名,禁用模型事件;有唯一约束时用upsert()并确保数据库支持。

直接用 User::factory()->count(50)->create() 最省事,但不注册工厂、不手动调用、不处理时间字段或唯一性,八成会失败。
Seeder 文件没被调用?检查 DatabaseSeeder::run() 里有没有 $this->call(UserSeeder::class)
Laravel 8+ 移除了自动扫描 database/seeders 目录的逻辑。即使你写了 UserSeeder 并在 run() 里调用了 create(),只要没在 DatabaseSeeder.php 的 run() 方法中显式写 $this->call(UserSeeder::class),命令就完全静默跳过。
DatabaseSeeder.php 默认是空的,不是注释掉而是真·什么都没写。常见错误包括:
- 文件名和类名大小写不一致(
UserSeeder.php→class userseeder) - 命名空间写成
App\Database\Seeders或漏写,正确应为namespace Database\Seeders; - 运行前没执行
composer dump-autoload,导致类未被发现
User::factory() 报 Call to undefined function factory() 怎么办
这是 Laravel 8+ 废弃全局 factory() 函数后的典型报错。新机制只认模型静态方法,且依赖 Database\Factories\UserFactory 类存在。
必须按顺序确认三件事:
- 已运行
php artisan make:factory UserFactory --model=User,且文件路径为database/factories/UserFactory.php -
UserFactory.php中的definition()方法返回的是字段数组,不是模型实例 - Seeder 中调用的是
User::factory()->count(50)->create(),不是factory(User::class, 50)->create()
如果只是要假数据字符串(比如填日志字段),用 $this->faker->email;要入库并触发模型事件、类型转换(如 $casts)、访问器,必须走 User::factory()。
批量插 1000 条卡死或超时?关事件 or 改用 DB::table()->insert()
默认 User::factory()->count(1000)->create() 是逐条 INSERT + 触发 Eloquent 生命周期事件,内存和时间开销都大。这不是代码写错了,是机制本身如此。
两种提速路径:
- 关事件:加
->withoutEvents(),例如User::factory()->count(1000)->withoutEvents()->create() - 绕过 Eloquent:用
DB::table('users')->insert($data),但注意:
– 字段键名必须与数据库列完全一致(如email_verified_at,不能是emailVerifiedAt)
– 时间字段得手动转成Y-m-d H:i:s格式(用now()或Carbon::now())
–$casts、mutator、deleted_at处理全失效,deleted_at为 NULL 时必须传null,不能传字符串'null'
大数据量(>1000 条)务必分块,比如每次 500 条:for ($i = 0; $i count(500)->create(); }
唯一字段(如 email)重复插入失败?别只靠 $this->faker->unique()->safeEmail()
$this->faker->unique()->safeEmail() 默认只在当前批次内去重,跨批次或多次运行 db:seed 就可能重复。Laravel 不会自动清空 Faker 的 unique 缓存。
更稳妥的做法有:
- 启用全局缓存:
$this->faker->unique(true)->safeEmail() - 每次填充前主动清空:
$this->faker->unique(true)->clear() - 彻底规避冲突:用
str()->random(10).'@example.com'拼接邮箱,不依赖 Faker 唯一性逻辑
最容易被忽略的是:反复运行 db:seed 导致主键冲突或重复数据,却没意识到 truncate() 要慎用,也忘了工厂关联方向写反(比如该用 has() 却误用 for())。











