Laravel Migrations onDelete Restrict not working - php

Hello I'm trying to define relationships in my migrations
I'm using on delete restrict to prevent deletion of parent record when child is present. but its not working. For example I have this event table (parent) that has editions (child). I'm using event_id in editions table
with onDelete('restrict') and have event_id in my edition table..
It should restrict me on deleting from events table as long record has child record in edition tables right? but its not..
Here are the migrations of both tables
Events (parent)
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateEventsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('events', function (Blueprint $table) {
//master table
$table->increments('event_id');
$table->string('name');
$table->text('full_name');
$table->text('description');
$table->tinyInteger('status');
$table->integer('created_by');
$table->integer('updated_by');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('events');
}
}
Editions (Child)
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateEditionsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('editions', function (Blueprint $table) {
$table->increments('edition_id');
$table->integer('event_id')->unsigned();
$table->string('name');
$table->dateTime('start')->nullable();
$table->dateTime('end')->nullable();
$table->enum('stage', ['Archived', 'Cancelled', 'Closed', 'Live', 'On-site', 'Pre-event', 'Sold out'])->nullable()->default('Pre-event');
$table->tinyInteger('status');
$table->integer('created_by');
$table->integer('updated_by');
$table->timestamps();
});
Schema::table('editions', function($table) {
$table->foreign('event_id')
->references('event_id')->on('events')
->onDelete('restrict')->onUpdate('restrict');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('editions');
}
}

According to this thread :
If you are using the SoftDeletes trait, then calling the delete()
method on your model will only update the deleted_at field in your
database, and the onDelete constraint will not be triggered, given
that it is triggered at the database level i.e. when a DELETE query is
executed.
So make sure that you use DELETE not SoftDeletes otherwise you can add the constraint manually.

One thing I see missing from your foreign key definition is adding an index on it, that is a requirement for foreign keys and it might be what's caussing issues for you.
Try changing
$table->integer('event_id')->unsigned();
to
$table->integer('event_id')->unsigned()->index();
Also, you can just add the foreign key definition immediately after the column definition, no need to put it in a different Schema::table() block.

Related

How can I modify DB structure in Laravel without truncating tables?

I have defined a DB table structure below.
If I want to modify a table column:
From
$table->string('active',1);
To:
$table->string('active',1)->nullable(); // allow null values
Every time I run the migration script, my tables will be truncated.
Is there a way to define a table structure and have it be modified to correct structure WITHOUT dropping the table?
Here is my code for now:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class VTUser extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('Z_user', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('nickname')->unique();
$table->string('email')->unique();
$table->string('passhash');
$table->string('keygen');
$table->string('active',1)->nullable();
$table->string('banned',1);
$table->string('admin',1);
$table->string('step',1);
// $table->rememberToken();
// $table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('Z_user');
}
}
There can be two ways of achieving this -
Either you can rollback the migration with php artisan migrate:rollback --step=1 and then change the up function with $table->string('active',1)->nullable();
Create a new migration to update the table by doing $table->string('active',1)->nullable(); in this new migration.

Php artisan migrate gives different result with the same code

pic1
pic2
Pic 2 is the usual laravel migration tables that i created. Pic 1 is the laravel migration tables that i newly created. They have the same code with same foreign key only with different attributes name. Why is pic 1 only have varchar(191) instead of varchar(255), and the foreign key doesnt apply from migrations anymore? Before pic 1, i did ran some stuff on terminal for deployment purpose like npm build. Is the terminal the cause of this?
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('calibrations', function (Blueprint $table) {
$table->id();
$table->string('Identification_No');
$table->foreign('Identification_No')->references('Identification_No')->on('fieldequips');
$table->string('Calibration_point');
$table->date('Expired_Date');
$table->date('Calibration_Date');
$table->date('Next_Due_Date');
$table->string('Correction_factor');
$table->string('Validated_by');
$table->date('Validated_Date');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('calibrations');
}
};
In app/Providers/AppServiceProvider.php you should change Schema::defaultStringLength(191) to Schema::defaultStringLength(255), I guess

How to drop schema with connection to table in another database?

