in my database i have already tables namely: notifications table, statuses table, they have many to many relation, that is why i have a pivot table called notification_status. i created them with migrations and seed them with a seeder, all works fine. now i realize that i need one extra table which has many to one relation with notifications table(natification->hasMany->alertfrequency). when i tried to migrate it, it did allow me to do so.
here is my notification table
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateNotificationsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('notifications', function (Blueprint $table) {
$table->increments('id');
$table->string('website_url');
$table->string('email');
$table->string('slack_channel');
$table->string('check_frequency');
$table->string('alert_frequency');
$table->string('speed_frequency');
$table->boolean('active');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('notifications');
}
}
and the alert frequency table, the new table i want to add,
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAlertFrequenciesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('alertFrequencies', function (Blueprint $table) {
$table->increments('id');
$table->integer('notification_id');
$table->foreign('notification_id')
->references('id')->on('notifications')
->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('alertFrequencies');
}
}
when i tried to add i get the following constrain
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `alertFrequencies` add constraint `alertfrequencies_notification_id_foreign` foreign key (`notification_
id`) references `notifications` (`id`) on delete cascade)
any one with a idea or suggestion. i appreciate all idea and suggestions.
From #AlexeyMezenin's answer, update based on Documentation:
Replace
$table->integer('notification_id')->unsigned();
with
$table->unsignedInteger('notification_id');
First thing you should do is to add unsigned(), because id is unsigned too:
$table->integer('notification_id')->unsigned();
If it'll not help, divide key creation and adding a foreign key constraint:
Schema::create('alertFrequencies', function (Blueprint $table) {
$table->increments('id');
$table->integer('notification_id')->unsigned();
$table->timestamps();
});
Schema::table('alertFrequencies', function (Blueprint $table) {
$table->foreign('notification_id')->references('id')->on('notifications')->onDelete('cascade');
});
You need to migrate notifications table prior to alertFrequencies table as notification_id of alertFrequencies is referencing id of notifications table.
And you need to change $table->integer('notification_id'); to $table->integer('notification_id')->unsigned(); as you cannot accept minus ids as foreign key
And also make sure you have set your table engine set to InnoDB in your `config/database.php'.
$table->engine = 'InnoDB';
Related
I am a Laravel and Eloquent noob.
I'm trying to do a simple foreign key in a "checklist items" table that takes the primary ID from the "users" table as a foreign key.
Here are my two database migrations:
users:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
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();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
items:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateItemsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->integer('user_id')->unsigned();
$table->string('itemName');
$table->string('itemDescription');
$table->timestamps();
});
Schema::table('items', function($table) {
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('items');
}
}
attempting to run php artisan migrate yields the following error:
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (0.49 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (0.59 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated: 2019_08_19_000000_create_failed_jobs_table (0.33 seconds)
Migrating: 2021_05_04_085648_create_items_table
Illuminate\Database\QueryException
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `items` add constraint `items_user_id_foreign` foreign key (`user_id`) references `users` (`id`))
at D:\Applications\laragon\www\ToDoApp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:671
667| // If an exception occurs when attempting to run a query, we'll format the error
668| // message to include the bindings with SQL, which will make this exception a
669| // lot more helpful to the developer instead of just the database's errors.
670| catch (Exception $e) {
> 671| throw new QueryException(
672| $query, $this->prepareBindings($bindings), $e
673| );
674| }
675|
1 D:\Applications\laragon\www\ToDoApp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:464
PDOException::("SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint")
2 D:\Applications\laragon\www\ToDoApp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:464
PDOStatement::execute()
It should be noted that I can achieve what I need fine in the PHPMyAdmin GUI directly, or using basic PHP PDOs, but I don't understand Eloquent and need to understand what I am doing wrong.
I have a feeling that it's to do with a mismatch in the attribute definitions between the two table migrations, but the few things I tried caused alternate errors.
columns must be of the same type and sign (signed or unsigned)
$table->integer('user_id')->unsigned(); should be $table->bigInteger('user_id')->unsigned();
Just make a new Migration file for only the foreign key (docs). something like
php artisan make:migration add_columns_to_items_table
Why use different file for same table? Because we make the table first before we make the foreignKey right? :)
Then inside your migration file on up() function:
Schema::table('items', function (Blueprint $table) {
$table->foreignId('user_id')->constrained();
});
Yah, its shorter and better for development purpose
This happens when you create the migration for the many before the one part of one-to-many relationship. In your case I guess you created migration for items before users. Simply rename your migration files according to your relationships. Also please note that your relationship columns must be of the same type. In your case, you are referencing an integer of 4-byte to bigInteger of 8-byte. (id columns is an unsigned 8-byte integer).
Replace your items migration with the following code:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateItemsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->integer('user_id')->unsigned();
$table->string('itemName');
$table->string('itemDescription');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('items');
}
}
I need to connect two tables in DB with relation one to one. Where 'id' from first table need to be the 'id' in the second table.
Table 1:
public function up()
{
Schema::disableForeignKeyConstraints();
Schema::create('devices', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('device_type', 20)->nullable();
$table->date('purchase_date')->nullable();
$table->date('activation_date')->nullable();
$table->date('deactivation_date')->nullable();
$table->bigInteger('companyId')->unsigned();
$table->timestamps();
$table->foreign('companyId')->references('id')->on('companies');
});
Schema::enableForeignKeyConstraints();
}
Table 2:
public function up()
{
Schema::disableForeignKeyConstraints();
Schema::create('device_news', function (Blueprint $table) {
$table->integer('x', 10)->nullable();
$table->integer('y', 10)->nullable();
$table->time('time')->nullable();
$table->bigIncrements('deviceId');
$table->timestamps();
$table->foreign('deviceId')->references('id')->on('devices');
});
Schema::enableForeignKeyConstraints();
}
I never had situation like this. Is it correct or I have to change something?
To create an Eloquent model for a legacy table that has no primary key, simply add the following to your model:
/**
* primaryKey
*
* #var integer
* #access protected
*/
protected $primaryKey = null;
/**
* Indicates if the IDs are auto-incrementing.
*
* #var bool
*/
public $incrementing = false;
You should still have a $table->bigIncrements('id'); on the second table, so the table gets a PK - but you create the relation on an unsigned biginteger, which is not a primary key.
Laravel naming conventions also dictates that a relational column should be device_id and not deviceId (same goes for your primary table, it should be company_id and not companyId). Doing this will make your life much easier when you start defining your relations on your models.
Schema::create('device_news', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('device_id');
$table->integer('x', 10)->nullable();
$table->integer('y', 10)->nullable();
$table->time('time')->nullable();
$table->timestamps();
$table->foreign('device_id')->references('id')->on('devices');
});
I have table with primary key and auto-increment field, I want make new migration to drop primary key index and also remove the auto increment field. How can i achieve this.
I created new migration as
public function up()
{
Schema::table('tbl_message_read_state', function (Blueprint $table) {
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('tbl_message_read_state', function (Blueprint $table) {
$table->dropPrimary('message_id');
$table->unsignedInteger('message_id');
});
}
It gave me error in command as [Illuminate\Database\QueryException]
SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name 'message _id' (SQL: alter table tbl_'message_read_state' add 'message_id' int unsigned not null)
Whats Wrong ?????
Blueprint class offers dropPrimary methods that allow you to remove primary key.
public function down()
{
Schema::table('table', function (Blueprint $table) {
$table->dropPrimary();
$table->unsignedInteger('id'); // for removing auto increment
});
}
This did it for me:
Schema::table('table_name', function (Blueprint $table) {
// Make AI field `id` unsigned otherwise SQL
// will throw error when you try to remove it
$table->integer('id')->unsigned()->change();
$table->dropColumn('id');
// If there was a foreign on message_id, make sure to remove it
$table->dropForeign('table_name_message_id_foreign');
$table->dropPrimary('message_id');
$table->dropColumn('message_id');
}
The dropPrimary method only removed the primary key, not the column. You would have to do:
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('tbl_message_read_state', function (Blueprint $table) {
$table->dropPrimary('message_id');
$table->dropColumn('message_id');
$table->unsignedInteger('message_id');
});
}
Or instead of dropping and re-creating the column, you can use change in Laravel 5.
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('tbl_message_read_state', function (Blueprint $table) {
$table->dropPrimary('message_id');
$table->integer('message_id')->unsigned()->change();
});
}
You can try this
$table->dropPrimary('id_primary');
Drop the primary key:
$table->dropPrimary( 'id' );
Reference
Use a simple drop column
$table->dropColumn('id');
https://laravel.com/docs/4.2/schema#dropping-indexes
tabel_name
column
index $table->dropPrimary('users_id_primary');
I have the following migration file declared in laravel:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateProductsTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('products' , function($table){
$table->increments('id');
$table->integer('category_id');
$table->string('title');
$table->text('description');
$table->decimal('height' , 6 , 2);
$table->decimal('width' , 6 , 2);
$table->decimal('length' , 6 , 2);
$table->string('color');
$table->string('material');
$table->timestamps();
});
Schema::table('products' , function($table){
$table->foreign('category_id')->references('id')->on('categories');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('products');
}
}
now when i run php artisan migrate
i get an error , because the id in categories is int(10) and the categories_id I.E.
$table->foreign('category_id')->references('id')->on('categories');
is int(11) how do i make both int(10) ?
I would guess that your previous migrations were run on a previous version of Laravel. If that's the case, you can simply modify the column type of categories.id to int(11) directly in the DB.
Otherwise, you could use a Raw Query to add the column using INT(10).
To confirm the hypothesis that a version change caused this, you could run ALL migrations in an empty DB and see if you have the same issue.
Schema::table('products', function($table)
{
$table->integer('id, 10');
});
I have a calls table with user_id column and a foreign key constrain. So, user_id is related to users table.
I made a migration which deletes the column and foreign key constrain. The up method works fine. However, when it comes to down it breaks down because I add a user_id column and then restore the constrain, but the values in the column have nothing to do with real data so I got 150 MySQL error.
I've found a solution which didn't work for me. The solution is to temporarily disable foreign key constrains. Here is my migration file:
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class RemoveUseridFromCalls extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('calls', function(Blueprint $table)
{
$table->dropForeign('calls_user_id_foreign');
$table->dropColumn('user_id');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
\DB::statement('SET FOREIGN_KEY_CHECKS = 0');
Schema::table('calls', function(Blueprint $table)
{
$table->integer('user_id')->unsigned();
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('set null');
});
\DB::statement('SET FOREIGN_KEY_CHECKS = 1');
}
}
But I still get the same error.
So, the questions are:
What would you do if you need to remove user_id from columns table as it's not needed anymore, however you have to write the down method as well as up?
Why disabling foreign key checks doesn't work?
I use InnoDB as table type for all my tables.
You can simply use onDelete('cascade').
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('calls', function(Blueprint $table)
{
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->timestamps();
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade'); // use 'cascade'
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('calls');
}
}
onDelete('cascade') tells Laravel to delete a calls row when it's corresponsding foreign key user_id is deleted.
I had the same problem and fixed it by separating migration into several files. First one creates the table, the others add columns for the keys and the keys themselves.
After that everything starts working like a charm.
To check foreign key in table while dealing with migration can be as follow:
$keyExists = DB::select(DB::raw('SHOW KEYS FROM TABLE_NAME WHERE Key_name=\'YOUR_FOREIGN_KEY_NAME\''));
if(!$keyExists){
$table->foreign('app_id')
->references('id')
->on('apps')
->onDelete('cascade');
}