【问题标题】:Laravel - Unable to Migrate table with both 1:N and 1:1 RelationshipsLaravel - 无法迁移具有 1:N 和 1:1 关系的表
【发布时间】:2018-07-11 18:07:22
【问题描述】:

我有以下迁移表:

class CreateQuizzesTable extends Migration
{
    public function up()
    {
        Schema::create('quizzes', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('customer_id')->unsigned()->nullable();
            $table->string('name');
            $table->foreign('customer_id')->references('id')->on('customers')->onDelete('set null');
        });
    }

    public function down()
    {
        Schema::dropIfExists('quizzes');
    }
}

还有

class CreateCustomersTable extends Migration
{
    public function up()
    {
        Schema::create('customers', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('quiz_id')->unsigned()->nullable();
            $table->string('name')->unique();
            $table->string('password');
            $table->foreign('quiz_id')->references('id')->on('quizzes')->onDelete('set null');
        });
    }

    public function down()
    {
        Schema::dropIfExists('customers');
    }
}

客户可以创建(并因此拥有)多个测验 (1:N)。 customers 表有 quiz_id 字段的原因是,在他创建的那些中,一次只能激活一个 (1:1)。

问题是当我尝试迁移时它崩溃了,因为两个表相互引用,通知我另一个表还不存在。

如果我将 CreateQuizzesTable 设置为先执行:

SQLSTATE[42P01]:未定义表:7 错误:关系不存在«客户»

如果我将 CreateCustomersTable 设置为先执行:

SQLSTATE[42P01]:未定义表:7 错误:关系不存在«测验»

我坚持,这不是 N:M 关系,我想避免使用中间表来管理它。

更新:查看@JasperStaats 的答案后,我仍然对表的播种有疑问。由于必须首先执行两个表播种器中的一个,因此它期望另一个表的外键值已经存在于数据库中(例如:如果我首先执行 QuizzesTableSeeder,它将无法插入值 'customer_id' = > 1,因为客户表仍然是空的。现在,我将该字段值保留为空,然后转到数据库并将其替换为适当的值,但这并不理想。

种子执行指令文件:

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        $this->call(QuizzesTableSeeder::class);
        $this->call(CustomersTableSeeder::class);
    }
}

客户播种文件:

use Illuminate\Database\Seeder;

class CustomersTableSeeder extends Seeder
{
    public function run()
    {
        \DB::table('customers')->delete();

        \DB::table('customers')->insert(array(
            0 =>
            array(
                'id' => 1,
                'quiz_id' => 1,
                'name' => 'user1',
                'password' => 'pass1'
            )
        ));
    }
}

测验种子文件:

use Illuminate\Database\Seeder;

class QuizzesTableSeeder extends Seeder
{
    public function run()
    {
        \DB::table('quizzes')->delete();

        \DB::table('quizzes')->insert(array(
            0 =>
            array(
                'id' => 1,
                'customer_id' => 1,
                'name' => 'quizz1',
            )
        ));
    }
}

【问题讨论】:

  • 可能问题出在您的迁移文件序列中..
  • 您可以制定的解决方案是,首先创建没有该关系的表(或仅在有效时未签名),然后迁移以将该密钥签名到另一个表。从来没有遇到过这个问题,所以我不知道这是否是最好的解决方案。
  • 可能您需要创建第一个客户表,然后只有您可以在测验表中引用它。所以只需尝试先创建客户表,然后创建测验表。
  • @sandy 我已经在我的问题中解释了执行/创建的顺序并不重要,因为两个表都使用 FK 相互引用

标签: php laravel migration


【解决方案1】:

我可以建议先迁移表,然后进行新的迁移以生成外键。

php artisan make:migration add_foreign_keys

然后

class AddForeignKeysTable extends Migration
    {
        public function up()
        {
            Schema::table('customers', function (Blueprint $table) {

                $table->foreign('quiz_id')->references('id')->on('quizzes')->onDelete('set null');
            });

            Schema::table('quizzes', function (Blueprint $table) {
                $table->foreign('customer_id')->references('id')->on('customers')->onDelete('set null');
            });


        }

        public function down()
        {
            Schema::table('customers',function(Blueprint $table){
                // Place foreign key name
                $table->dropForeign('FOREIGN_KEY_NAME');
            });

            Schema::table('quizzes',function(Blueprint $table){
                // Place foreign key name
                $table->dropForeign('FOREIGN_KEY_NAME');
            });
        }
    }

这样你就可以确定如果表存在就会添加外键

【讨论】:

  • 它有效,如果在接下来的几个小时内没有更好的答案出现,我会认为它有效:) 你碰巧知道数据库种子部分的类似技巧吗?我也有同样的问题
  • 你能举个例子吗?因为我不知道你在用播种做什么。
  • 我已经更新了解释播种部分的问题
猜你喜欢
  • 1970-01-01
  • 2021-02-20
  • 2022-09-23
  • 1970-01-01
  • 2014-04-19
  • 1970-01-01
  • 2020-09-16
  • 2019-02-10
  • 1970-01-01
相关资源
最近更新 更多