How to drop foreign key using Laravel migrations? - php

I've tried to drop a an InnoDB table that holds a foreign key using Laravel Migrations but I found out that I need to drop the foreign first but what I've read on the doc and on articles doesn't work.
Here's the portion of the code creating the problem :
Schema::table('admin_admin_action', function(Blueprint $table) {
$table->dropForeign(['admin_action_id']);
$table->dropColumn('admin_action_id');
$table->dropForeign(['admin_id']);
$table->dropColumn('admin_id');
});
And here's the error code
Illuminate\Database\QueryException : SQLSTATE[42000]: Syntax error or access violation: 1091 Can't DROP 'admin_admin_action_admin_action_id_foreign'; check that column/key exists (SQL: alter table `admin_admin_action` drop foreign key `admin_admin_action_admin_action_id_foreign`)
This table is the result of a many to many association and here are the foreign keys
Schema::table('admin_admin_action', function($table) {
$table->unsignedInteger('admin_id');
$table->unsignedInteger('admin_action_id');
$table->foreign('admin_id')->references('id')->on('admin');
$table->foreign('admin_action_id')->references('id')->on('admin_actions');
});
I've also tried specifying the full foreign key name but it says that the key/column doesn't exist though it does exist in the database.
I'm doubting this is a migration's issue because the migration runs smoothly but that's not the case for the rollback.
Edit: The foreign keys are respectively named
admin_admin_action_admin_id_foreign
admin_admin_action_admin_action_id_foreign
Help!

I found the solution !
You're right ! It's a mis-conception issue I've created a "admin_admin_action" and an "admin_action_admin" tables. So I've been trying to the table that doesn't have the foreign keys but has the same position in the database. They're duplicated ! Thanks

Related

Laravel Migration create foreign key using foreignIdFor with specific data type?

So I've been trying to write a migration that creates a data table question_display_formats using tiny increments as you see below.
And then, adding new Foreign Key column to existing questions table, trying to use the foreignIdFor method as a shortcut that'd look nice
public function up()
{
Schema::create('question_display_formats', function (Blueprint $table) {
$table->tinyIncrements('id');
$table->string('format');
});
Schema::table('questions', function (Blueprint $table) {
$table->foreignIdFor(QuestionDisplayFormat::class)
->nullable(true)
->after('question_type_id')
->constrained();
});
}
Turns out, this errors out with
General error: 1215 Cannot add foreign key constraint
Which turns out because the foreignIdFor users a different data type (confirmed by manually matching them and running the erroring out SQL alter table statement).
I googled, read and tried to adjust by doing:
$table->mediumIncrements('question_display_format_id'); before the foreignIdFor line, which leads to error
SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name
'question_display_format_id' (SQL: alter table questions add
question_display_format_id mediumint un signed not null
auto_increment primary key, add question_display_format_id bigint
unsigned null after question_type_id)
Is there a way to use foreignIdFor with the matching column size? or am I supposed to fall back on the classic way of first creating the column explicitly, then doing like $table->foreign('question_display_format_id')->references('id')->on('question_display_formats'); which I don't like because its very verbose and doesn't look good?
On the other hand, this is a one time used script.. lol would've been faster to just do it the old way! but I am curious to see how to do it right :)

How to migrate my users table in Laravel after I made a change?

I am building an eCommerce site and I am running into an issue when migrating my orders table. I am getting the following error:
SQLSTATE[HY000]: General error: 3780 Referencing column 'user_id' and referenced column 'id' in foreign key constraint 'orders_user_id_foreign' are incompatible. (SQL: alter table `orders` add constraint `orders_user_id_foreign` foreign key (`user_id`) references `users` (`id`) on delete set null on update cascade)
The schema that sets up the foreign key for this migration looks like:
// set up foreign key on users
$table->integer('user_id')->unsigned()->nullable(); // will be null if guest
$table->foreign('user_id')
->references('id')->on('users')
->onUpdate('cascade')
->onDelete('set null');
I figured out that the users table schema sets up the id like so:
$table->id();
And the orders table schema sets up the id like this:
$table->increments('id');
So I changed the users migration so that it is the same as the orders migration i.e both are like:
$table->increments('id');
But when I run php artisan migrate, I get this back:
➜ MobileMastery_V2 git:(master) ✗ php artisan migrate --path=/database/migrations/2014_10_12_000000_create_users_table.php
Nothing to migrate.
As you can see above I tried declaring the path to the migration I wanted to see if that would work but it didn't. How can I get this single file to migrate? Thanks
Laravel migrations are intended to keep track of the changes you make on your database over time. Laravel creates a table called migrations that keeps track of the migrations if it already ran or not. So in this case you can create a new migration that only makes that change, or if your database has no data on it yet you can drop the database schema, make your modifications on the migrations and run it again.
And about the primary key and foreign keys, I recommend you to read this part of Laravel documentation.
You should create migration for this change and run php artisan migrate.

What is this second parameter in the foreign method in migration Laravel?

