Migrations do not follow timestamp order - mysql

I am working with Laravel 5.4 trying to run my migrations. I have read that the order of execution follows the timestamps of the migration files. But this is not the case, as I receive the following error:
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint
(SQL: alter table `aplicantes` add constraint `aplicantes_pais_id
_foreign` foreign key (`pais_id`) references `pais` (`id`))
These are my migrations files:
2014_01_01_100004_create_pais_table.php
2014_01_01_100005_create_departamentos_table.php
2014_01_01_100006_create_aplicantes_table.php
And this is where migration complains:
class CreateAplicantesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('aplicantes', function (Blueprint $table) {
$table->increments('id');
$table->string('nombre');
$table->unsignedInteger('pais_id');
$table->foreign('pais_id')->references('id')->on('pais');
$table->timestamps();
});
}
}
This is my Pais migration:
public function up()
{
Schema::create('pais', function (Blueprint $table) {
$table->increments('id');
$table->string('nombre');
$table->timestamps();
});
}
When I inspect the database, only the aplicantes table is created, which is the third in the order. I guess that is why the migration fails because the aplicantes table is being created first, which references a table that does not exist yet.
EDIT:
I have updated my migrations, creating an individual file for the foreign keys of every table. I'm getting an error when migrate:refresh, an access violation while dropping a foreign key, and I presume it's because of the same reason: migration is performing in alphabetical order, not by the timestamp.
UPDATE:
I had to rename every migrations file and now it seems working. Seems that migrate only care about days field in the naming convention of the migration files, not the seconds, as I was working with.
Despite that I see a correct order of migrate in migrations table, it complains of dropping foreign keys when I have my migration file like this:
class AddAplicantesForeignKey extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('aplicantes', function (Blueprint $table) {
$table->foreign('pais_id')->references('id')->on('pais')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('aplicantes', function(Blueprint $table)
{
$table->dropForeign('pais_id');
});
}
}
I manage to disable the complains by turn off the foreign key constraints check in my migration create table:
public function down()
{
DB::statement('SET FOREIGN_KEY_CHECKS = 0');
Schema::dropIfExists('aplicantes');
}
I am not happy with this solution, but it seems to only be working this way.

Related

How to resolve SQLSTATE[HY000]: General error: 1824 Failed to open the referenced table in laravel?

I created Three migration tables user_container table is for storing user details, admin_table is for storing admin details, blog_table is for storing blogs .admin can create blogs so that's why i make a foriegn key relationship for admin to blogs table .when i try to migrate the tables i am getting the following error
Illuminate\Database\QueryException
SQLSTATE[HY000]: General error: 1824 Failed to open the referenced table 'admin_table' (SQL: alter table `blogs_table` add constraint `blogs_table_admin_id_foreign` foreign key (`admin_id`) references `admin_table` (`id`))
please help me to fix this issue i am not getting where did i mistake..
migration table structure
2021_08_11_170129_create_Blogs_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateBlogsTable extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('blogs_table', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('price');
$table->string('country');
$table->longText('description');
$table->integer('rating');
$table->longText('image');
$table->unsignedInteger('admin_id');
$table->foreign('admin_id')->references('id')->on('admin_table');
$table->timestamps();
//$table->softDeletes();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('blogs_table');
}
}
2021_08_12_121933_create_admin_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateAdminTable extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('admin_table', function (Blueprint $table) {
$table->id();
$table->string('firstName');
$table->string('lastName');
$table->string('email')->unique();
$table->string('mobile');
$table->string('password');
$table->timestamps();
//$table->softDeletes();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('admin_table');
}
}
You are trying to run the migration on your Blogs Table first and after that, you run the migration on Admin Table.
Laravel migration takes the timestamp at the beginning of the file to decide which migration should be migrated first in the sequence.
Make sure you create an admin table first before the Blog table (this also applies to any tables that have references). Or simply just rename the file (change the timestamp) like E.g:
2021_08_12_121933_create_admin_table.php
2021_08_11_170129_create_Blogs_table.php
To this:
2021_08_11_121933_create_admin_table.php
2021_08_12_170129_create_Blogs_table.php
Then run php artisan migrate:fresh to refresh your migration.
When you're setting up the foreign key $table->foreign('admin_id')->references('id')->on('admin_table'); the table admin_table doesnt exist yet.
Change the migration name of the admin_table to be run before that of the blog one.
2021_08_11_121933_create_admin_table.php
instead of
2021_08_12_121933_create_admin_table.php

Laravel migration "Cannot add foreign key constraint" error with MySQL database

