Laravel change String Boolean value to Int Boolean in migration - php

I'm working with a Laravel project that has two existing columns that are set to strings and hold a visually pleasing Boolean value of true or false.
I'm trying to change these columns from string to boolean in a Laravel migration, but need to convert the existing values in the columns, for instance, if the column value for a record has the value of false, it needs to become 0.
My current migration to modify these columns doesn't seem to acheive this automatically, how can I achieve this?
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddColumnsToNotificationContactsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('notification_contacts', function (Blueprint $table) {
$table->boolean('canNotify')->change();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('notification_contacts', function (Blueprint $table) {
//
});
}
}
I get:
SQLSTATE[HY000]: General error: 1366 Incorrect integer value: 'false' for column 'canNotify' at row 1 (SQL: ALTER TABLE notification_contacts CHANGE canNotify canNotify TINYINT(1) NOT NULL)

Do it in multiple steps instead of running it in a single operation.
Steps are:
Add a new temp Column canNotifyTemp
Populate it with the old data from Column canNotify
Delete the old column
Rename the temp column
class UpdateClientsTableAddRedesignColumns extends Migration
{
public function up()
{
// step 1
Schema::table('notification_contacts', function(Blueprint $table) {
$table->boolean('canNotifyTemp')->default(0);
});
// step 2
DB::table('notification_contacts')
->where('canNotify', 'true')
->update(["canNotifyTemp" => true]);
DB::table('notification_contacts')
->where('canNotify', 'false')
->update(["canNotifyTemp" => false]);
// step 3
Schema::table('notification_contacts', function(Blueprint $table) {
$table->dropColumn('canNotify');
});
// step 4
Schema::table('notification_contacts', function(Blueprint $table) {
$table->renameColumn('canNotifyTemp', 'canNotify');
});
}
public function down()
{
// step 4 rollback
Schema::table('notification_contacts', function (Blueprint $table) {
$table->renameColumn('canNotify', 'canNotifyTemp');
});
// step 3 rollback
Schema::table('notification_contacts', function (Blueprint $table) {
$table->string('canNotify')->default('false');
});
// step 2 rollback
DB::table('notification_contacts')
->where('canNotifyTemp', true)
->update(["canNotify" => 'true']);
DB::table('notification_contacts')
->where('canNotifyTemp', false)
->update(["canNotify" => 'false']);
// step 1 rollback
Schema::table('notification_contacts', function (Blueprint $table) {
$table->dropColumn('canNotifyTemp');
});
}
}
Note: I did not run the migration so if there is any problem, tell me.

Related

How to add multiple columns in already made table in Laravel?