I'm working with Laravel in this new project but there's one piece of code that I don't know what it does.
$table->foreign('course_id', '54419_596eedbb6686e')->references('id')->on('courses');
The line above is one of my migration files, I know that I'm saying that the 'course_id' is a foreign key with relation to 'id' on courses table. But what I don't know is what is this second parameter ('54419_596eedbb6686e'), if I look in the method description it says that is a name, but a name for what? Am I supposed to create a number like this and put it in all my foreign keys? Is there a command to generate this number?
Anyway if anyone can help me to understand this piece of code it would be great.
Hope I was clear on the question.
The second parameter is the name for your foreign key.
By default the name of the foreign key for this $table->foreign('course_id')->references('id')->on('courses'); will be courses_course_id_foreign.
In this case $table->foreign('course_id', '54419_596eedbb6686e')->references('id')->on('courses'); your foreign key will be named as 54419_596eedbb6686e.
When you create a foreign key you are creating a constraint and that's what the second parameter of foreign() function is specifying: the constraint name.
If you are using mysql you can log in the shell(or whatever program you use to check the db out) and run SHOW CREATE TABLE table_name. that will output information about that table you specified. There you'll be able to see '54419_596eedbb6686e' as a constraint of your table. Something like this:
CONSTRAINT constraint_name FOREIGN KEY (column_id) REFERENCES table_name (id) ON DELETE CASCADE
You can find a little more information in the following links: MySQL FOREIGN KEY syntax
SQL FOREIGN KEY on CREATE TABLE
When you create migration let this in your migration for foreign key
$table->foreign('foreign_id')
->references('id')->on('main_table_name')
->onUpdate('CASCADE')
->onDelete('RESTRICT');

Foreign Key contraints with AWS RDS not working

I'm trying to move my local laravel database up to RDS, I have had lots of problems with Elastic beanstalk so I decided to go a different way. When I migrate I get the following error with every foreign key I have:
[Illuminate\Database\QueryException] SQLSTATE[HY000]: General error:
1215 Cannot add foreign key constraint (SQL: alter table videos add
constraint videos_object_id_foreign foreign key (object_id)
references objects (id) on delete cascade)
PDOException
[PDOException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint
I have looked into RDS's foreign key constraints and they say they are not enforced, but it says they can be used for informational purposes.
Every foreign key is unsigned.
Schema::create('videos', function (Blueprint $table) {
$table->increments('id');
$table->integer('object_id')->unsigned()->nullable();
$table->foreign('object_id')->references('id')->on('objects')->onDelete('cascade');
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->rememberToken();
$table->timestamps();
});
Note: I have also tried separated the forein keys into a separate migration after the table was created and had no luck.
To find the specific error run this:
SHOW ENGINE INNODB STATUS
And look in the LATEST FOREIGN KEY ERROR section.
The data type for the child column must match the parent column exactly.
Also, you should run the query set foreign_key_checks=0 before running the DDL so you can create the tables in an arbitrary order rather than needing to create all parent tables before the relevant child tables.

Laravel Eloquent truncate - Foreign key constraint

I am having some issues with deleting data using Laravel 5. I seem to be stuck on a 'foreign key constraint', while I don't see why.
In my current database model I have a datapoints table, which has a foreign key to the sensors table (datapoints.sensors_id -> sensor.id).
The code I am trying:
Route::get('/truncateData', function() {
DB::table('datapoints')->truncate();
DB::table('sensors')->truncate();
return 'Done...';
});
The result:
SQLSTATE[42000]: Syntax error or access violation: 1701 Cannot
truncate a table referenced in a foreign key constraint
(alerting.datapoints, CONSTRAINT datapoints_sensor_id_foreign
FOREIGN KEY (sensor_id) REFERENCES alerting.sensors (id))
(SQL: truncate sensors)
I would understand this constraint if the order would be inverse (first deleting sensors), but when datapoints is empty, there should be no problem deleting sensors? I have also tried:
DB::table('datapoints')->delete();
DB::table('sensors')->delete();
return 'Done...';
Lastly I also tried adding explicitly 'DB::commit()' between the delete statements, but all return the same result.
Is this normal behaviour? Am I missing something?
No, this is the way your database works. You can't truncate table that is referenced by some other table. You may do something like
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
DB::table('datapoints')->truncate();
DB::table('sensors')->truncate();
DB::statement('SET FOREIGN_KEY_CHECKS=1;');
to disable foreign key checks, truncate tables and enable it again.
If you prefer to use Eloquent objects, Maksym's answer the "Eloquent" way
use Illuminate\Support\Facades\Schema;
use App\Models\Datapoint;
use App\Models\Sensor;
Schema::disableForeignKeyConstraints();
Datapoint::truncate();
Sensor::truncate();
Schema::enableForeignKeyConstraints();
In Laravel 7 and 8, for compatibility across 4 databases (MySql, Postgres, SQLite and SqlServer) and no Eloquent, you can use:
Schema::disableForeignKeyConstraints();
DB::table('datapoints')->truncate();
DB::table('sensors')->truncate();
Schema::enableForeignKeyConstraints();

Categories