laravel migration for change column type that used in a view - laravel

I use laravel migartion to create some tables and then i create a migration for a view that use my tables.
now, i want to change type of column that used in this view (i create a new migration for it.).but, PostgreSQL does not let me to change column type because column is used in view. i want to know what is best way to manage this issue.
i tried to use migration that created view to drop then and recreate it after changing column type but there is problem because migrations doesn't have namespaces and i don't know is it good way for solving this problem.

First, my English is not good. What i understand is, you are creating a new migration with already existing table? If the table is already existed then you may try to change the column name using this
Schema::table('users', function (Blueprint $table) {
$table->string('name', 50)->change();
});
Laravel Documentation

I fix my issue with following level:
add folder common-queries in project/database/migrations/
add CommonQueries namespace in composer.json with project/database/migrations/common-queries folder location.
add my view create and drop in a class MyCurrentView (for example).
use this class in old migration up and down function for creating and droping view
use this class in new migration and drop view before changing column type and create view after changing column type.

Related

Adding new enum type to the existing enum column in Laravel migration

I am developing a Laravel application. What I am trying to do now is that I am trying to add a new enum type to the existing enum column.
This is how enum column is created/ migrated in the first place.
$table->enum('type', [BlogType::IMAGE, BlogType::TEXT]);
Now I am trying to add a new enum type to that column creating a new migration like this.
Schema::table('blogs', function (Blueprint $table) {
$table->enum('type', [BlogType::IMAGE, BlogType::TEXT, BlogType::VIDEO])->change();
});
As you can see, I added a VIDEO blog type.
When I run the migration, I got the following error.
Unknown database type enum requested, Doctrine\DBAL\Platforms\MySqlPlatform may not support it.
Then I came across this link, Laravel 5.1 Unknown database type enum requested.
I tried adding the following in the constructor of the migration class.
\Illuminate\Support\Facades\DB::getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
Then I got the following error when I run the migration.
Unknown column type "enum" 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.
Now I am not renaming the column, I am just adding the new supported enum value. What would be the best solution and how can I do that, pelase?
For now, we have only one solution: RAW query
public function up()
{
DB::statement('
ALTER TABLE `blogs` CHANGE COLUMN `type` `type`
ENUM("'.implode([BlogType::IMAGE, BlogType::TEXT, BlogType::VIDEO], '", "').'")
NOT NULL
DEFAULT "'.BlogType::IMAGE.'"
');
}
Where blogs is table name and type column name.

What is the best way to copy data from one field to another when creating a migration of a new field?

I have a database table having a field that has a boolean field type. Now, as per the new requirement, the field should be changed to the small integer type.
In order to achieve it, I created a migration and added the script in the same migration file to copy the value from the old field to the new field. However, I think this is not the best approach that I have followed. Can someone please help and advise about the best way to handle this scenario.
public function up()
{
Schema::table('skills', function (Blueprint $table) {
$table->tinyInteger('skill_type_id')->nullable()->comment = '1 for advisory skills, 2 for tools, 3 for language & framework';
});
$skill_object = (new \App\Model\Skill());
$skills = $skill_object->get();
if (_count($skills)) {
foreach($skills as $skill) {
$skill_type = 1;
if ($skill->is_tool) {
$skill_type = 2;
}
$skill_object->whereId($skill->id)->update(['skill_type_id' => $skill_type]);
}
}
}
You can do it with 02 migrations, the first one is to create the new field, as already did. The second is create a migration with raw statement to copy value from old field to new field.
If you don't need anymore old field, you can create a third migration deleting the old field.
public function up()
{
Schema::table('skills', function (Blueprint $table) {
DB::statement('UPDATE skills SET skill_type_id = IF(is_tool, 2, 1)');
}
}
You can do this(update the data) from the following way in your scenario.
Create separate routes and update the data after the migrations.
Create seeder(having the same query as above in migrations file) run the seeder.
But above both solutions are little risky if you are trying to do this with your production database. If someone mistakenly hit URL and run seeder multiple time, It's difficult to manage.
I believe the best way to solve your problem by seed(modify) the data on the same migrations file after modifying the schema because migrations won't run again (even mistakenly), Once it migrated.
You are doing the correct way as I believe.
You are free to develop your own way to achieve this task, but as far as migrations are concerned, these are meant for controlling and sharing the application's database schema among the team, not the actual data ;)
You can create separate seeder for this task.
It will keep your migration clean and easy to rollback if needed.
NOTE: Don't include this seeder class in DatabaseSeeder.
These kind of seeder class are only meant for update the existing data after fixing the current functionality(I am taking into consideration, you have already fixed the code as per your new requirement). So, there is not need to worry about re run the same seeder class.
Considering (laracast, stack-overflow), i will prefer to go by your way over the suggestions provided above as neither i have to maintain extra route nor additional migration (03).
The only improvement i can suggest here is you can use databse-transaction something like this :
// create new column
DB::transaction(function () {
update new column
delete old column
});

Laravel Database migrations Schema builder custom column type

I am trying to create migrations with Laravel but I am in a situation where I need custom column type since the one I want isn't included in schema builder , which is "POLYGON". So I want to know, how I can create my custom column type, other than those that are already in the Schema builder.
What I want would look like this in SQL statement:
alter table xxx add polygon POLYGON not null
Is it possible to do it by myself or I am forced to use some library like this?
I know that I can do like this:
DB::statement('ALTER TABLE country ADD COLUMN polygon POLYGON');
but it leads me to the error that the table doesn't exist.
There is no built in way to do this but you can achieve a good result with minimal code.
<?php
use Illuminate\Database\Schema\Grammars\Grammar;
// Put this in a service provider's register function.
Grammar::macro('typePolygon', function (Fluent $column) {
return 'POLYGON';
});
// This belongs in a migration.
Schema::create('my_table', function (Blueprint $table) {
$table->bigIncrements('id');
$table->addColumn('polygon', 'my_foo');
});
The key is to add a function with the name typePolygon to the Grammar class because this function is what determines the actual type used by the particular DBMS. We achieve this by adding a macro to the Grammar.
I have written a blog post about how to extend this solution to any custom type: https://hbgl.dev/add-columns-with-custom-types-in-laravel-migrations/
I assume you require spatial fields in your DB... I would consider via Packagist.org and search for laravel-geo (or equivalent) - which supports spatial column tyes inc Polygon. You could then use standard Laravel migration files for your custom fields -e.g.
$table->polygon('column_name');
In your UP function in your migration file...

Update Schema via an Eloquent Model, Laravel 5.2

i'd like to know if it's possible at all to update the table schema in a Migration through a specific Eloquent Model, or if i actually need to pass in the name of the Table and Connection every single time.
I ask this because in my case this requires an additional configuration file that my package must publish to the end users, apart from the already required table Eloquent model (which is used for other purposes)
You can update schema later and add or drop columns and/or index.
To do this you create a new migration and add the changes there. It will change the table over your previous version.
More info in Laravel documentation.
For renaming the table
Schema::rename($from, $to);
https://laravel.com/docs/5.2/migrations#renaming-and-dropping-tables

Adding new columns to an Existing Doctrine Model

First of all Hats of to StackOverflow for their great service and to you guys for taking your time to answer our questions.
I am using Doctrine ORM 1.2.4 with CodeIgniter 1.7.3. I created a Site with some required tables and pumped in with datas only to realize at a later point of time that a specific table needs to have one more column.
The way i created the tables was by writing the model as php classes which extend the Doctrine_Record.
Now i am wondering if i need to just add the column in the model that requires a new column in the setTableDefinition() method and recreate that table or is there any other way that easily does this. The former method i've mentioned requires me to drop the current table along with the datas and recreate the table which i do not wish. Since doctrine seems to be a very well architect-ed database framework, i believe it is lack of my knowledge but surely should exist a way to add new columns easily.
PS: I am not trying to alter a column with relations to other tables, but just add a new column which is not related to any other table. Also i create the tables in the database using Doctrine::createTablesFromModels(); When i alter a table with a new column and run this method it shows errors.
Since you don't want to drop & recreate, use a Doctrine Migration.
The official docs here show many examples:
http://www.doctrine-project.org/projects/orm/1.2/docs/manual/migrations/en
Since you just want to add a field, look at their second code example as being the most relevant which is like this:
// migrations/2_add_column.php
class AddColumn extends Doctrine_Migration_Base
{
public function up()
{
$this->addColumn('migration_test', 'field2', 'string');
}
public function down()
{
$this->removeColumn('migration_test', 'field2');
}
}

Resources