1
votes

tl;dr. Solution:

Thanks to Jonas.

the problem was that the tables I was referring as foreign, were not InnoDB.

I added raw SQL statements in alter migrations and then added the foreign keys:

DB::statement("ALTER TABLE table ENGINE='InnoDB';");

Original question

First, before the Stackoverflow police bust me, I know this question is probably 83% of the database of this website. But me is special (Kidding, I know I'm not). But I've tried most of the common stuff and nothing seems to work. So probably I'm overseeing something.

Error

General error: 1215 Cannot add foreign key constraint (SQL: alter table applications add constraint applications_user_id_foreign foreign key (user_id) references users (id) on delete cascade)

This is my migration:

public function up()
{
    Schema::create("applications", function(Blueprint $table) {
        $table->engine = "InnoDB";
        $table->increments('id');
        $table->timestamps();
    });

    Schema::table('applications', function($table) {

        $table->integer('user_id')->unsigned()->index();
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        $table->integer('job_request_id')->unsigned()->index();
        $table->foreign('job_request_id')->references('id')->on('job_requests')->onDelete('cascade');
        $table->integer('status')->default(0);
    });
}

What I've already tried:

1.

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

        $table->integer('user_id')->unsigned();
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        $table->integer('job_request_id')->unsigned();
        $table->foreign('job_request_id')->references('id')->on('job_requests')->onDelete('cascade');
        $table->integer('status')->default(0);
    });
}

2.

public function up()
{
    Schema::create("applications", function(Blueprint $table) {
        $table->engine = "InnoDB";
        $table->increments('id');
        $table->timestamps();

        $table->integer('user_id')->unsigned();
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        $table->integer('job_request_id')->unsigned();
        $table->foreign('job_request_id')->references('id')->on('job_requests')->onDelete('cascade');
        $table->integer('status')->default(0);
    });
}
  1. Splitting the migration into two files (A create and an alter). Even adding each reference one by one.

4.- using DB::statement('SET FOREIGN_KEY_CHECKS=0;'); and =1 at the beginning an the end og the migration.

5.- removing the unsigned() and the index().

Might mean something:

1.- When I rollback the migration, it doesn't delete the table. So if I rollback and migrate, would give me a "already exists error".

2.- I already have migrations which reference the same items, i.e:

Schema::create('job_requests', function (Blueprint $table) {
        ...
        $table->integer('user_id')->unsigned()->nullable();
        $table->foreign('user_id')->references('id')->on('users');
        ...
    });

UPDATE

For the drop methods I've tried:

  1. For the create migrations

    public function down() { Schema::drop('applications'); }

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

2.- For the alter migrations

public function down()
{
    Schema::table('applications', function (Blueprint $table) {
        $table->dropForeign(['user_id']);
        $table->dropColumn('user_id');
        $table->dropForeign(['job_request_id']);
        $table->dropColumn('job_request_id');
    });
}

UPDATE 2:

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->increments('id');
        $table->string('first_name');
        $table->string('last_name')->nullable();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
}

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

public function up()
{
    Schema::create('job_requests', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('status')->default(0);
        $table->integer('user_id')->unsigned()->nullable();
        $table->foreign('user_id')->references('id')->on('users');
        $table->timestamps();
    });
}

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

I added three more alter migration:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->engine = "InnoDB";
    });
}

///////////////////////////

public function up()
{
    Schema::table('job_requests', function (Blueprint $table) {
        $table->engine = "InnoDB";
    });
}

///////////////////////////

public function up()
{
    Schema::table('applications', function (Blueprint $table) {
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        $table->foreign('job_request_id')->references('id')->on('job_requests')->onDelete('cascade');
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::table('applications', function (Blueprint $table) {
        $table->dropForeign(['user_id']);
        $table->dropForeign(['job_request_id']);
    });
}

Without luck yet.

2
Can you show the down methods for your migrations? Also, when you say it doesn't delete the table, I'm assuming you want it to?Rwd
(I've updated the question). Yes, I mean, delete it when rolling back.Jorge Anzola
Your question doesn't contain the actual problem. Which foreign key doesn't work? What's the error?Jonas Staudenmeir
Both. (I've tried them both separately also)Jorge Anzola
You can't change the table engine like that. You have to use raw SQL: DB::statement("ALTER TABLE users ENGINE='InnoDB';");Jonas Staudenmeir

2 Answers

2
votes

The referenced tables also have to use the InnoDB engine.

You can change them with raw SQL statements:

DB::statement("ALTER TABLE users ENGINE='InnoDB';");
DB::statement("ALTER TABLE job_requests ENGINE='InnoDB';");
0
votes

for deleting the table:

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