Migration handling unsupported types - mysql

I already have a database setup and I would like to create migration(s) from an empty db to current state.
How do I handle unsupported types (like Point) by Laravel migration?
Only solution I could think of was using DB::statement and writing raw SQL. Is there any better way?
Also, is there any converter from an existing DB to Laravel migration that properly handles these unsupported types?

There is a package that can do this for you: https://github.com/shiftonelabs/laravel-nomad/
It has a function with this signature:
public function passthru($realType, $column, $definition = null)
{
return $this->addColumn('passthru', $column, compact('realType', 'definition'));
}
That is used like
class CreateUsersTable extends Migration {
public function up()
{
Schema::create('users', function(Blueprint $table)
{
$table->increments('id');
$table->passthru('citext', 'name');
$table->passthru('citext', 'title')->nullable();
$table->passthru('string', 'email', 'varchar(255)')->unique();
$table->passthru('string', 'password')->definition('varchar(60)');
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Schema::drop('users');
}
}
It extends the BaseBlueprint class and uses the function addColumn
https://laravel.com/api/5.2/Illuminate/Database/Schema/Blueprint.html#method_addColumn

Related

How to alter the column in laravel?

I am using laravel and mysql database ,i want to change the column type and data what ever present inside the database can you please help me to acheive this one..
Schema::table('users', function (Blueprint $table) {
// DB::query("ALTER TABLE `users`.`percentage` CHANGE COLUMN `percentage/100` Decimal(23,4) NUllable ;");
$table->decimal('percentage')->storedAs("'percentage' / 100");
});
Question: Updating table schema without affecting data in Laravel
For example this is your database migrate file:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateUsersTable extends Migration {
public function up()
{
Schema::create('users', function(Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email');
$table->string('percentage');
$table->timestamps();
});
}
public function down()
{
Schema::drop('users');
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class changeColumnUsersTable extends Migration {
public function up()
{
Schema::table('users', function($table)
{
$table->decimal('percentage', 23, 4)->change();
});
}
public function down()
{
Schema::table('users', function($table)
{
$table->decimal('percentage', 23, 4)->change();
});
}
}
Then migrate using the command,
php artisan migrate
In the Laravel Documentation, there's a Updating Column Attributes
But the thing is ->change() doesn't work with storeAs, so you may want to use a raw query here:
public function up()
{
DB::statement("ALTER TABLE `users` CHANGE `percentage` `percentage` DECIMAL(23,4) AS (('percentage' / 100)) STORED");
}
Here is official documentation of Laravel regarding this issue : Updating Column Attributes

How to insert a different value for existing rows than the default in a migration that adds a new column to a table

I have a migration that updates a table to add a new column:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddStringNormalizationSettingToDataSourcesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('data_sources', function (Blueprint $table) {
$table->char('do_string_normalization', 1)->default('n')->after('vat_mode');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('data_sources', function (Blueprint $table) {
$table->dropColumn('do_string_normalization');
});
}
}
This works fine, the column is created and all existing rows have the value 'n'. However I would like the default to actually be 'y' so new rows will get created with the value 'y' unless otherwise specified.
How would I specify a different value for the default after the column is created and the existing rows are updated?
I have tried adding a line after the original column insert:
$table->char('do_string_normalization', 1)->default('n');
$table->char('do_string_normalization', 1)->default('y')->change();
But it throws the following exception when running the migration:
Unknown column type "char" requested. Any Doctrine type that you use has to be registered with \Doctrine\DBAL\Types\Type::addType(). You can get a list of all the known types with \Doctrine\DBAL\Types\Type::getTypesMap(). If this error occurs during database introspection then you might have forgotten to register all database types for a Doctrine Type. Use AbstractPlatform#registerDoctrineTypeMapping() or have your custom types implement Type#getMappedDatabaseTypes(). If the type name is empty you might have a problem with the cache or forgot some mapping information.
Googling the string "Unknown column type "char" requested" leads to an issue on the laravel framework's tracker where it is suggested that you can not modify a newly created column in the same migration. I could, I guess, create another migration to change the default. But I would rather not have two migrations just to add a single file if possible. Is it?
Update
After further testing (with multiple migration files and two Schema::table() calls) the issue seems to actually be that doctrine (the package from Symphony used by Laravel to make modifications to existing tables) does not support the char datatype. So this works fine:
public function up()
{
Schema::table('data_sources', function (Blueprint $table) {
$table->string('do_string_normalization', 1)->default('n');
});
Schema::table('data_sources', function (Blueprint $table) {
$table->string('do_string_normalization', 1)->default('y')->change();
});
}
As does this:
public function up()
{
Schema::table('data_sources', function (Blueprint $table) {
$table->boolean('do_string_normalization')->default(false);
});
Schema::table('data_sources', function (Blueprint $table) {
$table->boolean('do_string_normalization')->default(true)->change();
});
}
But this throws up an exception:
public function up()
{
Schema::table('data_sources', function (Blueprint $table) {
$table->char('do_string_normalization', 1)->default('n');
});
Schema::table('data_sources', function (Blueprint $table) {
$table->char('do_string_normalization', 1)->default('y')->change();
});
}
If I understand you correctly, you have an existing table with many rows in it already, and you would like to add a column to this table. For all existing rows you would like the value of the new column to be set to 'n', and for all new rows being added to the table you would like the default to be 'y'.
You can achieve using a raw db statement. This is necessary since there are likely compatibility issues between database types that prevents Doctrine from being able to support changing char type columns.
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('data_sources', function (Blueprint $table) {
$table->char('do_string_normalization', 1)->default('n')->after('vat_mode');
});
// Note this may not be compatible with all DBs
DB::statement('ALTER TABLE data_sources ALTER do_string_normalization SET DEFAULT "y";');
}

How to change database column 'null' to 'nullable' using laravel migration in mysql?

This is my vehicles table. I want to change my database structure by using a migration
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateVehiclesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('vehicles', function (Blueprint $table) {
$table->increments('id');
$table->string('image')->nullable();
$table->string('reg_no')->unique();
$table->string('fuel_type');
$table->string('capacity');
$table->double('rate');
$table->boolean('req_carrier');
$table->date('service_date');
$table->integer('service_freq_km');
$table->integer('service_freq_months');
$table->date('insurance_date');
$table->integer('insurance_freq_months');
$table->date('eco_date');
$table->integer('eco_freq_months');
$table->date('licence_date');
$table->integer('licence_freq_months');
$table->integer('current_company');
$table->string('status')->default("available");
$table->timestampsTz();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('vehicles');
}
}
I want to give nullable values to these columns.
1.service_date
2.service_freq_km
3.service_freq_months
How can I alter these columns as nullable in mysql?
You can read the docs about Modifying Columns.
If you want these feature, you need to install this package first:
composer require doctrine/dbal
Then, you need to create another migration, for example:
2019_10_24_xxxxxx_change_columns_to_nullable_in_vehicles.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class ChangeColumnsToNullableInVehicles extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('vehicles', function (Blueprint $table) {
$table->date('service_date')->nullable()->change();
$table->integer('service_freq_km')->nullable()->change();
$table->integer('service_freq_months')->nullable()->change();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('vehicles', function (Blueprint $table) {
$table->date('service_date')->nullable(false)->change();
$table->integer('service_freq_km')->nullable(false)->change();
$table->integer('service_freq_months')->nullable(false)->change();
});
}
}
install the package in order to update the tables composer require doctrine/dbal
Since you have migrated the migration files, you now need to create a new migration file using artisan command:
php artisan make:migration change_nullable_field_columns_to_vehicles_tables --table=vehicles
In newly created migration file, add the following codes
public function up() {
Schema::table('vehicles', function (Blueprint $table) {
$table->date('service_date')->nullable()->change();
$table->integer('service_freq_km')->nullable()->change();
$table->integer('service_freq_months')->nullable()->change();
});
}
//For php artisan down
public function down(){
Schema::table('vehicles', function (Blueprint $table) {
$table->date('service_date')->nullable(false)->change();
$table->integer('service_freq_km')->nullable(false)->change();
$table->integer('service_freq_months')->nullable(false)->change();
});
}
Now you can execute migrate command
php artisan migrate
You need to create new migration file that is name "2019_10_24_00000_update_vehicle_tables"
if(Schema::hasTable('vehicles')) {
Schema::table('vehicles', function($table)
{
$table->date('service_date')->nullable();
$table->integer('service_freq_km')->nullable();
$table->integer('service_freq_months')->nullable();
});
}
create new migration class for alter table and use this up function
public function up()
{
Schema::table('vehicles', function (Blueprint $table) {
$table->date('service_date')->nullable();
$table->integer('service_freq_km')->nullable();
$table->integer('service_freq_months')->nullable();
});
}
Schema::table use for alter table and Schema::create is use for create new table
$table->string('first_name')->default('DEFAULT');
If the default value is supposed to be null, make it nullable instead.
$table->string('name')->nullable();
$table->string('name')->nullable()->default('NULL');
$table->string('name')->nullable()->default(NULL);
$table->string('name')->nullable()->default();

how to rename foreign key in Laravel

I want to rename the foreign key in Laravel.
This is how, I have created it:
Schema::create('holidays', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->integer('account_id')->unsigned();
$table->date('holiday_date');
});
if (Schema::hasTable('accounts')) {
Schema::table(
'holidays',
function (Blueprint $table) {
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
}
);
}
And now, I want to change account_id to engagement_id. How to do that?
It should be something like this :
Note : Before Renaming Foreign, You Must Need To Delete Old Foreign And Assign New One
class RenameColumn extends Migration
{
public function up()
{
Schema::table('holidays', function(Blueprint $table) {
$table->dropForeign('holidays_account_id_foreign');
$table->renameColumn('account_id', 'engagement_id');
$table->foreign('engagement_id')->references('id')->on('accounts')->onDelete('cascade');
});
}
public function down()
{
Schema::table('holidays', function(Blueprint $table) {
$table->dropForeign('holidays_engagement_id_foreign');
$table->renameColumn('account_id', 'engagement_id');
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
});
}
}
What #rborum explained requires doctrine/dbal package to be installed. Else you could directly execute sql query to rename your key or do any other changes.
I was able to do this without dropping the column.
Very simply:
public $oldIndex = 'old_constraint_name_foreign';
public $newIndex = 'new_constraint_name_foreign';
public $oldColumn = 'old_column_name';
public $newColumn = 'new_column_name';
Schema::table('my_table', function (Blueprint $table) {
$table->renameIndex($this->oldIndex, $this->newIndex);
$table->renameColumn($this->oldColumn, $this->newColumn);
});
You need to make a new migration with:
php artisan make:migration rename_column
With this inside:
class RenameColumn extends Migration
{
public function up()
{
Schema::table('accounts', function(Blueprint $table) {
$table->renameColumn('account_id ', 'engagement_id');
});
}
public function down()
{
Schema::table('accounts', function(Blueprint $table) {
$table->renameColumn('account_id ', 'engagement_id');
});
}
}
Then execute your migration:
php artisan migrate
If you do not already have it, you will need Doctrine. You can get this via composer with
composer require doctrine/dbal

How to get nested array from `sql/mysql` under a common column using `groupby` without using foreach to structure the data?

Lets say the table tracker contains this columns(id,section,user_id,message) and other one is user table which contains user data and user_id is the foreign key in the table tracker so I am using join to get the name from user table and I am using laravel.
The response is like this:-
{'id'=1,'name'='pavan','section'='marketing','message'='something'}
The required structure is a nested array under user_id like this:-
{
//user_id 1:
[name,section,message],
2:
[name,section,message]
}
How do I get this using MySQL query?
//user model
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
//tracker model
public function up()
{
Schema::create('trackers', function (Blueprint $table) {
$table->increments('id');
$table->enum('section',['Marketing','Sales','Customer','Trainer','Operations']);
$table->string('subject')->nullable();
$table->longText('content');
$table->enum('status',['processing','resolved']);
$table->date('date');
$table->unsignedInteger('user_id');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
});
}
//get data method in tracker model
public function getdata(){
return \DB::table('trackers')
->join('users','users.id','=','trackers.user_id')
->select('trackers.user_id','users.name',
'trackers.created_at','trackers.id','date',
'trackers.status','trackers.section','trackers.content')
->orderBy('created_at','DESC')->get();
}
//query
$dat=new Tracker;
$data=$dat->getdata()->where('date',Carbon::today()->
toDateString())->where('status','processing');
$dat=new Tracker;
$data=$dat->getdata()->where('date',Carbon::today()->
toDateString())->where('status','processing')->get();
get() will return the collection after getting the collection you can use
You can data like this with
$dat->groupBy('user_id');
This will return the data as you expected.
You can get more information about collection->groupby()
https://laravel.com/docs/5.6/collections#method-groupby