I have posts table:
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('imid');
$table->string('name');
$table->text('body');
$table->timestamps();
});
and
images table:
Schema::create('images', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('imid');
$table->string('name')->nullable();
$table->longText('image_path')->nullable();
$table->timestamps();
});
I am trying to add a foreign field to existing posts table in a separate migration:
public function up()
{
Schema::table('posts', function (Blueprint $table) {
$table->foreign('imid')->references('imid')->on('images')->onDelete('cascade');
});
}
public function down()
{
Schema::table('posts', function (Blueprint $table) {
$table->dropColumn('imid');
});
}
But when I run
php artisan migrate
I get error:
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `posts` add constraint `posts_imid_foreign` foreign key (`imid`) references `images` (`imid`) on delete cascade)
It seems I do it right. What am I missing here?
Check that both your tables have the columns for which you create the foreign key (imid) and that these columns have the same types. You can use the following commands to do this:
DESCRIBE posts;
DESCRIBE images;
Next, check if posts table has no imid values which point to non-existing records in the images table (If they are - connect them to existing ones or remove them)
SELECT posts.id, posts.imid FROM posts
LEFT JOIN images ON posts.imid = images.imid
WHERE images.id IS NULL;
Make sure your tables are using InnoDB engine
SHOW TABLE STATUS WHERE name = 'posts';
if Engine != InnoDB then run:
ALTER TABLE posts ENGINE = InnoDB;
Finally, I suggest that you change the down method of your migration so that it does the reverse of the up method:
Schema::table('posts', function (Blueprint $table) {
$table->dropForeign('posts_imid_foreign');
});
Related
I'm trying to create foreign keys in Laravel however when I migrate my table using artisan i am thrown the following error:
SQLSTATE[HY000]: General error: 1005 Can't create table `bright`.`carts` (errno: 150 "Foreign key constraint is incorrectly formed") (SQL: alter table `carts` add constraint `carts_product_id_foreign` foreign key (`product_id`) references `products` (`id`) on delete cascade)
My migration code is as so: carts migration file
public function up()
{
Schema::create('carts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('product_id')->unsigned();
$table->integer('customer_id')->unsigned();
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
$table->foreign('customer_id')->references('id')->on('customers')->onDelete('cascade');
$table->string('quantity');
});
}
products migration file
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('unit');
$table->decimal('price', 6, 3);
$table->string('img_url');
$table->string('description');
$table->integer('sold');
$table->integer('in_stock');
});
}
customers migration file
public function up()
{
Schema::create('customers', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('first_name');
$table->string('last_name');
$table->string('phone_number');
$table->string('address');
$table->string('zip')->nullable();
$table->string('email')->unique();
$table->string('user_name')->unique();
$table->string('password');
});
}
Any ideas as to what I've done wrong, I want to get this right now, as I've got a lot of tables I need to create e.g. carts, products, customers. Ideally I want to create carts table which hold this data with the foreign keys, i..e product_id and cart_id
Try using this structure.
$table->foreignIdFor(Product::class);
$table->foreign('product_id')->references('id')->on('products');
$table->foreignIdFor(Customer::class);
$table->foreign('customer_id')->references('id')->on('customers');
Also make sure, your products and customers migrations run before your carts migrations, and your models are imported to your migrations.
You can use like this.
$table->unsignedBigInteger('product_id')->nullable();
$table->foreign('product_id')->references('id')->on('products');
$table->unsignedBigInteger('customer_id')->nullable();
$table->foreign('customer_id')->references('id')->on('customers');
I'm trying to make "categories" migration, where each category refers it's parent category by ID in the same table.
Migration:
Schema::create('categories', function (Blueprint $table) {
$table->string('id', 36)->primary();
$table->string('parent_id', 36)->nullable();
$table->foreign('parent_id')->references('id')->on('categories');
$table->string('name');
});
But i'm getting next error:
Illuminate\Database\QueryException : SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table categories add constraint categories_parent_id_foreign foreign key (parent_id) references categories (id))
Field types are the same, and I don't know, what to do.
Removing "->nullable()" has no effect.
Laravel Framework version 6.20.7
Thanks.
Add the foreign key constraint in another run like as below
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->string('id', 36)->primary();
$table->string('parent_id', 36)->nullable();
$table->string('name');
});
Schema::table('categories',function (Blueprint $table){
$table->foreign('parent_id')->references('id')->on('categories');
});
}
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');
I user below tutorial for laravel categories :
Laravel categories with dynamic deep paths
I use below code same tutorial for migration :
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->string('slug');
$table->integer('parent_id')->unsigned()->default(0);
$table->timestamps();
});
Schema::table('categories', function (Blueprint $table) {
$table->foreign('parent_id')->references('id')->on('categories')->onUpdate('cascade')->onDelete('cascade');
});
}
but I have below error :
SQLSTATE[HY000]: General error: 1005 Can't create table 'xxx'.'#sql-453_147' (errno: 150 "Foreign key constraint is incorrectly formed")
(SQL: alter table 'categories' add constraint 'categories_parent_id_foreign' foreign key ('parent_id') references 'categories' ('id') on delete cascade on update cascade)
Thanks for help
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('categories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->string('slug');
$table->bigInteger('parent_id')->unsigned()->default(0);
$table->timestamps();
});
Schema::table('categories', function (Blueprint $table) {
$table->foreign('parent_id')->references('id')->on('categories')->onUpdate('cascade')->onDelete('cascade');
});
}
The problem is because of the difference of the column types. So unlike the tutorial you are using bigIncrements which means big integer for the ID and using the default integer for the parent_id. Try changing the id to this:
$table->increments('id');
or your parent_id to this:
$table->bigInteger('parent_id')->unsigned()->default(0);
I have two tables like this
Books
id|book_name|writter_id
1|Artemis|1
Writters
id|writter_name
1|Jane Doe
both of the tables have a relationship like this
Book model return $this->belongsTo('App\Writter', 'writter_id');
Writter model return $this->hasMany('App\Book', 'writter_id');
books.index.blade.php
<p>{{ $book->writter->writter_name }}</p>
create books
public function up()
{
Schema::create('books', function (Blueprint $table) {
$table->increments('id');
$table->string('book_name', 100)->unique();
$table->integer('writter_id')->unsigned();
$table->timestamps();
});
}
create writter
public function up()
{
Schema::create('writters', function (Blueprint $table) {
$table->increments('id');
$table->string('writter_name', 100);
$table->timestamps();
});
// Set Foreign Key
Schema::table('books', function (Blueprint $table) {
$table->foreign('writter_id')
->references('id')
->on('writers')
->onDelete('cascade')
->onUpdate('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
// Drop Foreign Key di kolom id_penulis di table books
Schema::table('books', function(Blueprint $table) {
$table->dropForeign('books_writter_id_foreign');
});
Schema::drop('writters');
}
Every time i delete the writters (for an example like jane doe above) the books data still have the writter_id So the index view throw me an error.
Is it possible to delete the data/row from the writters table, and delete the writter_id on the books in the same time?
Edit your books table migration and add foreign keys
$table->integer('writter_id')->unsigned()->nullable();
Schema::table('books', function($table) {
$table->foreign('writter_id')->references('id')->on('writters')->onDelete('set null');
});
As you see it sets null on writter delete
For make youre migration file, do you use foreign key ?
With foreign key you can add a method for on Delete.
Foreign key Documentation
migration.php
$table->integer('writter_id')->unsigned();
$table->foreign('writter_id)->references('id')->on('writters)->onDelete('cascade');
It's will be work
If you haven't set up foreign keys on your tables, removing a row from a table won't update the column referencing to that row.
To solve this we can set up foreign keys with the schema builder.
You can create a new migration file or modify your existing migrations if you don't care about your current database values.
Create a new migration file with php artisan make:migration. Inside that file, use these methods (don't forget to run composer require doctrine/dbal before running the migration):
public function up() {
// Remove current foreign keys and index.
Schema::table('books', function (Blueprint $table) {
$table->dropForeign('books_writter_id_foreign');
$table->dropIndex('books_writter_id_foreign');
});
// Add new foreign and allow books to now have a writter by using `NULL`.
Schema::table('books', function (Blueprint $table) {
$table->integer('writter_id')->unsigned()->nullable()->change(); // Before changing a column, be sure to add the doctrine/dbal dependency to your composer.json file.
$table->foreign('writter_id')
->references('id')
->on('writers')
->onDelete('SET NULL');
});
}
public function down() {
// Revert to previous values.
Schema::table('books', function (Blueprint $table) {
$table->dropForeign('books_writter_id_foreign');
$table->dropIndex('books_writter_id_foreign');
$table->integer('writter_id')->unsigned()->change();
$table->foreign('writter_id')
->references('id')
->on('writers')
->onDelete('cascade')
->onUpdate('cascade');
});
}
Using ->onDelete('SET NULL') on the foreign key will set the value to NULL when the referenced value is deleted from the referenced table.
In your blade file you can now check if the book have a writer before outputting it:
#if ($book->writter_id)
<p>{{ $book->writter->writter_name }}</p>
#endif