A bug with renaming existing column in Laravel migrations - php

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;");
}

Related

Laravel change String Boolean value to Int Boolean in migration

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.

Laravel foreign key constraint is incorrectly formed I have searched and cannot find the answer

class CreateMediaTable extends Migration
{
public function up()
{
Schema::create('media', function (Blueprint $table) {
$table->increments('id');
$table->unsignedBigInteger('id_users');
$table->unsignedBigInteger('id_posts');
$table->char('type', 1); //P: photo or V: video
$table->string('file');
$table->timestamps();
$table->foreign('id_posts')->references('id')->on('posts');
$table->foreign('id_users')->references('id')->on('users');
});
}
public function down()
{
Schema::dropIfExists('posts');
}
}
and my createprofilemigration
/**
* #author Alex Madsen
*
* #date November 6, 2018
*/
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUserProfilesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('user_profiles', function (Blueprint $table) {
$table->unsignedInteger('id_users')->unique();
$table->string('handle')->unique();
$table->string('icon')->default('https://i.redd.it/130am13nj6201.png');
$table->string('profile_image')->nullable();
$table->string('description')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('user_profiles');
}
}
Keeps throwing these errors, What am I missing? Mind you I am new to this, Trying to learn with youtube and stackoverflow on my off time. Not sure which way to go. I have looked on the forums and tried $table->foreign('id_posts')->references('id')->on('posts'); But it didn't fix the issue.
Illuminate\Database\QueryException : SQLSTATE[HY000]: General error: 1005 Can't create table `ci`.`media` (errno: 150 "Foreign key constraint is incorrectly formed") (SQL: alter t
able `media` add constraint `media_id_posts_foreign` foreign key (`id_posts`) references `posts` (`id`))
at C:\xampp6\htdocs\lol\simple_social_network_laravel\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| }
class CreatePostsTable extends Migration
{
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->unsignedBigInteger('id_users');
$table->unsignedInteger('subreddit_id');
$table->text('description');
$table->string('title');
$table->text('content');
$table->unsignedInteger('id_posts');
$table->timestamps();
$table->foreign('id_users')->references('id')->on('users');
$table->foreign('subreddit_id')->references('id')->on('id_posts');
});
}
public function down()
{
Schema::dropIfExists('posts');
}
}
When using foreign keys types should be exactly the same.
You create:
$table->unsignedBigInteger('id_posts');
so it's unsigned big integer, but probably in posts table instead of bigIncrements you use just increments for id column and that's why you are getting this error.
So quite possible instead of:
$table->unsignedBigInteger('id_posts');
you should use
$table->unsignedInteger('id_posts');
or as alternative solution use
$table->bigIncrements('id');
in posts migration
In your posts migration, you made your id with increments
that is mean that it takes
unsigned integer auto_increment
but in your migration of media file, you create a posts_id with unsignedBigInteger
so there's two way to fix that choose only one
edit your id in posts migration to be bigincrements
edit your posts_id in 'media' migration to unsignedIntegere

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');
});

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

Categories