Laravel 10多关联模型Factory与Seeder填充数据报错求助
Laravel 多表关联迁移与数据填充错误解决
问题背景
- 涉及三个数据表:
Categories、Books、Authors - 关联关系:
Categories与Books为一对多Authors与Books为一对多
- 先完成了
Categories和Books的迁移、模型及数据填充,后添加Authors相关文件后,执行迁移和Seeder时出现两个错误:SQLSTATE[HY000]: General error: 1005 Can't create table
booky.books(errno: 150 "Foreign key constraint is incorrectly formed") (Connection: mysql, SQL: alter tablebooksadd constraintbooks_author_id_foreignforeign key (author_id) referencesauthors(id) on delete cascade)
SQLSTATE[HY000]: General error: 1364 Field 'author_id' doesn't have a default value
错误原因分析
- 外键约束错误:
原Books迁移文件中直接添加了author_id外键,但执行该迁移时Authors表尚未创建,MySQL无法创建指向不存在表的外键约束。 - 字段缺失默认值错误:
创建Book时未提供author_id值(原Seeder仅传入category_id),且author_id字段无默认值,违反数据库非空约束。
解决方案
1. 修复迁移文件
如果已经执行过Books的迁移,不要直接修改原迁移文件,而是创建新迁移来添加author_id字段及外键:
php artisan make:migration add_author_id_to_books_table
在新迁移文件中写入:
public function up(): void { Schema::table('books', function (Blueprint $table) { // 添加author_id字段,自动关联authors表并设置级联删除 $table->foreignId('author_id')->constrained()->cascadeOnDelete(); }); } public function down(): void { Schema::table('books', function (Blueprint $table) { $table->dropForeign(['author_id']); $table->dropColumn('author_id'); }); }
注意:确保
Authors迁移文件的时间戳前缀早于这个新迁移文件,让Authors表先被创建。如果Authors迁移是后创建的,手动调整文件名的时间戳即可。
2. 完善模型关联
- 在
App\Models\Book中添加关联:
public function category() { return $this->belongsTo(Category::class); } public function author() { return $this->belongsTo(Author::class); }
- 在
App\Models\Author中添加关联:
public function books() { return $this->hasMany(Book::class); }
- 在
App\Models\Category中添加关联:
public function books() { return $this->hasMany(Book::class); }
3. 调整Book Factory
修改BookFactory,让它自动关联Author,避免手动传值:
public function definition(): array { return [ 'book_title' => fake()->sentence(), 'book_desc' => fake()->paragraph(), 'book_image' => fake()->imageUrl(), // 自动关联随机存在的作者 'author_id' => \App\Models\Author::inRandomOrder()->first()->id ]; }
4. 优化DatabaseSeeder
先创建所有分类和作者,再批量创建书籍并关联两者,逻辑更清晰:
public function run(): void { // 先创建3个分类 $categories = \App\Models\Category::factory(3)->create(); // 先创建5个作者 $authors = \App\Models\Author::factory(5)->create(); // 为每个分类创建4本书,同时关联随机作者 $categories->each(function ($category) use ($authors) { \App\Models\Book::factory(4)->create([ 'category_id' => $category->id, 'author_id' => $authors->random()->id ]); }); }
验证执行
- 回滚之前的错误迁移(若需要):
php artisan migrate:rollback
- 重新执行迁移:
php artisan migrate
- 运行Seeder:
php artisan db:seed
内容的提问来源于stack exchange,提问作者MohamedSalem
相关产品推荐
相关产品推荐

