我试图在Laravel中创建外键,但是当我使用artisan迁移我的表时,我抛出了以下错误:

[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL
: alter table `priorities` add constraint priorities_user_id_foreign foreign 
key (`user_id`) references `users` (`id`))     

我的迁移代码如下:

优先级迁移文件

public function up()
{
    //
    Schema::create('priorities', function($table) {
        $table->increments('id', true);
        $table->integer('user_id');
        $table->foreign('user_id')->references('id')->on('users');
        $table->string('priority_name');
        $table->smallInteger('rank');
        $table->text('class');
        $table->timestamps('timecreated');
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    //
    Schema::drop('priorities');
}

用户迁移文件

public function up()
{
    //
    Schema::table('users', function($table)
    {
    $table->create();
    $table->increments('id');
    $table->string('email');
    $table->string('first_name');
    $table->string('password');
    $table->string('email_code');
    $table->string('time_created');
    $table->string('ip');
    $table->string('confirmed');
    $table->string('user_role');
    $table->string('salt');
    $table->string('last_login');

    $table->timestamps();
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    //
        Schemea::drop('users');
}

关于我做错了什么,我现在想要得到这个,因为我有很多表,我需要创建例如用户,客户端,项目,任务,状态,优先级,类型,团队。理想情况下,我想创建表持有这些数据与外键,即clients_project和project_tasks等。

希望有人能帮我开始。


当前回答

我在laravel 5.8有这个问题,我修复了这个代码,如laravel文档中所示,在我添加外键的地方。

$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

然后我运行$ PHP artisan migrate:refresh

由于这种语法相当冗长,Laravel提供了额外的、更简洁的方法,使用约定来提供更好的开发体验。上面的例子可以这样写:

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained()->onDelete('cascade');
});

其他回答

在我的例子中,我引用了字符串user_id列上的整数id列。我改变了:

表- >字符串(“user_id”)

to:

表- >美元整数(user_id) - >无符号();

希望它能帮助到一些人!

使用Laravel 5.3也有同样的问题。

解决方案是使用unsignedInteger而不是integer('name')->unsigned()。

这就是有效的方法

$table->unsignedInt('column_name');
$table->foreign('column_name')->references('id')->on('table_name');

这样做的原因是,当使用integer('name')->unsigned时,在表中创建的列的长度为11,但当使用unsigedInteger('name')时,列的长度为10。

长度10是使用Laravel时主键的长度,因此列的长度匹配。

在最初的问题之后的几年,我使用laravel 5.1,我有同样的错误,因为我的迁移是由计算机生成的,所有的日期代码都是相同的。我遍历了所有提出的解决方案,然后重构以找到错误源。

在遵循laracast和阅读这些文章时,我相信正确答案与Vickies的答案相似,除了您不需要添加单独的模式调用。你不需要设置Innodb,我假设laravel现在正在做这件事。

迁移只需要正确地计时,这意味着您将(稍后)修改需要外键的表的文件名中的日期代码。另外,对于不需要外键的表,降低数据码。

修改日期码的好处是您的迁移代码将更容易阅读和维护。

到目前为止,我的代码是通过调整时间代码来向后推需要外键的迁移。

但是我有几百个表,所以在最后,我有最后一个表用于外键。只是为了让事情顺利进行。我假设我将把它们拉到正确的文件中,并在测试时修改数据码。

例如:文件2016_01_18_999999_create_product_options_table。它需要创建产品表。看一下文件名。

 public function up()
{
    Schema::create('product_options', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('product_attribute_id')->unsigned()->index();
        $table->integer('product_id')->unsigned()->index();
        $table->string('value', 40)->default('');
        $table->timestamps();
        //$table->foreign('product_id')->references('id')->on('products');
        $table->foreign('product_attribute_id')->references('id')->on('product_attributes');
        $table->foreign('product_id')->references('id')->on('products');


    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::drop('product_options');
}

产品表:首先需要迁移这个表。2015年_01_18_000000_create_products_table

public function up()
{
    Schema::create('products', function (Blueprint $table) {
        $table->increments('id');

        $table->string('style_number', 64)->default('');
        $table->string('title')->default('');
        $table->text('overview')->nullable();
        $table->text('description')->nullable();


        $table->timestamps();
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::drop('products');
}

最后是我临时用来解决问题的文件,我将在为我命名为9999_99_9999_create_foreign_keys .php的模型编写测试时重构该文件。当我把这些键拉出来的时候,这些键就被注释了,但是你明白我的意思。

    public function up()
    {
//        Schema::table('product_skus', function ($table) {
//            $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
//    });

    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
//        Schema::table('product_skus', function ($table)
//        {
//            $table->dropForeign('product_skus_product_id_foreign');
//        });

在我的情况下,我只是改变了手动执行迁移的顺序,因此首先创建表用户。

在文件夹database/migrations/你的迁移文件名有这样的格式: year_month_day_hhmmss_create_XXXX_table.php

只是重命名创建用户文件,这样你的表优先级表的创建日期设置晚于用户日期(甚至晚一秒就足够了)

在我的案例中,问题在于迁移时机,在创建迁移时要小心,首先创建子迁移,而不是基础迁移。因为如果你先创建base migration,有外键就会寻找子表,不会有抛出异常的表。

进一步:

当您创建迁移时,它的开头有一个时间戳。假设你已经创建了一个迁移猫,它看起来像2015_08_19_075954_the_cats_time.php,它有这样的代码

<?php

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

class TheCatsTime extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('cat', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');  
            $table->date('date_of_birth');
            $table->integer('breed_id')->unsigned()->nullable(); 
        });

        Schema::table('cat', function($table) {
        $table->foreign('breed_id')->references('id')->on('breed');
      });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('cat');
    }
}

在创建基表之后,创建另一个迁移品种,即子表,它有自己的创建时间和日期戳。 代码如下所示:

<?php

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

class BreedTime extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('breed', function (Blueprint $table) {
             $table->increments('id');    
             $table->string('name');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('breed');
    }
}

看起来这两个表都是正确的,但当你运行PHP artisan迁移。它会抛出一个异常,因为迁移会首先在你的数据库中创建基表因为你先创建了这个迁移,我们的基表有外键约束,它会寻找子表,而子表不存在,这可能是一个异常。

So:

首先创建子表迁移。 在创建子迁移之后创建基表迁移。 PHP工匠迁移。

做就行了