I want to add multiple number of columns in the already made table in Laravel . How can i add multiple columns ?
I don't know how to do add columns in my table. I can only add single column one at a time.
Below given is my migration table up function.
public function up()
{
Schema::create('matches', function (Blueprint $table) {
$table->increments('id');
$table->string('sports');
$table->string('match');
$table->string('date');
$table->string('time');
$table->string('teamA');
$table->longtext('teamA_flag');
$table->string('teamB');
$table->longtext('teamB_flag');
$table->string('venue');
$table->string('status');
$table->timestamps();
});
}
This is my table whose name is matches. I want to add two columns using Laravel. The name of columns are: email and qualification.
I am expecting to add multiple number of columns on the table (matches).
I want to add multiple number of columns in the already made table in Laravel . How can i add multiple columns ?
I don't know how to do add columns in my table. I can only add single column one at a time.
Create migration first by php artisan make:migration alter_table_matches,
open migration that is created by the command.
public function up()
{
Schema::table('matches', function (Blueprint $table) {
$table->string('email')->nullable()->default(null);
$table->string('qualification')->nullable()->default(null);
});
}
then in down function
public function down()
{
Schema::table('matches', function (Blueprint $table) {
$table->dropColumn('email');
$table->dropColumn('qualification');
});
}
You can just run:
php artisan make:migration add_first_item_and_second_item_and_next_item_to_matches
This creates a migration file, you can then add:
public function up()
{
Schema::table('products', function (Blueprint $table) {
$table->string('first_item');
$table->string('second_item');
$table->string('next_item');
});
}
public function down()
{
Schema::table('products', function (Blueprint $table) {
$table->dropColumn('first_item');
$table->dropColumn('second_item');
$table->dropColumn('next_item');
});
}
I hope this solves your problem
You can add new columns by creating a new migration.
Remember to make the name of the migration as descriptive as possible.
2021_09_06_083822_update_email_column_and_add_agency_id_and_contact_source_id_in_contacts_table.php
class UpdateEmailColumnAndAddAgencyIdAndContactSourceIdInContactsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('contacts', function (Blueprint $table) {
$table->string('email')->nullable();
$table->integer('agency_id')->after('country_id')->references('agentid')->on('byt_agents');
$table->foreignId('contact_source_id')->after('agency_id')->nullable()->constrained();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('contacts', function (Blueprint $table) {
$table->dropColumn(['agency_id', 'email']);
$table->dropForeign(['contact_source_id']);
});
}
}
If you want to add multiple columns to an already existing table you can follow above answer-thread
but In that case, your all columns will be added at the end of already existing columns
so, In order to add multiple columns after a certain column. You can add columns group by using callback/closure as shown in the below snippet:
class AddFieldsInMatches extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('matches', function (Blueprint $table) {
// closure to add multiple-columns after `id` column
$table->after('id', function ($table) {
$table->integer('email')->nullable();
$table->integer('qualification')->nullable();
});
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('matches', function (Blueprint $table) {
$table->dropColumn('email');
$table->dropColumn('qualification');
});
}
}
Note:
Make sure these columns must be nullable otherwise, you will get an error on running php artisan migrate command on the terminal
callback/closure approach is applicable after Laravel 8.27 versions.
Reference Article: click here
Other StackOverFlow threat: click here

Rollback of new column deletes the entire table

I am trying to rollback updated column in my database table using migrations in laravel 4.2.
public function up()
{
if (Schema::hasTable('payments') && !Schema::hasColumn('payments', 'updated_at')) {
Schema::table('payments', function (Blueprint $table) {
$table->dateTime('updated_at')->nullable();
});
}
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
if (Schema::hasTable('payments')) {
Schema::table('payments', function (Blueprint $table) {
Schema::drop('updated_at');
});
}
}
When I do it this way it shows me that updated_at table doesnt exist:
Schema::drop('updated_at');
Doing it this way deleted the entire table:
Schema::drop('payments', 'updated_at');
How is it supposed to look like then?
Thank you and best wishes!
Schema::drop('updated_at'); is telling the DB to drop the updated_at table, which obviously doesn't exist. You need to use $table->dropColumn('updated_at') to drop a column on a specific table. See below:
public function down(){
if (Schema::hasTable('payments')) {
Schema::table('payments', function (Blueprint $table) {
$table->dropColumn('updated_at');
});
}
}
You can see you are already in the Schema::table("payments" ...) function, so using $table->dropColumn() will attempt to drop the column from the payment table.
Use the $table variable:
Schema::table('payments', function($table)
{
$table->dropColumn('updated_at');
});

A bug with renaming existing column in Laravel migrations

