Laravel 5.8 Schema adding foreign key not working - laravel-5

I'm trying to create foreign keys in Laravel 5.8 and when I migrate my table using Artisan the foreign key not set. In the cities table and provinces table, all id fields are unsigned integers. I'm working with wamp64 on Windows 10.
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->integer('city_id')->unsigned();
$table->integer('province_id')->unsigned();
// table Foreign Key
$table->foreign('city_id')->references('id')->on('cities');
$table->foreign('province_id')->references('id')->on('provinces');
});
}

because you have already users rows within your users database table.
to achieve that you should make these new fields city_id and province_id as nullable as default value.
so your migration should be like below :
public function up()
{
Schema::table('users', function (Blueprint $table) {
// I have added here nullable for both city_id and province_id
$table->integer('city_id')->unsigned()->nullable();
$table->integer('province_id')->unsigned()->nullable();
// table Foreign Key
$table->foreign('city_id')->references('id')->on('cities');
$table->foreign('province_id')->references('id')->on('provinces');
});
}

Related

Laravel migrations change foreign key to be nullOnDelete() and nullable(true)

I have this migration where I created a foreign key the first time:
Schema::table('user_plays_quizzes', function (Blueprint $table) {
$table->bigInteger('quiz_id')->unsigned()->change();
$table->foreign('quiz_id')->references('id')->on('quizzes');
});
Now I have a new migration, where I want to update this foreign key to be nullable(true) and to be nullOnDelete().
I tried it so many times, but there are always errors, I feel like this is the closest approach:
Schema::table('user_plays_quizzes', function (Blueprint $table) {
$table->bigInteger('quiz_id')->unsigned()->nullable(true)->change();
$table->foreign('quiz_id')->references('id')->on('quizzes')->nullOnDelete();
});
Sadly it also does not work:
SQLSTATE[HY000]: General error: 1005 Can't create table d039e62e.user_plays_quizzes (errno: 121
"Duplicate key on write or update") (SQL: alter table user_plays_quizzes add constraint user_plays_quizzes_quiz_id_foreign for
eign key (quiz_id) references quizzes (id) on delete set null)
No Idea how to solve it. I cant even drop the keys and recreate them aswell. Maybe someone has an idea how I can update it with a migration
Why can't you drop the key and recreate it?
public function up()
{
Schema::table('user_plays_quizzes', function (Blueprint $table) {
// Drop fk constraint on quiz_id column
$table->dropForeign(['quiz_id']);
// Alter quiz_id column
$table->bigInteger('quiz_id')->unsigned()->nullable(true)->change();
// Add new fk constraint on quiz_id column
$table->foreign('quiz_id')->references('id')->on('quizzes')->nullOnDelete();
});
}
public function down()
{
Schema::table('user_plays_quizzes', function (Blueprint $table) {
// Drop fk constraint on quiz_id column
$table->dropForeign(['quiz_id']);
// Restore quiz_id column to how it was before
$table->bigInteger('quiz_id')->unsigned()->nullable(false)->change();
// Restore original fk constraint on quiz_id column
$table->foreign('quiz_id')->references('id')->on('quizzes');
});
}

Change foreign key unsignedBigInteger field to be text field in migration laravel

I have a table foo and a migration for it like this (just showing the up method):
public function up()
{
Schema::table('foo', function (Blueprint $table) {
$table->unsignedBigInteger('boo_id');
});
Schema::table('foo', function (Blueprint $table) {
$table->foreign('boo_id')->references('id')->on('boos');
});
}
So I have a boo_id foreign key on boos.id. Now I would like to create a migration that will alter the field boo_id to be text and not be foreign key anymore. How can I do that?
You first need to delete the foreign key and the index created for the foreign and then change the data type of the column. A migration like this would help:
public function up()
{
Schema::table('foo', function (Blueprint $table) {
$table->dropForeign('foo_boo_id_foreign');
$table->dropIndex('foo_boo_id_foreign');
});
Schema::table('foo', function (Blueprint $table) {
$table->text('boo_id')->change();
});
}
Please note that they must be in two seperate Schema::table bodies, otherwise you will face an error: Syntax error or access violation: 1170 BLOB/TEXT column 'boo_id' used in key specification without a key length (SQL: ALTER TABLE foo CHANGE boo_id boo_id TEXT DEFAULT NULL). Also note that the names passed to dropForeign and dropIndex functions might be different for you, you should check that in your DB to be sure, as that naming convention is not mandatory.

Add laravel migrations with foreign keys

