DDLを書いていた頃が懐かしい。。。今はマイグレーションを使ってテーブル構造もバージョン管理するようになりました。
ローカルにDBがある場合は気軽にできるかもしれませんが、DBを共有している場合は慎重に行うことには今も昔も変わりません。
ということで、前回からの流れでマイグレーションがどのように動くのか見てみます。
クライアント環境:Windows10 XAMPP(PHP7.0.4) Eclipse 4.5.2(Mars) Laravel5.2.33
サーバ環境:CentOS7 MariaDB5.5.47
マイグレーション
・実行
>php artisan migrate
「database/migrations」にある実行されていないものが古い順に全て実行される。
※リビジョン?バージョン?情報は「migrations」テーブルにある。
・ロールバック(リビジョン?バージョン?を1つ戻す)
>php artisan migrate:rollback
※「migrations」テーブルにあるbatchが一番大きいクラスを全て実行する感じ。
・リセット(初期状態に戻す)
>php artisan migrate:reset
※ただし、再度マイグレーションすると「migrations」テーブルのbatchは全て1になるので、rollbackは初期状態に戻す形となる。
・再マイグレーション(初期状態に戻してマイグレーション実行)
>php artisan migrate:refresh
「–seed」オプションが有る時は「/database/seeds/DatabaseSeeder.php」の初期データが投入される。追加したSeederは読み込まれないのか、他にも設定があるのかわからない。
・マイグレーションで”class not found”エラーが出る場合
>composer dump-autoload
上記を実行して再度マイグレーションするとよいかもしれない。
テーブルの追加
マイグレーション用クラスの準備
>php artisan make:migration <<クラス名>> --create=<<テーブル名>>
「database/migrations」にファイルが追加される。
クラス名は他と重複しないようにする。(マイグレーションのロールバックでエラーになります。)
命名基準としては以下の感じがよいかな。。。
<<create|alter|drop>>_<<テーブル名>>_<<YYYYMMDD>>_table
追加されたファイルの内容(tasksテーブルの例)
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTasksTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('tasks', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('tasks');
}
}
マイグレーション実行時にupメソッドが呼ばれて、rollbackでdownメソッドが呼ばれる。
テーブルにコメントを設定したいけど、どうするのかな。。。
普通にクエリー発行してコメントをつけるのなら、「Schema::create」の後に
「ALTER TABLE tasks comment=”コメント名”」をDB::statementで実行するぐらいしか思いつかない・・・
列の追加
コマンドプロンプト
>php artisan make:migration <<クラス名>> --table=<<テーブル名>>
追加されたファイルにnameカラムを追加(tasksテーブルの例)
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AlterTasksTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('tasks', function (Blueprint $table) {
$table->string("name", 100)
//->first() // カラムを先頭に持ってくる
->nullable() // NULLを許容
->after('id') // カラムの場所をIDカラムの後ろに
->comment('タスク名') // 列名のコメント
->default('うにうに') // デフォルト値
//->unsigned() // 符号なしに。
;
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('tasks', function (Blueprint $table) {
$table->dropColumn("name");
});
}
}
これで、nameカラムが追加され、rollbackするとnameカラムが削除される。
列の場所も変更できるし、列にコメントを設定できるしいい感じ。
列の変更
public function up()
{
Schema::table('tasks', function (Blueprint $table) {
$table->string('name', 200)->change();
});
}
マイグレーションを実行するとエラーとなる。
[RuntimeException]
Changing columns for table "tasks" requires Doctrine DBAL; install "doctrin
e/dbal".
DBALが必要なのね・・・
「composer.json」をいじる
"require": {
"php": ">=5.5.9",
"laravel/framework": "5.2.*",
"doctrine/dbal": ">=2.0" ← 追加(どのバージョンが良いかは不明・・・)
},
コマンドプロンプトで「composer update」(ちょっと時間かかる)
>composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Removing laravel/framework (v5.2.32)
- Installing laravel/framework (v5.2.33)
Downloading: 100%
- Removing mockery/mockery (0.9.4)
- Installing mockery/mockery (0.9.5)
Downloading: 100%
- Installing doctrine/lexer (v1.0.1)
Downloading: 100%
- Installing doctrine/annotations (v1.2.7)
Downloading: 100%
- Installing doctrine/collections (v1.3.0)
Downloading: 100%
- Installing doctrine/cache (v1.6.0)
Downloading: 100%
- Installing doctrine/common (v2.6.1)
Downloading: 100%
- Installing doctrine/dbal (v2.5.4)
Downloading: 100%
Writing lock file
Generating autoload files
Warning: Ambiguous class resolution, "AlterTasksTable" was found in both "D:/xampp7.0.4/htdocs/laravel_trial/database/migrations/2016_05_25_075114_alter_tasks_table.php" and "D:/xampp7.0.4/htdocs/laravel_trial/database/migrations/2016_05_26_022139_alter_tasks_table.php", the first will be used.
> Illuminate\Foundation\ComposerScripts::postUpdate
> php artisan optimize
Generating optimized class loader
あら?ワーニングが出る…同名のクラスをだとロールバックやらマイグレーションで戻せなくなる。クラス名の命名基準で、作成日時を入れるとか必要かと。
気を取り直して再度マイグレーションすると、列名の変更ができた。
参考)
インデックス、プライマリキー、外部キー
省略・・・(気が向いたら後日・・・)
初期データ
参照)
コマンドプロンプト
>php artisan make:seeder TasksTableSeeder
「/database/seeds/TasksTableSeeder.php」ができる。
<?php
use Illuminate\Database\Seeder;
class TasksTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
// サンプルで、100件をtasksテーブルに投入する。
for($i = 0; $i < 100; $i++) {
DB::table('tasks')->insert([
'name' => 'task_name' . $i,
]);
}
}
}
モデルを使う方法とかいろいろとあるので、その時に応じて作成。
コマンドプロンプトで初期データを投入する
>php artisan db:seed --class=TasksTableSeeder
負荷試験用のデータ準備とかで便利だ。
マイグレーションについて戯れてみましたが、実際の開発でとなるといろいろとルールの整備がかなり必要かなぁと思う。