I added a new migration to rename an old column. Everything seems correct in this code, for me:
public function up()
{
Schema::table('reports', function (Blueprint $table) {
$table->renameColumn('reporter_id', 'created_by');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('reports', function (Blueprint $table) {
$table->renameColumn('created_by', 'reporter_id');
});
}
But then I faced an error:
In Connection.php line 664: SQLSTATE[0A000]: Feature not supported: 1846 ALGORITHM=COPY is not supported. Reason: Columns participating in a foreign key are renamed. Try ALGORITHM=INPLACE. (SQL: ALTER TABLE reports CHANGE reporter_id created_b y INT NOT NULL)
In PDOStatement.php line 140: SQLSTATE[0A000]: Feature not supported: 1846 ALGORITHM=COPY is not supported. Reason: Columns participating in a foreign key are renamed. Try ALGORITHM=INPLACE.
In PDOStatement.php line 138: SQLSTATE[0A000]: Feature not supported: 1846 ALGORITHM=COPY is not supported. Reason: Columns participating in a foreign key are renamed. Try ALGORITHM=INPLACE. `
Could you help me to fix this?
First drop koreign key on up method.
public function up()
{
Schema::table('reports', function (Blueprint $table) {
$table->dropForeign('reports_reporter_id_foreign');
$table->renameColumn('reporter_id', 'created_by');
});
}
Then add foreign key again on down method.
public function down()
{
Schema::table('reports', function (Blueprint $table) {
$table->renameColumn('created_by', 'reporter_id');
$table->foreign('reporter_id')->references('id')->on('your_related_table')->onDelete('cascade');
});
}
I've encountered this too - it makes no sense, because when I use my standard SQL client to rename the same field ... it works. But it just doesn't work as a migration script. Thus, I ended up running the RENAME inside a DB::statement and that worked for me:
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
DB::statement("ALTER TABLE `mydb`.`mytable`
CHANGE `currentfieldname` `newfieldname`
INT(10) UNSIGNED NOT NULL;");
}

Can't Migrate Foreign Key

Here is Vehicles migrate :
public function up()
{
Schema::create('Vehicles', function (Blueprint $table) {
$table->increments('serie');
$table->string('color');
$table->integer('power');
$table->float('capacity');
$table->float('speed');
$table->integer('maker_id')->unsigned();
$table->timestamps();
});
Schema::table('Vehicles', function (Blueprint $table){
$table->foreign('maker_id')->references('id')->on('Makers');
});
}
Here is Makers Migrate :
public function up()
{
Schema::create('Makers', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('phone');
$table->timestamps();
});
}
When I run artisan migrate , I got following error messages.
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1005 Can't create table `api`.`#sql-14b0_71
` (errno: 150 "Foreign key constraint is incorrectly formed") (SQL: alter t
able `Vehicles` add constraint `vehicles_maker_id_foreign` foreign key (`ma
ker_id`) references `Makers` (`id`))
[PDOException]
SQLSTATE[HY000]: General error: 1005 Can't create table `api`.`#sql-14b0_71
` (errno: 150 "Foreign key constraint is incorrectly formed")
I want to create two tables: Vehicles & Makers . In vehicles , maker_id is foreign key . I read the some references for laravel migration from various sources. But I can't find solution.
Pay attention to your migration files order, you have two solutions:
Change order: make Makers Migrate file first then Vehicles Migrate.
If Makers Migrate file comes after Vehicles Migrate file and you don't want to change order, move this:
Schema::table('Vehicles', function (Blueprint $table){
$table->foreign('maker_id')->references('id')->on('Makers');
});
To Makers Migrate file.
Now I delete makers migrate file and I run vehicles migrate file . Below is vehicles migrate file.
public function up()
{
Schema::create('Vehicles', function (Blueprint $table) {
$table->increments('serie');
$table->string('color');
$table->integer('power');
$table->float('capacity');
$table->float('speed');
$table->integer('maker_id')->unsigned();
$table->timestamps();
});
}
But I got the below errors
PHP Fatal error: Cannot redeclare class CreateVehicleTable in C:\xampp\htdocs\m
yownapi\database\migrations\2016_07_05_190215_vehicles_table.php on line 35
[Symfony\Component\Debug\Exception\FatalErrorException]
Cannot redeclare class CreateVehicleTable
Now it is work properly with below codes
Makers Migrate
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class MakersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('Makers', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('phone');
$table->timestamps();
});
Schema::table('Vehicles', function(Blueprint $table){
$table->foreign('maker_id')->references('id')->on('makers');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('Makers');
}
}
Vehicles Migrate
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class VehiclesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('Vehicles', function (Blueprint $table) {
$table->increments('serie');
$table->string('color');
$table->float('power');
$table->float('capacity');
$table->integer('maker_id')->unsigned();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('Vehicles');
}
}
There is a simple way to do this. From your Vehicles migration, make the following changes
public function up()
{
Schema::create('Vehicles', function (Blueprint $table) {
$table->increments('serie');
$table->string('color');
$table->integer('power');
$table->float('capacity');
$table->float('speed');
$table->integer('maker_id')
$table->foreign('maker_id')
->references('id')->on('Makers');
$table->timestamps();
});
}
And since you will be adding the values form the id column in Makers, Laravel already has got your back, so there is really no need to add the unsigned() property there. Its still Okay if you add it there.
Hope I have answered your question. For More Details

With Laravel Migration, How to change data type of a column and update its existing data to fit the new data type, without using raw SQL queries?

Suppose I have a users table which has been created through Migration and Schema Builder, like this:
public function up()
{
Schema::create('users', function(Blueprint $table)
{
$table->increments('id')->unsigned();
$table->string('name', 50);
$table->string('email', 50)->unique();
$table->string('password', 100);
$table->enum('is_suspended', ['yes', 'no'])->default('no');
$table->timestamps();
});
}
public function down()
{
Schema::drop('users');
}
Now suppose I want to change data type of the column is_suspended from enum to boolean without using raw SQL queries, and also fill the new boolean column with 0 instead of the enum value no and 1 instead of enum vlaue yes, How can I do this with migration in Laravel framework?
Here is how I performed this:
The up() method:
...
use App\User;
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
// do the following steps in order:
// 1- add a new column with the desired data type to the table
// 2- fill the new column with the appropriate data
// 3- delete the old column
// 4- rename the new column to match name of the deleted column
Schema::table('users', function(Blueprint $table)
{
// 1- add a new column with the desired data type to the table
// note that after() method is used to order the column and works only with MySQL
$table->boolean('is_suspended_new')->default(0)->after('is_suspended');
});
// 2- fill the new column with the appropriate data
// note that you may need to use data in the old column as a guide (like in this example)
$users = User::all();
if ($users) {
foreach ($users as $user) {
$u = User::find($user->id);
if ($u->is_suspended === 'yes') {
$u->is_suspended_new = 1;
} elseif ($u->is_suspended === 'no') {
$u->is_suspended_new = 0;
}
$u->save();
}
}
Schema::table('users', function(Blueprint $table)
{
// 3- delete the old column
$table->dropColumn('is_suspended');
});
Schema::table('users', function(Blueprint $table)
{
// 4- rename the new column to match name of the deleted column
$table->renameColumn('is_suspended_new', 'is_suspended');
});
}
The down() method:
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
// IMPORTANT NOTE:
// because renaming (enum) column types is not supported in laravel 4.2 (as mentioned here https://laravel.com/docs/4.2/schema#renaming-columns)
// so we will make some changes in the order of the steps as follows:
//
// do the following steps in order:
// 1- rename the exiting column
// 2- add a new column with the desired data type and give it a name matches name of the existing column before renaming
// 3- fill the new column with the appropriate data
// 4- delete the old column
Schema::table('users', function(Blueprint $table)
{
// 1- rename the existing column
$table->renameColumn('is_suspended', 'is_suspended_old');
});
Schema::table('users', function(Blueprint $table)
{
// 2- add a new column with the desired data type to the table
// and give it a name matches name of the existing column before renaming
// note that after() method is used to order the column and works only with MySQL
$table->enum('is_suspended', ['yes', 'no'])->default('no')->after('is_suspended_old');
});
// 3- fill the new column with the approprite data
// note that you may need to use data in the old column as a guide (like in this example)
$users = User::all();
if ($users) {
foreach ($users as $user) {
$u = User::find($user->id);
if ($u->is_suspended_old == 1) {
$u->is_suspended = 'yes';
} elseif ($u->is_suspended_old == 0) {
$u->is_suspended = 'no';
}
$u->save();
}
}
Schema::table('users', function(Blueprint $table)
{
// 4- delete the old column
$table->dropColumn('is_suspended_old');
});
}

Categories