I have created a table called 'users'.There are tables called 'companies','designations','departments'.I want to add company_id,designation_id,department_id columns to users table as foreign keys.
I tried this but it didn't work
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->integer('department_id');
$table->integer('company_id');
$table->integer('designation_id');
$table->foreign('department_id')->references('id')->on('departments')->onDelete('restrict')->onUpdate('restrict');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('restrict')->onUpdate('restrict');
$table->foreign('designation_id')->references('id')->on('designations')->onDelete('restrict')->onUpdate('restrict');
});
}
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn(['department_id','company_id','designation_id']);
});
}
When I migrate the migration it shows this error.
Illuminate\Database\QueryException : SQLSTATE[HY000]: General
error: 1005 Can't create table lanwadb.users (errno: 150 "Foreign
key constraint is incorrectly formed") (SQL: alter table users add
constraint users_department_id_foreign foreign key (department_id)
references departments (id) on delete restrict on update restrict)
Designation migration as follows,
public function up()
{
Schema::create('designations', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestampsTz();
});
}
Department migration as follows,
public function up()
{
Schema::create('departments', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('company_id');
$table->timestampsTz();
});
}
```
To make relationship the foreign key field should be indexed. Here you have three columns you want to use as foreign key 'company_id', 'department_id' and 'designation_id'. In Laravel migration you can use unsigned() function to index them.
Example:
$table->integer('department_id')->unsigned();
$table->integer('company_id')->unsigned();
$table->integer('designation_id')->unsigned();
There is another function called unsignedInteger() by which you can make a column both Integer and Unsigned.
$table->unsignedInteger('department_id');
$table->unsignedInteger('company_id');
$table->unsignedInteger('designation_id');
use this:
$table->integer('department_id')->unsigned()->nullable();
$table->integer('company_id')->unsigned()->nullable();
$table->integer('designation_id')->unsigned()->nullable();
$table->foreign('department_id')->references('id')->on('departments')->onDelete('cascade')->onUpdate('cascade');
$table->foreign('company_id')->references('id')->on('departments')->onDelete('cascade')->onUpdate('cascade');
$table->foreign('designation_id')->references('id')->on('departments')->onDelete('cascade')->onUpdate('cascade');

How to create same foriegn_key for two or multiple tables id in laravel

In my project i have Journals table, Monthlies table, Loan table, Investment table. Journal table has payment_id which i want to give foreign key for the monthlies, loan and investment tables ID. I have tried this but in migration it occurs error "duplicate key on write or update"
what i want to do is , I am trying to insert loan, investment, monthlies id on journals table payment_id when loan, investment, monthlies are created. I can insert only one tables id on journals table payment_id (through foreign key relationship in migration) not multiple...how can i do that?
public function up()
{
Schema::create('journals', function (Blueprint $table) {
$table->increments('id');
$table->double('amount');
$table->integer('payment_id')->unsigned();
$table->enum('payment_format', ['monthly', 'investment', 'loan', 'income', 'expense', 'others']);
$table->string('short_description');
$table->integer('created_by')->unsigned();
$table->integer('updated_by')->unsigned();
$table->dateTime('deleted_at');
$table->timestamps();
$table->foreign('payment_id')->references('id')->on('monthlies')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('payment_id')->references('id')->on('investments')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('payment_id')->references('id')->on('loans')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('created_by')->references('id')->on('users')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('updated_by')->references('id')->on('users')
->onUpdate('cascade')->onDelete('cascade');
});
}
You can't do that in laravel. The same column can not be used as a foreign key to 3 other tables. However, you can do this in Laravel without using foreign keys on the database level.
Your migration:
Schema::create('journals', function (Blueprint $table) {
$table->increments('id');
$table->double('amount');
$table->integer('payment_id')->unsigned();
$table->enum('payment_format', ['monthly','investment','loan','income','expense','others']);
$table->string('short_description');
$table->integer('created_by')->unsigned();
$table->integer('updated_by')->unsigned();
$table->dateTime('deleted_at');
$table->timestamps();
$table->foreign('created_by')->references('id')->on('users')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('updated_by')->references('id')->on('users')
->onUpdate('cascade')->onDelete('cascade');
});
In your Journal model, define the relationship to your payment:
public function payment() {
switch($this->payment_format) {
case 'loan':
return $this->belongsTo(Loan::class, 'payment_id');
case 'monthly':
return $this->belongsTo(Monthly::class, 'payment_id');
case 'investment':
return $this->belongsTo(Investment::class, 'payment_id');
default:
// ??
break;
}
}
Now, by calling $journal->payment you get the proper object back based on the value in your payment_format field.
Try this:
$table->unsignedInteger('payment_id');
$table->foreignId('payment_id','monthlies')->.constrained('monthlies');
$table->foreignId('payment_id','items')->constrained('items');
In this code foreignId(column_name,'name_of_key').
Hope this helps.

How to define foreign keys in migrations?

The Problem
I want to add foreign keys to tables. When I run my first migration create_posts_table that looks like this:
Schema::create('posts', function(Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id');
$table->unsignedInteger('user_id')->index();
// . . .
});
Schema::table('posts', function(Blueprint $table)
{
$table->foreign('user_id')->references('id')
->on('users')->onDelete('cascade');
});
The following error is thrown:
[Illuminate\Database\QueryException] SQLSTATE[HY000]:
General error: 1215 Cannot add foreign key constraint (SQL: alter table
posts add constraint posts_user_id_foreign foreign key (user_id) references users (id) on delete cascade)
This is caused because the users table is not created yet, hence the failure to create the users' referencing foreign key on the posts table.
Possible Solution
The solution to this problem would be to add the foreign keys with a new migration after all of the tables had been created. However, it seems clunky to me.
The question
How can I define the foreign keys inside their respective tables' migrations, instead of adding them separately with the different migration after all of the tables had been created?
You can perform multiple migrations in the same migration file. If you have a posts table where you want a foreign key to the users table, but the users table does not yet exist, you either have to do it in the users table migration file after the users table has been created - or you have to do a separate migration, like you said. You can't "save" instructions for later in migrations.
In laravel way is keeping separate migration files for different tables with indexing, primary key & foreign keys.....
CreateUsersTable
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('email');
$table->string('password', 60);
$table->enum('status', ['0', '1'])->default('0');
$table->rememberToken();
$table->nullableTimestamps();
$table->unique('email');
});
}
public function down()
{
Schema::drop('users');
}
}
CreatePostsTable
class CreatePostsTable extends Migration
{
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
});
}
public function down()
{
Schema::drop('posts');
}
}

Resources