I am developing a Laravel application. I am using MySQL for the database. I have created a model class and am trying to run the migration on it. But when, I run migration, I am getting error with adding the foreign key constraint. This is what I have done so far.
First I have migrated the built in Laravel user model running this command.
php artisan migrate
The users table was created in the database.
Then I created another model running this command.
php artisan make:model TodoItem -m
Then I added the following code to the migration file.
class CreateTodoItemsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('todo_items', function (Blueprint $table) {
$table->text('about');
$table->integer('user_id');
$table->increments('id');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('todo_items');
}
}
AS you can see above, I am building the relationship between users table and todo_items table by adding a foreign key to the todo_items table. Then, I tried to migrate the TodoItem model by running this command.
php artisan migrate
When I run the command, I got this error.
Illuminate\Database\QueryException : SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `todo_items` add constraint `todo_items_user_id_foreign` foreign key (`user_id`) references `users` (`id`) on delete cascade)
at /var/www/vendor/laravel/framework/src/Illuminate/Database/Connection.php:664
660| // If an exception occurs when attempting to run a query, we'll format the error
661| // message to include the bindings with SQL, which will make this exception a
662| // lot more helpful to the developer instead of just the database's errors.
663| catch (Exception $e) {
> 664| throw new QueryException(
665| $query, $this->prepareBindings($bindings), $e
666| );
667| }
668|
Exception trace:
1 PDOException::("SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint")
/var/www/vendor/laravel/framework/src/Illuminate/Database/Connection.php:458
2 PDOStatement::execute()
/var/www/vendor/laravel/framework/src/Illuminate/Database/Connection.php:458
Please use the argument -v to see more details.
I did the same in my previous project which is using Postgresql. I was working fine. For this project, I am using MySQL database and now it is giving me the above error.
This is because you added $table->integer('user_id'); to your migration file. You must add an unsignedInteger instead of an integer, because the original id column of the users table is unsigned (and both columns must be exactly the same).
[EDIT]
Since Laravel 5.8, the id column type of the default users table is no longer an integer. It is now a bigInteger.
try
$table->unsignedBigInteger('user_id')->nullable()->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
Change this
$table->integer('user_id');
To this
$table->unsignedInteger('user_id')->nullable(false);
Try running it like this, this should work.
// also, do the unsigned thing the people above me posted
public function up()
{
Schema::create('todo_items', function (Blueprint $table) {
$table->text('about');
$table->integer('user_id');
$table->increments('id');
$table->timestamps();
});
Schema::table('todo_items', function(Blueprint $table) {
$table->foreign('user_id')->references('id')->on('users')->onUpdate('CASCADE')->onDelete('CASCADE');
});
}
The issue was that either mysql didn't want foreign keys during table creation, or laravel was issuing them in the wrong order.
In short, this didn't work:
Schema::create('todo_items', function (Blueprint $table) {
$table->text('about');
$table->integer('user_id')->unsigned();
$table->increments('id');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
This worked:
Schema::create('todo_items', function (Blueprint $table) {
$table->text('about');
$table->integer('user_id')->unsigned();
$table->increments('id');
$table->timestamps();
});
Schema::table('todo_items', function(Blueprint $table){
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});

Laravel nullable migration with foreign key

I have items table with supplier_id column and the foreign key to that column. The column is not nullable and I want to make it nullable. So the up() method works:
$table->integer('supplier_id')->unsigned()->nullable()->change();
But I can't get down() method to work, always get the error:
Cannot change column 'supplier_id': used in a foreign key constraint 'items_supplier_id_foreign'
Latest attempt:
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('items', function (Blueprint $table) {
$table->dropForeign(['supplier_id']);
$table->integer('supplier_id')->unsigned()->nullable(false)->change();
$table->foreign('supplier_id')->references('id')->on('suppliers');
});
}
Any suggestions? I'm using Laravel 5.4
#apokryfos is right. See here
Before any changes are made to your table, it’s important to briefly go over what data can (and cannot) be specified within an existing column that you wish to alter to NOT NULL, ensuring that no row is allowed to have a NULL value in that column.
At first, you need fill all nullable values using seeds and then modify column. Or your can drop supplier_id and than using default() method fill all rows in the table.
Only dropping foreign key constraint is not enough if you're changing the column next, you have to also drop its index. Below is the migration down function
Schema::table('users', function (Blueprint $table) {
$table->dropForeign('users_role_id_foreign');
$table->dropIndex('users_role_id_foreign');
});
// Conflict with change on same Blueprint instance (strange)
Schema::table('users', function (Blueprint $table) {
$table->integer('role_id')->change();
});
Credits: Github

Errors when refreshing migration of DB tables

After refreshing my migrations im getting issues between users migrations and account Types users table, cant figure out the problem.
Error
[Illuminate\Database\QueryException]
SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'account_typ
es' already exists (SQL: create table `account_types` (`id` int unsigned no
t null auto_increment primary key, `name` varchar(50) not null, `created_at
` timestamp null, `updated_at` timestamp null) default character set utf8mb
4 collate utf8mb4_unicode_ci)
[PDOException]
SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'account_typ
es' already exists
My Migrations
Account Types
public function up()
{
Schema::create('account_types', function (Blueprint $table) {
$table->increments('id');
$table->string('name', 50);
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('account_types');
}
Users
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('surname', 20);
$table->string('email')->unique();
$table->string('password');
$table->string('mobilephone', 9);
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('users');
}
Relation ship between the users and account types, i believe that maybe the problem is here, but still cant figure out what is wrong with the migration code.
Relation of Users and Account Types
public function up()
{
Schema::table('users', function($table) {
$table->integer('account_type_id')->unsigned();
$table->foreign('account_type_id')
->references('id')->on('account_types');
});
}
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropForeign('users_account_type_id_foreign');
$table->dropColumn('account_type_id');
});
}
Like I had many times before there occurred an error when you were migrating and you get this error because the migration script hasn't had the chance to register the last migration.
If you don't care about the data already stored drop all the tables in your database manually (even the migrations table) and rerun.
When you have data in your tables you want to keep you should check this migrations table and look at the batch column. Put every entry on 1 you want to keep and set the row and the rows below it on 0 (maybe deleting them will also work). Run php artisan migrate. When using phpmyadmin you can update these rows by query, eg: UPDATE migrations SET batch=0 WHERE migration LIKE "%create_users_table";
Hope this helps :).
I think you should try this:
first remove account_types, users from migrations table in your database.
And refresh your migrations.
Hope this works for you!

