返回

Laravel 10 多表工厂关系问题及解决方法

php

Laravel 10 中的多表工厂关系问题与解决方案

在使用 Laravel 10 的工厂和数据播种器来创建模拟数据时,你可能会遇到一些问题。例如,你可能会看到以下错误消息:

SQLSTATE[HY000]: General error: 1005 Can't create table `booky`.`books` (errno: 150 "Foreign key constraint is incorrectly formed")

SQLSTATE[HY000]: General error: 1364 Field 'author\_id' doesn't have a default value

错误分析

这些错误表明在你定义 books 表的外键时存在问题。外键 author_id 引用 authors 表中的 id 字段,但是 authors 表中没有定义默认值。

解决方案

要解决这个问题,你可以按照以下步骤操作:

  1. 修改 authors 表迁移文件:

    authors 表迁移文件中,添加 $table->unsignedBigInteger('id')->autoIncrement();,以设置 id 字段为自增主键。

    public function up(): void
    {
        Schema::create('authors', function (Blueprint $table) {
            $table->unsignedBigInteger('id')->autoIncrement();
            $table->string('author_name');
            $table->timestamps();
        });
    }
    
  2. 运行迁移:

    运行迁移以应用更改。

    php artisan migrate
    
  3. 更新数据播种器:

    在数据播种器中,将 rand(1, 5) 更改为 $author->id,以将 author_id 设置为相应作者的 id

    public function run(): void
    {
        \App\Models\Category::factory(3)
            ->create()
            ->each(function ($category) {
                \App\Models\Book::factory(4)
                    ->create(['category_id' => $category->id]);
            });
    
        \App\Models\Author::factory(5)
            ->create()
            ->each(function ($author) {
                \App\Models\Book::create(['author_id' => $author->id]);
            });
    }
    

其他提示

  • 确保 categoriesbooks 表的外键约束已正确定义。
  • 验证 author_id 字段是否已设置为 unsignedBigInteger
  • 检查 authors 表中是否有默认值。

常见问题解答

  1. 为什么我需要设置 id 字段为自增主键?

    id 字段是主键,它用于唯一标识表中的每行。自增主键会自动为每一行生成一个唯一的 ID,简化了数据插入过程。

  2. 为什么我需要在 authors 表中设置默认值?

    默认值对于外键字段非常重要,因为它确保即使没有显式设置外键值,也能插入数据。

  3. 我如何确保外键约束已正确定义?

    外键约束应在表迁移文件中使用 foreignId 方法定义。确保 foreignId 方法的第一个参数与外键字段名称匹配,第二个参数与被引用表的主键字段名称匹配。

  4. 如何检查 author_id 字段是否已设置为 unsignedBigInteger

    在表迁移文件中,author_id 字段应定义为 $table->unsignedBigInteger('author_id')

  5. 如何在 authors 表中检查默认值?

    可以在数据库管理工具或通过运行以下查询来检查 authors 表中的默认值:

    SELECT COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_NAME = 'authors' AND COLUMN_NAME = 'id';