I am trying to set foreign key of my 'books' table with 'categories' table using php artisan migrate, but I got the following error:
Illuminate\Database\QueryException
SQLSTATE[HY000]: General error: 1824 Failed to open the referenced table 'categories' (SQL: alter table `books` add constraint `books_category_id_foreign` foreign key (`category_id`) references `categories` (`id`))
books migration file:
public function up()
{
Schema::create('books', function (Blueprint $table) {
$table->increments('id');
$table->integer('category_id')->unsigned();
$table->foreign('category_id')->references('id')->on('categories');
$table->string("image");
$table->string("title");
$table->string("description")->nullable();
$table->string("author");
$table->string("cover");
$table->integer("nod")->nullable();// Number of downloads
$table->integer("rating")->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('books');
}
categories migration file:
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string("title");
$table->string("image");
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('categories');
}
I really need help with this to use in my mobile app API. I hope someone can help me.
The problem is on the migration itself. Have a look carefully at this
SQLSTATE[HY000]: General error: 1824 Failed to open the referenced table 'categories' (SQL: alter table `books` add constraint `books_category_id_foreign` foreign key (`category_id`) references `categories` (`id`))
You are trying to open the categories table but it basically wasn't there or wasn't created yet. If you use GUI like HeidiSQL or Navicat, or PMA, You will be able to see it.
Laravel migration takes the timestamp on the beginning of the file to decide which migration should be migrated first in sequence.
Make sure you create the categories table first before the books table (this also applies for any tables that has reference). Or simply just rename the file (change the timestamp) like E.g:
2020_01_01_1234_create_books_table.php
2020_01_01_5678_create_categories_table.php
to this
2020_01_01_1234_create_categories_table.php
2020_01_01_5678_create_books_table.php
Then run php artisan migrate:fresh to refresh your migration.
I faced the same issue with you since yesterday and I later saw my mistakes, I was able to understand the cause of the problem.
There are so many factors to consider
Make sure the date for the parent table (categories) is earlier than the date for the child table (books) so that during the migration, the parent table will be created first because the child table might want to reference id in a table that does not exist.
Make sure to follow the convention for naming
you can refactor your migration file like this
$table->foreignId('category_id')->constrained('categories');
or
$table->foreignId('category_id')->constrained();
example of one of my migration files
public function up()
{
Schema::create('project_details', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->charset = 'utf8mb4';
$table->collation = 'utf8mb4_unicode_ci';
$table->id();
$table->foreignId('project_id')->constrained()->onDelete('cascade');
$table->string('name', 150)->nullable();
$table->string('description', 600)->nullable();
$table->string('location', 150)->nullable();
$table->integer('completed_percent')->nullable()->default(0);
$table->foreignId('manager_id')->constrained('staffs');
$table->foreignId('sponsor_id')->constrained('sponsors')->nullable();
$table->foreignId('donor_id')->constrained('sponsors')->nullable();
$table->foreignId('mda_id')->constrained('sponsors')->nullable();
});
}
You try get category for book before you create category table and book table cant understand what you referenced for.
Solution #1
Declare your category table before book table, just rename date in migration file name. Category table must be created before book table.
Solution #2
Create reference after you create category table.
Remove
$table->foreign('category_id')->references('id')->on('categories');
from book migration and create references after you up category table.
categories migration file:
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string("title");
$table->string("image");
$table->timestamps();
});
Schema::table('books', function (Blueprint $table) {
$table->foreign('category_id')->references('id')->on('categories');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('categories');
}
Main idea is make all relations when all tables created.
Also, use php artisan migrate:fresh for fast wipe and recreate tables
I had the same error just right now.
It has something related to creating those migrations.
The problem I had because I refactored the table name manually and didn't take care of the connection between the tables and instantly tried to migrate them.
The solution I did and worked for me is I deleted the migrations manually and created them again using php make:magirate.
In my opinion you need to change the engine of the SQL to InnoDB, this issue was struggling with me for a lot of time all you need to do is adding
<?php
$table->engine = 'InnoDB';
?>
to the table migration file
reference :
https://web-brackets.com/discussion/4/-solved-sqlstate-hy000-general-error-1824-failed-to-open-the-referenced-table-alter-on-foreign-key-
The table (Categories) you are referencing its "id" is either not created or its created after the "books" table. You can manually delete both tables and create them again with "Categories" been first or you can manually change the date of the "Categories" to a date before the "books" and you are good to go.
Make sure you have such a table in your database. If you use a lot of database, then you need to specify the database for constrained
$connection_db = DB::connection('connection_name')->getDatabaseName();
$table->foreign('category_id')->references('id')->on("$connection_db.categories");
Make sure both the tables are created using the same engine. In my case, I created two tables with two different engines (MyISAM and InnoDB). Changing both the table engines to InnoDB did the trick.
Related
I'm building a project with Laravel version 7.25.0. I coded my migration files and they contain some foreign keys. I added nullable() at the end of each foreign key but they don't work. I looked at similar questions but none of them solved my problem. Here is my migration file's up function
{
Schema::create('tests', function (Blueprint $table) {
$table->id();
$table->string('title')->nullable();
$table->tinyInteger('level')->nullable();
$table->tinyInteger('try_count')->nullable();
$table->char('room_name')->nullable();
$table->boolean('timeless')->nullable();
$table->integer('time')->nullable();
$table->foreignId('school_id')->constrained('schools')->nullable();
$table->foreignId('year_id')->constrained('years')->nullable();
$table->foreignId('course_id')->constrained('courses')->nullable();
$table->string('type')->nullable();
$table->date('start_date')->nullable();
$table->date('end_date')->nullable();
$table->time('start_time')->nullable();
$table->time('end_time')->nullable();
$table->text('description')->nullable();
$table->boolean('timeout')->nullable();
$table->boolean('question_sorting')->nullable();
$table->timestamps();
});
}
when I migrate it with the other files and not getting any error, this is my phpmyadmin page of that table
phpadmin page table ss
Any additional column modifiers must be called before constrained,
So You must put the nullable() before constrained() like this :
$table->foreignId('course_id')->nullable()->constrained('courses');
ProductTable
public function up()
{
Schema::create('product', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('description');
$table->string('type');
$table->integer('size');
$table->integer('price');
$table->string('image')->nullable();
$table->timestamps();
});
}
When I hit submit, I got error saying base table not found
Laravel can not find the prular form of the table name that you used, just specify your table name on your model like so; And check your view aswell make sure on your resource/view you have a file named successs.blade.php
public $table = "yourTableName";
may be your table is not available in database so first add the table in
your database. in your model like this
public $table = "yourTableName";
after the define your table in your model just migrate the table in your database
php artisan make:migration
I have 3 models: User , ChangeMoney and CurrencyType, I have simple relationship with User and ChangeMoney and I want to add another relationship with ChangeMoney table with CurrencyType, but I get this error:
D:\xampp\htdocs\epay-pro>php artisan migrate
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL
: alter table `change_money` add constraint change_money_currency_id_foreig
n foreign key (`currency_id`) references `currency_type` (`id`))
current my migration is:
Schema::create('change_money',function(Blueprint $table){
$table->increments('id');
$table->tinyInteger('currency_type');
$table->string('current_money');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->integer('currency');
$table->timestamps();
});
and I don't have any problem, now I want to add other foreign key to CurrencyType table such as:
Schema::create('change_money',function(Blueprint $table){
$table->increments('id');
$table->tinyInteger('currency_type');
$table->string('current_money');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->integer('currency_id')->unsigned();
$table->foreign('currency_id')->references('id')->on('currency_type');
$table->timestamps();
});
currency_type table migration:
Schema::create('currency_type',function(Blueprint $table){
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->string('currency_type','50');
$table->char('currency_symbol','1');
$table->timestamps();
});
Migrations in Laravel runs in order. I don't now your migrations order, but I think that your change_money migration is running first than your currency_type migration. So when the aplication try to add a foreign key in ChangeMoney table to CurrencyType table, the CurrencyType table not exist yet.
Try to create a new migration to add just the relationship between ChangeMoney table and CurrencyType table
You have to remove data from both tables ('change_money', 'currency_type').
Or you can turn off the check of foreign keys. In MySQL, or in the phpmyadmin run this:
SET FOREIGN_KEY_CHECKS=0;
Run migration in Laravel: php artisan migrate
And then again turn on check of foreign keys:
SET FOREIGN_KEY_CHECKS=1;
PROBLEM SOLVED by split foreign key to other migration
class ForeignKeyBetweenChangeMoneyAndCurrencyType extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('change_money', function (Blueprint $table) {
$table->integer('currency_id')->unsigned();
$table->foreign('currency_id')->references('id')->on('currency_type');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('change_money', function(Blueprint $table) {
$table->dropForeign(' change_money_currency_id_foreign');
});
}
}
I have a database table teacher_attendances, with field:
id, name, data, attendance.
I try to generate a pivot table based on teacher_attendances table.
I want rowname as TeacherName and columnname as Date and cloumnname below mark attendance.
How to create pivot table in Laravel 4?
Have you checked out Laravel Migration and Schema Builder Documentation?
Run php artisan migrate:make create_teacher_attendances_table --create --table=teacher_attendances in the CLI to generate the file.
Then edit the file to include something like this up method
public function up()
{
Schema::create('teacher_attendances', function(Blueprint $table)
{
$table->increments('id');
// Your code here
});
}
Don't forget about foreign-keys.
You need to execute following command:
php artisan make:migration create_attendance_teacher --table="attendance_teacher"
Note : create_attendance_teacher is taken singular form for the tables attendances & teachers respectively.
As per convention try to create pivot table alphabetical order. Hence we took attendance table before teachers table.
Then, in migration script:
public function up()
{
Schema::create('teacher_attendances', function(Blueprint $table)
{
$table->increments('id');
$table->integer('attendance_id');//Foreign key from attendances table
$table->increments('teacher_id');////Foreign key from teachers table
});
}
In Laravel 4, when working with many-to-many relationships as described in the 4.2 docs, how can I actually get Laravel to create the pivot table for me?
Do I need to add something in my migrations for the two models that are involved? Do I need to manually create a migration for the pivot table? Or how does Laravel know to create the pivot table?
All I've done so far is add the belongsToMany information to the two respective models, i.e.
class User extends Eloquent
{
public function roles()
{
return $this->belongsToMany('Role');
}
}
However, that does not trigger creation of the pivot table. What step am I missing?
It appears as though the pivot table does need to be created manually (i.e. Laravel does not do this automatically). Here's how to do it:
1.) Create a new migration, using singular table names in alphabetical order (default):
php artisan make:migration create_alpha_beta_table --create --table=alpha_beta
2.) Inside the newly created migration, change the up function to:
public function up()
{
Schema::create('alpha_beta', function(Blueprint $table)
{
$table->increments('id');
$table->integer('alpha_id');
$table->integer('beta_id');
});
}
3.) Add the foreign key constraints, if desired.
(I haven't gotten to that bit, yet).
Now to seed, say, the alpha table, using keys from beta, you can do the following in your AlphaTableSeeder:
public function run()
{
DB::table('alpha')->delete();
Alpha::create( array(
'all' => 'all',
'your' => 'your',
'stuff' => 'stuff',
) )->beta()->attach( $idOfYourBeta );
}
I use Jeffrey Way's Laravel-4-Generators or Laravel-5-Generators-Extended.
then you can just use this artisan command:
php artisan generate:pivot table_one table_two
To expand on Ben's answer (I tried to edit it but reviewers said it added too much):
To add the foreign key constraints, make sure if alpha id is unsigned, alpha_id is also unsigned in the pivot table. This migration would run after (2) in Ben's answer since it alters the table created then.
public function up()
{
Schema::table('alpha_beta', function(Blueprint $table)
{
$table->foreign('alpha_id')->references('id')->on('alpha');
$table->foreign('beta_id')->references('id')->on('beta');
});
}
For Many to Many relationships you can create the Migration file of the Database manually like this:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateAccountTagTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('account_tag', function (Blueprint $table) {
// $table->timestamps(); // not required
// $table->softDeletes(); // not required
$table->integer('account_id')->unsigned();
$table->foreign('account_id')->references('id')->on('accounts');
$table->integer('tag_id')->unsigned()->nullable();
$table->foreign('tag_id')->references('id')->on('tags');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('account_tag');
}
}
Note: in case you have timestamps on the pivot table you must set withTimestamps on the relationship of both ends like this:
return $this->belongsToMany(\Mega\Modules\Account\Models\Tag::class)->withTimestamps();
.
return $this->belongsToMany(\Mega\Modules\Account\Models\Account::class)->withTimestamps();
Create new migration:
php artisan make:migration create_alpha_beta_table --create=alpha_beta
Inside the newly created migration:
public function up() {
Schema::create('alpha_beta', function(Blueprint $table) {
$table->increments('id');
$table->unsignedBigInteger('alpha_id');
$table->unsignedBigInteger('beta_id');
// foreign keys
$table->foreign('alpha_id')->references('id')->on('alphas');
$table->foreign('beta_id')->references('id')->on('betas');
});
}
for the latest Laravel's versions:
composer require --dev laracasts/generators
php artisan make:migration:pivot table1 table2
In addition to all the above answers
There is no need to have an AI index for a pivot table. Its uniquely defined by its touple (key1,key2).
The primary key should be the composition (key1,key2). The benefits are that the touples are unique and all queries are best optimized.
So here comes a real life example:
Schema::create('bill_user', function (Blueprint $table) {
// unsigned is needed for foreign key
$table->integer('user_id')->unsigned();
$table->integer('bill_id')->unsigned();
$table->primary(['user_id', 'bill_id']);
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
$table->foreign(bill_id')
->references('id')->on('bills')
->onDelete('cascade');
});
following the latest laravel conventions, the up method should be
public function up() {
Schema::create('country_timezone', function (Blueprint $table) {
$table->foreignId('country_id')->references('id')->on('countries');
$table->foreignId('timezone_id')->references('id')->on('timezones');
});
}
the simplest but modern way of writing pivot table migration, where the Country and Timezone are models with many-to-many relationship. And id and timestamps are not necessary to include but straightforward manner
in the older version, you can use some generator or artisan to make pivots,
but in the newer version, this work is too easy.
you must only make migration to do that like the below code.
php artisan make:migration category_post --create=category_post
after run code
make migration with this params
$table->foreignId('post_id')->constrained('post');
$table->foreignId('category_id')->constrained('category');