SQLSTATE[23000]: Integrity constraint violation: 1217

After creatin multiple migrations in my project, I wanted to rollback to update a few things but suddenly I got this error when I tried to drop projects table. I double checked the foreign key constrains but I can't find the error.
[Illuminate\Database\QueryException]
SQLSTATE[23000]: Integrity constraint violation: 1217 Cannot delete or upda
te a parent row: a foreign key constraint fails (SQL: drop table `projects`
)
[PDOException]
SQLSTATE[23000]: Integrity constraint violation: 1217 Cannot delete or upda
te a parent row: a foreign key constraint fails
Here are my migrations:
1.create table users:
public function up()
{
Schema::create('users', function(Blueprint $table)
{
$table->increments('id');
$table->string('first_name');
$table->string('last_name');
$table->string('email', 50)->unique();
$table->string('password', 60);
$table->string('password_temp', 60);
$table->string('code', 60);
$table->boolean('active');
$table->string('remember_token', 100);
$table->timestamps();
});
}
public function down()
{
Schema::drop('users');
}
2.create clients table:
public function up()
{
Schema::create('clients', function(Blueprint $table)
{
$table->increments('id');
$table->integer('user_id')->unsigned()->index()->nullable();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
}
public function down()
{
Schema::drop('clients');
}
3.create projects table:
public function up()
{
Schema::create('projects', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
$table->integer('status');
$table->integer('client_id')->unsigned()->index()->nullable();
$table->foreign('client_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
}
public function down()
{
Schema::drop('projects');
}
In the last migration, what could possibly be the mistake I am doing?! I face no trouble when migrating but it appears only when I rollback to add any changes.
Any idea why this happens?
Use this in down function.
public function down()
{
DB::statement('SET FOREIGN_KEY_CHECKS = 0');
Schema::dropIfExists('tableName');
DB::statement('SET FOREIGN_KEY_CHECKS = 1');
}
If there are only 3 tables above mentioned, there is no issue in your migration as I have tried it myself with
php artisan migrate
to create the tables and
php artisan migrate:rollback
to rollback.
One thing that I know is Laravel is going to assume the sequence of the migration based on the migration file timestamp.
Therefore, I am quite sure there is another table that has a foreign key reference to the projects tables that has not been dropped as the error messsage is (SQL: drop table projects)
Try to use php artisan tinker and then Schema::drop('some_table_name'); where some_table_name is the table that has reference to projects table, then drop the projects table again.
When you use foreign keys in your tables you need to remove those using the dropForeign method before you drop your table, else you will run into the integrity constraint issues you are currently getting.
public function down()
{
Schema::table('projects', function(Blueprint $table) {
$table->dropForeign('projects_client_id_foreign');
});
Schema::drop('projects');
}
This problem is commonly created by editing/adding to existing migrations.
Either create new migration files when dealing with foreign keys or be prepared to potentially dump/drop your entire db and refresh.