remove Default in migration? - laravel

In the migration I alter enabled field to set to 1 value as default.
public function up()
{
Schema::table('client', function (Blueprint $table) {
$table->boolean('enabled')->default(1)->change();
});
}
In down() method - How do I remove default() ? I know can do default(0) but default was never created during create table.

Surprisingly or not, for NOT NULL fields ->default(null) removes the default from a table:
public function up()
{
Schema::table('client', function (Blueprint $table) {
$table->boolean('enabled')->default(null)->change();
});
}
Just omitting the default() part doesn't work, since laravel makes a diff between current state and current state + specified changes. No changes specified, no diff.
After that, doctrine generates ALTER TABLE statement, treating NULL as no default value.
With nullable fields though, from what I can see, doctrine doesn't let you simply drop the default. The only option is supposedly to make them NOT NULL:
public function up()
{
Schema::table('client', function (Blueprint $table) {
$table->boolean('enabled')->nullable(false)->default(null)->change();
});
}
Maybe with PostgreSQL you can get away without converting to NOT NULL, but that's to be confirmed.

Since there is no way to remove this statement with Laravel functions, your down function must execute the statement as raw. It should be something like:
public function down()
{
DB::statement('ALTER TABLE client ALTER COLUMN enabled DROP DEFAULT');
}
In order to execute this migration, you need to include at the top of your migration:
use Illuminate\Support\Facades\DB;

Related

How to limit probable entry from user in migration?

What if I try to limit possible entries in migration level in Laravel. For instance i have a migration:
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('type')
$table->timestamps();
});
}
Now I want to accept anything from image, post, bio for the type column. if the user try to save anything except the 3 options, i want the DB to deny. How can I do so ?
You can use an enum column allowing only the defined values.
https://laravel.com/docs/8.x/migrations#column-method-enum
$table->enum('type', ['image', 'post', 'bio']);

How to migration change columns type?

I got an error, When I try to column type from string to text, With migration function of Laravel.
File : {data_time}_change_db_structure.php
public function up()
{
Schema::table('service_request_type', function (Blueprint $table) {
$table->dropIndex(['sro_key_group']);
$table->text('sro_key_group')->change();
$table->renameColumn('sro_key_group', 'tags');
});
}
This is orginal migration create table file.
public function up()
{
Schema::create('service_request_type', function (Blueprint $table) {
$table->engine = 'InnoDB';
...
$table->string('sro_key_group', 100)->nullable()->index();
...
});
}
Error I got.
[Illuminate\Database\QueryException]
SQLSTATE[42000]: Syntax error or access violation: 1170 BLOB/TEXT
column 'sro_key_group' used in key specification without a key length
(SQL: ALTER TABLE service_request_type CHANGE sro_key_group sro _key_group TEXT DEFAULT NULL COLLATE utf8_unicode_ci)
[Doctrine\DBAL\Driver\PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1170 BLOB/TEXT
column 'sro_key_group' used in key specification without a key length
[PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1170 BLOB/TEXT
column 'sro_key_group' used in key specification without a key length
What wrong? And I already install doctrine/dbal in my composer.json.
You'll need to do this in three steps, either using three separate migrations, or three calls to table() as you've shown in your answer.
The first issue is that, even though you've written your statements in the order you'd like them to execute (and the order they need to execute), the schema builder will actually rearrange the order so that "change" statements are executed first. The schema builder treats new columns and changed columns as "implied" statements, and moves them to the top of the stack of commands to run. However, rename statements are not considered "change" statements.
So, even though you've written the code to:
[
remove index,
change column from varchar to text,
rename column,
]
The schema builder will actually execute:
[
change column from varchar to text,
remove index,
rename column,
]
Now, since the change command is happening before the column is removed from the index, you are getting the 1170 error.
The next issue is with attempting to do the column change and the column rename in the same context. The SQL to implement the requests changes is generated by doing schema diffs, however both schema diffs will be done before any changes are actually made. So, the first change from varchar to text will generate the appropriate SQL to make that change, but then the second change to rename the column will actually generate SQL that changes the column back to a text field while renaming it.
To work around these issues, you can either create three migrations, where the first migration simply drops the index, the second migration changes the type, and then the third migration renames it, or you can keep your one migration and run three table() statements.
public function up()
{
// make sure the index is dropped first
Schema::table('service_request_type', function (Blueprint $table) {
$table->dropIndex(['sro_key_group']);
});
// now change the type of the field
Schema::table('service_request_type', function (Blueprint $table) {
$table->text('sro_key_group')->nullable()->change();
});
// now rename the field
Schema::table('service_request_type', function (Blueprint $table) {
$table->renameColumn('sro_key_group', 'tags');
});
}
Ahhhhhh mannnnn...
I got the answer.
public function up()
{
Schema::table('service_request_type', function (Blueprint $table) {
$table->dropIndex(['sro_key_group']);
});
Schema::table('service_request_type', function (Blueprint $table) {
$table->text('sro_key_group')->nullable()->change();
});
Schema::table('service_request_type', function (Blueprint $table) {
$table->renameColumn('sro_key_group', 'tags');
});
}
Hmmmmmmm WTF is that?

Laravel - How to change column type (smallInteger => string)

The documentation doesn't say anything about changing data type with migrations.
I have this column in my DB table
$table->smallInteger('driverslicensetype')->nullable();
and I am saving four-digit numbers, but when the number begins with 0 (a zero) for example 0230 it will be saved as 230 in DB. And that is wrong.
Now i want to change this column data type from smallInteger to varchar.
How can i do this through migrations?
To use the schema changing feature, you need Doctrine DBAL:
composer require doctrine/dbal
Now you can use change():
public function up()
{
Schema::table('foo', function (Blueprint $table) {
$table->string('driverlicensetype', 4)->nullable()->change();
});
}
public function down()
{
Schema::table('foo', function (Blueprint $table) {
$table->smallInteger('driverlicensetype')->nullable()->change();
});
}
If you prefer the raw approach (or if your SQL is more restrictive, like when driverlicensetype is a foreign key), use DB::statement:
public function up()
{
DB::statement('ALTER TABLE foo ...');
}
// ...

Drop and then create same columns in current up migration function

Schema::table('users', function (Blueprint $table) {
$table->dropTimestamps();
$table->dropColumn(['email', 'bio']);
$table->string('email', 20)->unique()->after('id');
$table->string('bio', 150)->after('surname');
$table->timestamps();
});
That is what I've got now. So, I have the columns existing atm in my table, but I want to modify and re-arrange them a bit. But when I run the migration, I get SQL error that email column exists. And I will probably get the same error for the bio and timestamps as well. I kind of understand why this happens, so what am I asking is just for a workaround.
Is it possible to make what I want inside one single migration, or I have to create a migration for deleting the columns and then a separate migration for creating them the way I want?
Just break the schema up into two calls
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->dropTimestamps();
$table->dropColumn(['email', 'bio']);
});
Schema::table('users', function (Blueprint $table) {
$table->string('email', 20)->unique()->after('id');
$table->string('bio', 150)->after('surname');
$table->timestamps();
});
}
This way the change is occurring in one migration with two database calls.
Consider that if you drop the columns, you will lose ALL THE DATA contained therein. Normally this is a very bad and dangerous idea. If you instead need to simply change parameters, you should use the change() function to make the required modifications to your schema. This will convert the existing data to the best of your databases's ability.
NEVER DROP COLUMNS on an in-use database unless you absolutely know what you're doing.
public function up()
{
Schema::table('users', function (Blueprint $table) {
// Add the unique constraint, for example
$table->string('email', 20)->unique()->after('id')->change();
// Add the length to the bio, for example
$table->string('bio', 150)->after('surname')->change();
});
}
public function down()
{
Schema::table('users', function (Blueprint $table) {
// Remove length and constraints
$table->string('email')->unique(false)->change();
$table->string('bio')->change();
});
}

