Can I make email as a foreign key ? $table->foreignId('email')->constrained('users')->onDelete('CASCADE'); . I wrote a seeder and is for an integer value for emai. I need to make email unique
This is my users table
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
To create an Foreign Key association with email column of users table, you cannot use foreignId method as it creates unsignedBigInteger equivalent column.
You can create the foreign key association as
//Some other table - for eg lets say posts
Schema::create('posts', function(Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body');
$table->string('author_email');
$table->foreign('author_email') // a column on posts table
->references('email') //name of the column on users (referenced) table
->on('users') //name of the referenced table
->onDelete('cascade'); //constrain
});
Then using this foreign key association you can define the author relation in Post model linking it to the User model
//Post.php - eloquent model class
public function author()
{
return $this->belongsTo(User::class, 'author_email', 'email');
}
Note: For this to work as expected, email column on users table must contain unique values i.e have a unique index (as you have in the migration of users table)
Laravel Docs - Migrations - Foreign Key Constraints
I want to delete a record in category table wherein it will also delete the subcategory record which has a the foreign key of category. How can I do this?
Also, an explanation would help as why it has happened. Thank you!
Controller
public function destroy(Category $category)
{
// return $category;
Category::where('id', $category->id)->delete();
Subcategory::where('category_id', $category->id)->delete();
return back();
}
Category migration
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Sub-category mgiration
Schema::create('subcategories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('category_id')->unsigned();
$table->string('subcatname');
$table->string('name');
$table->timestamps();
$table->foreign('category_id')->references('id')->on('categories');
});
this is simple because of the default delete: Restrict option in foreign key.
1.Add on delete cascade option to foreign key. This option will automatically remove any associated records from the subcategoires table when you delete the category record.
The modified fk statement looks like as follows:
ADD CONSTRAINT `category_subcategory_foreign` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE;
or you can go through
Laravel also provides support for creating foreign key constraints, which are used to force referential integrity at the database level. For example, let's define a user_id column on the posts table that references the id column on a users table:
Schema::table('posts', function (Blueprint $table) {
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
});
You may also specify the desired action for the "on delete" and "on update" properties of the constraint:
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
You need onDelete method. Just from Docs
$table->foreign('category_id')
->references('id')->on('categories')
->onDelete('cascade');
I have 3 tables to connect each other. Tables name's roles, role_user, and users. I want to make migration on laravel and adding some constraint. and here's what in my role tables migration:
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('description');
$table->timestamps();
});
and here's my Users table migration:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('username')->unique();
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->boolean('active')->default(0);
$table->softDeletes();
$table->rememberToken();
$table->timestamps();
});
and here's my role_user table migration:
Schema::create('role_user', function (Blueprint $table) {
$table->integer('role_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->unique(['role_id', 'user_id']);
$table->foreign('role_id')->references('id')->on('roles')
->onDelete('cascade')->onUpdate('cascade');
$table->foreign('user_id')->references('id')->on('users')
->onDelete('cascade')->onUpdate('cascade');
});
in my Migration order i put roles table on top of users already but i got this kind of errors:
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `role_user` add constraint `role_user_role_id_foreign` foreign key (`role_id
`) references `roles` (`id`) on delete cascade on update cascade)
[PDOException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint
Probably your problem was with the order of creation of migrations.
Laravel runs the migrations in order of creation using the timestamp in the file name , because of that, if you created them in the following order:
roles in 2018_06_02_023539_create_roles_table
role_user in 2018_06_02_023800_create_role_user_table
users in 2018_06_02_023815_create_users_table
The table users would not exist when referenced in the table role_user, thus causing an SQL error.
The most simple fix that you could do is renaming the role_user migration file in this way:
2018_06_02_023800_create_role_user_table => 2018_06_02_023820_create_role_user_table
Try this one on the pivot table
public function up()
{
Schema::create('role_user', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('role_id');
$table->unsignedBigInteger('user_id');
$table->timestamps();
$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
I delete all my table and left just 4 tables :
create_user_table,
create_password_reset,
create_roles_table,
create_role_user
and everything works fine.
Till now I don't understand what makes these errors although I already put the same orders.
in table "role_user" replace columns type from integer to bigIncrements
When migrating my DB, this error appears. Below is my code followed by the error that I am getting when trying to run the migration.
Code
public function up()
{
Schema::create('meals', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->integer('category_id')->unsigned();
$table->string('title');
$table->string('body');
$table->string('meal_av');
$table->timestamps();
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
$table->foreign('category_id')
->references('id')
->on('categories')
->onDelete('cascade');
});
}
Error message
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1005 Can't create table
meal.#sql-11d2_1 4 (errno: 150 "Foreign key constraint is
incorrectly formed") (SQL: alter
table meals add constraint meals_category_id_foreign foreign key (category_id) references categories (id) on delete
cascade)
When creating a new table in Laravel. A migration will be generated like:
$table->bigIncrements('id');
Instead of (in older Laravel versions):
$table->increments('id');
When using bigIncrements the foreign key expects a bigInteger instead of an integer. So your code will look like this:
public function up()
{
Schema::create('meals', function (Blueprint $table) {
$table->increments('id');
$table->unsignedBigInteger('user_id'); //changed this line
$table->unsignedBigInteger('category_id'); //changed this line
$table->string('title');
$table->string('body');
$table->string('meal_av');
$table->timestamps();
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
$table->foreign('category_id')
->references('id')
->on('categories')
->onDelete('cascade');
});
}
You could also use increments instead of bigIncrements like Kiko Sejio said.
The difference between Integer and BigInteger is the size:
int => 32-bit
bigint => 64-bit
#JuanBonnett’s question has inspired me to find the answer. I used Laravel to automate the process without considering the creation time of the file itself. According to the workflow, “meals” will be created before the other table (categories) because I created its schema file (meals) before categories.
That was my fault.
You should create your migration in order
for example I want my users to have a role_id field which is from my roles table
I first start to make my role migration
php artisan make:migration create_roles_table --create=roles
then my second user migration
php artisan make:migration create_users_table --create=users
php artisan migration will execute using the order of the created files
2017_08_22_074128_create_roles_table.php and 2017_08_22_134306_create_users_table check the datetime order, that will be the execution order.
files
2017_08_22_074128_create_roles_table.php
public function up()
{
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('name', 50);
$table->timestamps();
});
}
2017_08_22_134306_create_users_table
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->integer('role_id')->unsigned();
$table->string('name');
$table->string('phone', 20)->unique();
$table->string('password');
$table->rememberToken();
$table->boolean('active');
$table->timestamps();
$table->foreign('role_id')->references('id')->on('roles');
});
}
Just add ->unsigned()->index() at the end of the foreign key and it will work.
I got the same message for data type miss-matched problem.
I used bigIncrements() for 'id' and when I used it as foreign key (used bigInteger()) I got the error.
I have found the solution, bigIncrements() returns unsignedBigInteger. So need to use unsignedBigInteger() instead of bigInteger() in foreign key
Sharing this because it might help others
For me everything was in correct order, but it still didn't work. Then I found out by fiddling that the primary key must be unsigned.
//this didn't work
$table->integer('id')->unique();
$table->primary('id');
//this worked
$table->integer('id')->unsigned()->unique();
$table->primary('id');
//this worked
$table->increments('id');
if you are using ->onDelete('set null') in your foreign key definition make sure the foreign key field itself is nullable() ie
//Column definition
$table->integer('user_id')->unsigned()->index()->nullable(); //index() is optional
//...
//...
//Foreign key
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('set null');
Laravel 5.8
In the foreign key column use unsignedBigInteger to avoid mismatch foreign key data type problem . For example let us assume we have two tables questions and replies
Questions table will look:
public function up()
{
Schema::create('questions', function (Blueprint $table) {
$table->bigIncrements('id');
$table->text('body');
$table->integer('user_id')->unsigned();
$table->timestamps();
});
}
Replies table look like :
public function up()
{
Schema::create('replies', function (Blueprint $table) {
$table->bigIncrements('id');
$table->text('body');
$table->unsignedBigInteger('question_id');
$table->integer('user_id')->unsigned();
$table->foreign('question_id')->references('id')->on('questions')->onDelete('cascade');
$table->timestamps();
});
}
Migrations must be created top-down.
First create the migrations for the tables who don't belong to anyone.
Then create the migrations for tables that belong to the previous.
Simplified answer to the table engine problem:
To set the storage engine for a table, set the engine property on the schema builder:
Schema::create('users', function ($table) {
$table->engine = 'InnoDB';
$table->increments('id');
});
From Laravel Docs: https://laravel.com/docs/5.2/migrations
In my case, the new laravel convention was causing this error.
Just by a simple swap of the table creation id did the trick.
$table->increments('id'); // ok
, instead of:
$table->bigIncrements('id'); // was the error.
Already working with Laravel v5.8, never had this error before.
I had to face the same problem at Laravel 6. I solve this following way.
I think it helps you or others:
$table->bigIncrements('id');
$table->bigInteger('user_id')->unsigned(); //chnage this line
$table->bigInteger('category_id')->unsigned(); //change this line
---
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
$table->foreign('category_id')
->references('id')
->on('categories')
->onDelete('cascade');
Incrementing ID using a "big integer" equivalent.
used bigInteger instead of Integer
If still now you got an error.
I suggest you reorder your migration file following ways:
Change the dates that form the first part of the migration filenames
So they're in the order you want (example: for
2020_07_28_133303_update_categories.php, the date & time is
2020-07-28, 13:33:03);
N.B: First must be 'categories' migration file than 'meals' migration
File.
N.B:
In Laravel 5.6,
for $table->increments('id');
use $table->integer('user_id')->unsigned();
Laravel 6: Update on 17 Jan 2020
$table->bigInteger( 'category_id' )->unsigned();
This worked well for me
In my case the problem was that one of the referenced tables was InnoDB and the other one was MyISAM.
MyISAM doesn't have support for foreign key relations.
So, now both tables are InnoDB. Problem solved.
Maybe it can be of help to anyone landing here : I just experienced this same issue, and in my case it was that I had a (composite) unique constraint set on the foreign key column BEFORE the foreign key constraint. I resolved the issue by having the "unique" statement placed AFTER the "foreign" statement.
Works:
$table->foreign('step_id')->references('id')->on('steps')->onDelete('cascade');
$table->unique(['step_id','lang']);
Doesn't work:
$table->unique(['step_id','lang']);
$table->foreign('step_id')->references('id')->on('steps')->onDelete('cascade');
Am using Laravel 8 and had the same error. The issue is that a both those columns eg users.id and meals.user_id where user_id is the foreign key need to be the same.
The users.id looks like this:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
In mySql id is an Int(10) unsinged AUTO ICREMENT.
If we go to a different table where we want to set a foreign key e.g. the one below I changed the user_id to be an unsigned() also. Previously I had written it as simply $table->integer('user_id') and this gave me the exception but now you won't encounter that error because they are both Int(10) and Unsigned:
Schema::create('users_permissions', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->integer('permission_id')->unsigned();
//Foreign Key Constraints
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade');
//Setting the primary keys
$table->primary(['user_id','permission_id']);
});
One way to get around foreign key errors is to disable checking: "SET FOREIGN_KEY_CHECKS".
This is a palliative solution, but the correct thing is really to adjust the tables and their relationships.
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
Schema::table('example', function (Blueprint $table) {
$table->integer('fk_example')->unsigned()->index();
$table->foreign('fk_example')->references('id')->on('examples');
});
DB::statement('SET FOREIGN_KEY_CHECKS=1;');
I just use $table->unsignedBigInteger('user_id'); and solve it . (laravel 5.8)
I had the same problem , so i changed the creation date of my migration , changing this , i changed the execution order of the migrations , and the needed table was created first of the table i used it as a foreign key
The order of creation of migration files should be sorted and the foreign key should have exactly similar property as the primary key in the other table.
If you are still encountering the issue use this
$table->foreignId('project_id')
->constrained()
->onUpdate('cascade')
->onDelete('cascade');
It will just look up for that table and add a foreign key to it, it works.
Remember that this is important the referenced and referencing fields must have exactly the same data type.
You should first create Categories and users Table when create "meals"
To solve the issue you should rename migration files of Category and Users to date of before Meals Migration file that create those before Meals table.
sample:
2019_04_10_050958_create_users_table
2019_04_10_051958_create_categories_table
2019_04_10_052958_create_meals_table
It is a simple question, so give a simple answer and stop beating about the bush,
change your example $table->integer('user_id')->unsigned(); to $table->BigInteger('user_id')->unsigned(); to solve the foreign key error. so change integer to BigInteger in the migration file...
Please add ->nullable() on your field and make sure that all the fields you're referring to really exist.
Check in your database reference table must have primary key && auto increment
Drop the table which you want to migrate and Run the migrate again
I just added
$table->engine = 'MyISAM';
It worked.
It is because laravel by default creates tables with InnoDB Engine.
In my case, the problem was the difference between the table's engines. In my referenced table I didn't specify the engine.
It doesn't work
// Referenced table
Schema::create('budgets', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->softDeletes();
});
// The other table
Schema::create('payment', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->integer('budget_id')->unsigned()->nullable();
$table->foreign('budget_id')
->references('id')
->on('budgets')
->onDelete('cascade');
$table->timestamps();
});
To keep it under control, I recommend setting the engine on all your migrations to create tables. (Don't trust default database settings)
It works
// Referenced table
Schema::create('budgets', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->id();
$table->timestamps();
$table->softDeletes();
});
// The other table
Schema::create('payment', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->integer('budget_id')->unsigned()->nullable();
$table->foreign('budget_id')
->references('id')
->on('budgets')
->onDelete('cascade');
$table->timestamps();
});
Using Laravel 9~
I fixed mine by setting the id to increments, and assigned the foreign key to unsignedInteger, and then sort the migration file its the corresponding order.
My solution was based from #Swooth and #Muhammad Tareq solution
public function up()
{
Schema::create('cart_items', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('session_id')->index();
$table->foreign('session_id')->references('id')->on('shopping_sessions')
->onDelete('cascade');
}
You just need to create your migrations in order. Make sure you create the tables that don't receive any foreign keys first. Then create the ones that do.
And if you have already created your migrations, just change the time or date of your migrations so that tables that do not receive any foreign keys that are created before those that do.
Simple question: I'm new to Laravel. I have this migration file:
Schema::create('lists', function(Blueprint $table) {
$table->increments('id');
$table->string('title', 255);
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->timestamps();
});
I want to update it to add onDelete('cascade').
What's the best way to do this?
Firstly you have to make your user_id field an index:
$table->index('user_id');
After that you can create a foreign key with an action on cascade:
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
If you want to do that with a new migration, you have to remove the index and foreign key firstly and do everything from scratch.
On down() function you have to do this and then on up() do what I've wrote above:
$table->dropForeign('lists_user_id_foreign');
$table->dropIndex('lists_user_id_index');
$table->dropColumn('user_id');
In Laravel 7 it can be done in one line
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
let's say you have two tables student and section , you can refer the following two table structure for adding foreign key and making onDelete('cascade') .
Table -1 :
public function up()
{
Schema::create('student', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('address');
$table->string('phone');
$table->string('about')->nullable();
$table->timestamps();
});
}
Table - 2:
public function up()
{
Schema::create('section', function (Blueprint $table) {
$table->id();
$table->bigInteger('student_id')->unsigned()->index()->nullable();
$table->foreign('student_id')->references('id')->on('student')->onDelete('cascade');
$table->string('section')->nullable();
$table->string('stream')->nulable();
$table->timestamps();
});
}
hope it will help you -:)
you can read the full article from here .
Schema::create('roles',function(Blueprint $table){
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
Schema::create('permissions',function(Blueprint $table){
$table->unsignedBigInteger('role_id');
$table->foreign('role_id')->references('id')->on('roles');
$table->string('permission');
});
As of Laravel 8:
$table->foreignIdFor(OtherClass::class)->constrained();
So simple :)
Make sure that the OtherClass migration file is running EARLIER (by filename date as usual).
If the OtherClass id is not autoincrementing, the otherclass_id would have a type of char instead of bigint, in which case->
Use this instead:
$table->foreignId('otherclass_id')->index()->constrained()->cascadeOnDelete();
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
In this example, we are stating that the user_id column references the id column on the users table. Make sure to create the foreign key column first! The user_id column is declared unsigned because it cannot have negative value.
You may also specify options for the "on delete" and "on update" actions of the constraint:
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
To drop a foreign key, you may use the dropForeign method. A similar naming convention is used for foreign keys as is used for other indexes:
$table->dropForeign('posts_user_id_foreign');
If you are fairly new to Laravel and Eloquent, try out the Laravel From Scratch series available on laracasts. It is a great guide for beginners.
Laravel 7.x Foreign Key Constraints
Laravel also provides support for creating foreign key constraints, which are used to force referential integrity at the database level. For example, let's define a user_id column on the posts table that references the id column on a users table:
Schema::table('posts', function (Blueprint $table) {
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
});
Since this syntax is rather verbose, Laravel provides additional, terser methods that use convention to provide a better developer experience. The example above could be written like so:
Schema::table('posts', function (Blueprint $table) {
$table->foreignId('user_id')->constrained();
});
Source: https://laravel.com/docs/7.x/migrations
You should create a new migration file let's say 'add_user_foreign_key.php'
public function up()
{
Schema::table('lists', function(Blueprint $table)
{
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('lists', function(Blueprint $table)
{
$table->dropForeign('user_id'); //
});
}
The run
php artisan migrate
If you want to add onDelete('cascade') on the existing foreign key, just drop the indexes and create them again:
public function up()
{
Schema::table('lists', function($table)
{
$table->dropForeign('lists_user_id_foreign');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
public function down()
{
Schema::table('lists', function($table)
{
$table->dropForeign('lists_user_id_foreign');
$table->foreign('user_id')->references('id')->on('users');
});
}
Schema::table('posts', function (Blueprint $table) {
$table->unsignedInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
});
for versions before 7x;
Schema::create('lists', function(Blueprint $table) {
$table->increments('id');
$table->string('title', 255);
$table->unsignedBigInteger('user_id')->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
for version 7+;
Since this syntax is rather verbose, Laravel provides additional, terser methods that use conventions to provide a better developer experience. When using the foreignId method to create your column, the example above can be rewritten like so:
Schema::create('lists', function(Blueprint $table) {
$table->increments('id');
$table->string('title', 255);
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
The foreignId method is an alias for unsignedBigInteger while the constrained method will use convention to determine the table and column name being referenced. If your table name does not match the convention, you may specify the table name by passing it as an argument to the constrained method:
Schema::create('lists', function(Blueprint $table) {
$table->foreignId('user_id')->constrained('users')->onDelete('cascade');
});
source: https://laravel.com/docs/7.x/migrations#foreign-key-constraints
Clear and new in laravel
$table->foreignId('book_id')->constrained();
I was doing the same but got error " id not exist" => so I changed my migration file as below :
question table migration content:
$table->id() => should change to $table->increments('id')
definitions of foreign key in Reply table:
$table->foreign('question_id')->references('id')->on('questions')->onDelete('cascade');
now your foreign key will work.
Clear, modern and Straightforward approach
suppose parent: `Book Model` and `books table`
suppose child : `Page Model` and `pages table`
$table->foreignId('book_id')->references('id')->on('books');
where book_id is is the colomn name in child (pages table)
and id is the linkage between the Parent and Child tables, books and pages tables, and books is the table name to which we are going to link