首页 > 解决方案 > 如何在 Laravel 迁移中使用多个数据库设置外键约束

问题描述

我目前正在做一个需要使用多个数据库的项目。在我的 .env 文件中,我有以下数据库变量:

DB_CONNECTION=mysql
DB_ONE_NAME=db1

DB_CONNECTION_TWO=mysql2
DB_TWO_NAME=db2

在我的 config/database.php 文件中,我有以下参考:

'mysql' => [
        'driver' => 'mysql',
        'url' => env('DATABASE_URL'),
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_ONE_NAME', 'db1'),
        'username' => env('DB_USERNAME', 'user'),
        'password' => env('DB_PASSWORD', 'root'),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8',
        'collation' => 'utf8_general_ci',
        'prefix' => '',
        'prefix_indexes' => true,
        'strict' => true,
        'engine' => 'InnoDB',
        'options' => extension_loaded('pdo_mysql') ? array_filter([
            PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
        ]) : [],
    ],

'mysql2' => [
        'driver' => 'mysql',
        'url' => env('DATABASE_URL'),
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_TWO_NAME', 'db2'),
        'username' => env('DB_USERNAME', 'user'),
        'password' => env('DB_PASSWORD', 'root'),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8',
        'collation' => 'utf8_general_ci',
        'prefix' => '',
        'prefix_indexes' => true,
        'strict' => true,
        'engine' => 'InnoDB',
        'options' => extension_loaded('pdo_mysql') ? array_filter([
            PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
        ]) : [],
    ],

在我的第一个迁移文件中,我有这个:

<?php

    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;

    class CreateUsersTable extends Migration
    {
  
      public function up()
      {
        Schema::connection('mysql')->create('users', function (Blueprint $table) {
          $table->id();
          $table->string('name');
          $table->string('email')->unique();
          $table->string('username')->unique();
          $table->timestamps();

          $table->index('id');

    });
}


    public function down()
    {
      Schema::connection('mysql')->dropIfExists('users');
    }
}

在第二个迁移表中,我有这个:

<?php

    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;

    class CreateProjectsTable extends Migration
    {
  
      public function up()
      {
        Schema::connection('mysql2')->create('projects', function (Blueprint $table) {
          $table->id();
          $table->foreignId('user_id')->nullable()->constrained('mysql.users')->onDelete('set null');
          $table->string('name')->unique();
          $table->timestamps();

          $table->index(['id', 'user_id']);

    });
}


    public function down()
    {
      Schema::connection('mysql2')->dropIfExists('projects');
    }
}

我可能做错了什么?我检查了任何重复的文件,但找不到任何错误。

同样,我最近在我的机器上将 PHP 和 MYSQL 都升级到了它们的最新版本。在 Laravel 项目上工作所需的所有扩展都已正确安装。

但是,我仍然收到此错误:

SQLSTATE[HY000]: General error: 1005 Can't create table `db2`.`projects` (errno: 150 "Foreign key constraint is incorrectly formed") (SQL: alter table `projects` add constraint `projects_user_id_foreign` foreign key (`user_id`) references `mysql`.`users` (`id`) on delete set null)

另外,当我运行这个命令时,

php artisan migrate --pretend

或者

php artisan migrate

我仍然得到同样的错误。

我也试过用这个:

$table->unsignedBigInteger('user_id')->nullable();
$table->foreign('user_id')->references('id')->on('mysql.users')->onDelete('set null');

但没有任何工作。还有其他方法可以解决这个问题吗?如果有,请给我建议。谢谢你的时间。

标签: mysqllaraveldatabasemigration

解决方案


因此,在使用不同类型的方法进行了 14 小时的测试之后,我最终得到了我所说的“你应该知道 hack”哈哈

我在迁移表中使用第二个数据库连接名称,而不是使用数据库名称。

我在外键上使用连接名称的初始代码:

  Schema::connection('mysql2')->create('projects', function (Blueprint $table) {
      $table->id();
      $table->foreignId('user_id')->nullable()->constrained('mysql.users')->onDelete('set null');
      $table->string('name')->unique();
      $table->timestamps();

      $table->index(['id', 'user_id']);
  });

现在什么有效!使用数据库名称而不是外键上的连接名称:

 Schema::connection('mysql2')->create('projects', function (Blueprint $table) {
      $table->id();
      **$table->foreignId('user_id')->nullable()->constrained('db1.users')->onDelete('set null');**
      $table->string('name')->unique();
      $table->timestamps();

      $table->index(['id', 'user_id']);
  });

因此,第二个选项工作正常。我希望这对某人也有帮助!!!


推荐阅读