マイグレーション時にデータも変更/移行する方法(laravel)
マイグレーションをした際に、データを変更したり、移行したりする場合があると思います。
例えば、 記事にタグ付けする際にタグは3つまで!って決まっていのに、仕様変更で無限にタグ付けできるようにしたい場合。想像してみてください。
これまでarticlesテーブルにタグ1, タグ2, タグ3といれていました。
articles
- id
- title
- thumbnail_url
- tag1
- tag2
- tag3
しかし、無限にできるということは 新しくtagsテーブルを作ってarticlesテーブルと紐付けしないといけない!
そうなると、過去のデータも全部tagsテーブルに移行しないといけない!
という風になります。
articles
- id
- title
- thumbnail_url
tags
- id
- name
- article_id
そんなときはtagsテーブルを作り、articlesテーブルからtagsにタグ情報を移行させる必要があります。
そのデータ以降もマイグレーションファイル内で記述するとめちゃくちゃ便利なのです!
1. tagsテーブルを作る
新たにtagsテーブルを新設するので、マイグレーションでtagsテーブルを作成します。
php artisan make:migration create_tags
マイグレーションファイルを作っていきます。
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTags extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('tags', function (Blueprint $table) {
$table->increments('id');
$table->integer("article_id")->unsigned();
$table->string('name');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropTable("tags");
}
}
2. データを移行する
データを移行するためのマイグレーションファイルを作っていきます。
php artisan make:migration transfer_data_from_articles_to_tags
マイグレーションファイルを作っていきます。
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class TransferDataFromArticlesToTags extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
// データを移行する
$articles = Articles::all();
foreach ($articles as $article) {
if ($article->tag1) {
Tag::create(["article_id" => $article->id, "name" => $article->tag1]);
}
if ($article->tag2) {
Tag::create(["article_id" => $article->id, "name" => $article->tag2]);
}
if ($article->tag3) {
Tag::create(["article_id" => $article->id, "name" => $article->tag3]);
}
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
// ロールバック処理(本当はしっかり書いた方が良いかと)
}
}
このようにマイグレーションの内部でデータ移行の処理を書いてしまいます。
マイグレーションは基本スキーマの変更がメインなので、スキーママイグレーションしか書いちゃダメだと感じてしまいますが、個人的にはデータの変更・移行のようなデータマイグレーションも書いちゃって良いと思います。
ロールバックもできて便利ですし、ヒューマンエーラは発生しないですし、ローカルでもステージングでも本番でも php artisan migrate
でデータが移行できるなんて超便利
※十分の注意を払ってくださいね(笑)
articlesのtag1, tag2, tag3を削除する
articlesのtagカラムを削除するためのマイグレーションを作成します
php artisan make:migration remove_tags_column_from_articles --table="artilces"
マイグレーションファイルを仕上げていきます。
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTags extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('articles', function (Blueprint $table) {
$table->dropColumn("tag1");
$table->dropColumn("tag2");
$table->dropColumn("tag3");
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('articles', function (Blueprint $table) {
$table->string("tag1")->after("name");
$table->string("tag2")->after("tag1");
$table->string("tag3")->after("tag2");
});
}
}
終わりに
本記事で伝えたかったことは、ステップ2の部分でマイグレーションファイル内でデータを移行することについてです。
なかなかマイグレーションファイル内でデータ移行の処理を書くことがないかとは思いますが、
同じデータベース内で、データを変更したり移行したりすることがあればぜひ参考にしてみてください。
Discussion