In my Laravel app, I have connections to different databases and when I need to fresh my tables in each of database with a new dummy data (I do it with php artisan migrate:fresh --seed command) I always have this error
SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'table_name' already exists
which is weird because I have down() method in my migration class
class CreateExampleTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::connection('conn2')->create('table_name', function (Blueprint $table) {
$table->bigIncrements('id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::connection('conn2')->dropIfExists('table_name');
}
}
If you use migrate:refresh instead of fresh it will rollback the database using your down() methods.
I think the problem is not in your down() but with your up() : it is trying to create a table, but a table with that name already exists.
I would suggest doing something like:
if (!Schema::hasTable('tbl_name')) {
// create table
}
You may also have to specify which database you are using in the migrations.

How do I add default value as same from another column in Laravel Migration

I have a questions table in my database, in which I have a column of question_title, now I have added a column question_slug, which will contain the question's slug URL, so how I set question_slug default value as question_title in Laravel Migration, I need this all because I have questions saved in the database so I have run php artisan make:migration add_column_to_questions --table=questions now I have this code:
Schema::table('questions', function (Blueprint $table) {
$table->string('question_slug')->default();
});
first of all, create a new migration and put this code within it:
connections_string : it's within web/config/database.php file
configuration
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class NameOfUrMigration extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('questions', function (Blueprint $table) {
$table->string('question_slug')->default();
});
$questions = DB::connection('connections_string')->table('questions')->get();
foreach($questions as $question)
{
$question->question_slug = str_slug($question->question_title);
$question->save();
}
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
//
}
}
According to the documentation, default() is used to Declare a default value for a column.
That means the value that gets inserted by default in a field if you do not provide a value for it in the insert query.
The default() cannot help you achieve what you need here.
What you could do is create a new migration class with a raw query in the up() method which will update the value of question_slug with the value of question_title.
something like this:
public function up()
{
$sql = "UPDATE `questions` SET `question_slug` = `question_title` WHERE 1;";
//add filtering conditions if you don't want ALL records updated
DB::connection()->getPdo()->exec($sql);
}
Make sure you also create a corresponding down() method for the rollback

laravel 5 - How can i add ->index() to existing foreign key

Framework: Laravel 5.2
Database: MySQL
PHP: 7.0
I have the table "pops":
Schema::create('pops', function (Blueprint $table) {
$table->string('id')->primary()->index();
$table->string('ab_test_parent_id')->nullable();
$table->string('cloned_parent_id')->nullable();
$table->timestamps();
});
And the table "conversions":
Schema::create('conversions', function (Blueprint $table) {
$table->string('id')->primary()->index();
$table->integer('users')->default(null);
$table->string('name',256)->default(null);
$table->string('pop_id');
$table->foreign('pop_id')->references('id')->on('pops')->onDelete('cascade')->onUpdate('cascade');
$table->timestamps();
});
I have set a foreign key (pop_id) in the "conversions" table. Now does it's mean that the foreign key (pop_id) is also a index? if not... what i need to do in order to make it a index?
Thank?
You can just do this.
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddIndexToLeads extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('leads', function(Blueprint $table)
{
$table->index('trader_id');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('leads', function (Blueprint $table)
{
$table->dropIndex(['trader_id']);
});
}
}
credit to #bobbybouwmann
Here is a perfect solution for you.
Up
$table->string('poptin_id')->index('poptin_id');
Down
$table->dropIndex(['poptin_id']);
Suggestion to fix your migrations
$table->string('id')->primary()->index();
replace above with below
$table->increments('id');
and fix your foreign key as below
$table->integer('poptin_id')->index('poptin_id')->unsigned();
I was facing problem when i just write :-
$table->index('column_name');
So to be more exact first you need to create column with desired column type then assign it to be index like this :-
$table->string('column_name');
$table->index('column_name');
//or
$table->string('column_name')->index();
I hope this helps
Laravel only adds a foreign key constraint and doesn't add index implicitly. But some databases such as MySQL automatically index foreign key columns.
If you need to add index to a field in another migration. Then you could do
$table->index('email');

Categories