laravel migration re-organising column order

When you create a new column in a table you can use the ->after('column name') to dictate where it goes. How can I create a migration that re-orders the columns in the right order I want?
Try this, hope it help you to find right solution:
public function up()
{
DB::statement("ALTER TABLE example MODIFY COLUMN foo DATE AFTER bar");
}
public function down()
{
DB::statement("ALTER TABLE example MODIFY COLUMN foo DATE AFTER bar");
}
If you want to do it without destroying data, you could migrate the data across at the same time you do the schema update:
use DB;
public function up()
{
//Give the moving column a temporary name:
Schema::table('users', function($table)
{
$table->renameColumn('name', 'name_old');
});
//Add a new column with the regular name:
Schema::table('users', function(Blueprint $table)
{
$table->string('name')->after('city');
});
//Copy the data across to the new column:
DB::table('users')->update([
'name' => DB::raw('name_old')
]);
//Remove the old column:
Schema::table('users', function(Blueprint $table)
{
$table->dropColumn('name_old');
});
}
I would suggest a DB::query('.. raw sql query ..'); and use the query from the answer "How to move columns in a MySQL table?"
Try this
public function up()
{
DB::statement("ALTER TABLE example CHANGE foo foo DATA_TYPE DATA_ATTRIBUTE(s) AFTER bar");
DB::statement("ALTER TABLE example CHANGE foo foo INT(10) UNSIGNED NOT NULL AFTER bar");
}
Alternatively if you too lazy to figure out the SQL, you can visit your phpMyAdmin, click your database, click your table, click the Structure tab, besides the column you want to move, click the change button, edit the last Move column column, click the Save button & then copy the SQL.
VERY IMPORTANT NOTE
Use the following solution only if you haven't launched your app yet (i.e. it's not yet used by any real users) as the following solution will delete the column and all data stored in it and will create a new empty column with the same name after the column you determine.
Suppose your column name is address and you want to reorder its position so that it comes after another column called city, and your table name is employees.
In your terminal type the next command:
php artisan migrate:make reorganize_order_of_column_address --table=employees
You may only change reorganize_order_of_column_address and employees according to your needs, but keep the rest of the command as it is.
This will generate a migration file in app/database/migrations folder, open it and put your code inside the up() function like this:
public function up()
{
Schema::table('employees', function(Blueprint $table)
{
$table->dropColumn("address");
});
Schema::table('employees', function(Blueprint $table)
{
$table->string('address')->after("city");
});
}

Resources