私が現在管理するプロジェクトのほとんどは、Laravelのフレームワーク採用以前から存在したphpのプロジェクトです。嬉しいことにお客様から移行の機会を与えられて、ほとんどLaravelに書き換えることができました。しかし、それらのプロジェクトのDBの管理には、Laravelのmigrationを使用していません。私が開発したオンラインのツールが生成するSQLファイルでDBの変更を行っています。最近になって、プロジェクトのデータベーステストを行う必要が出て、migrationのファイルを用意しなければなくなりました。
どうして、migrationのファイルが必要?
今までは、dbunitなるものを使用してデータベーステストを行っていましたが、これが去年に作者(phpunitの作者でもある)の意向で開発が停止となりました。それゆえに、テストにおいてLaravelのRefreshDatabaseトレイトの使用に変えていくことが突然に必要になったわけです。
RefreshDatabaseは、毎回のテストの実行において、
$ php artisan migrate:fresh
の実行と同様に、migrationファイルで定義されたDBのテーブルをすべて削除し、再度一からそれらを作成します。つまり、データベースのテーブルをすべてゼロレコードの状態としてくれます。それゆえに、既存のDBのすべてのテーブルのmigrationを作成する必要があるのです。
migrationファイル自動生成ツール
既存のDBからmigrationファイルを作成するツールはないかと、探した結果、以下のツールが出てきました。
https://github.com/Xethron/migrations-generator
ツールのインストールには、
$ composer require --dev "xethron/migrations-generator"
をコマンドラインで実行します。
migrationファイルを作成するには、artisanの実行となります。laravel 5.8で新規のプロジェクトを作成して実行してみました。
$ php artisan migrate:generate Using connection: mysql Generating migrations for: password_resets, users Do you want to log these migrations in the migrations table? [Y/n] : > y Next Batch Number is: 2. We recommend using Batch Number 0 so that it becomes the "first" migration [Default: 0] : > 2 Setting up Tables and Index Migrations Created: /vol1/usr/www/repos/repos/l58-new/database/migrations/2020_01_08_191742_create_password_resets_table.php Created: /vol1/usr/www/repos/repos/l58-new/database/migrations/2020_01_08_191742_create_users_table.php Setting up Foreign Key Migrations Finished!
上の実行においては、2つ質問が尋ねられます。
最初は、migrationsのDBテーブルにログを作成するか?
2番目は、そのログにおいてのバッチ番号をなんとするか?
上では、yと2と答えたところ、migrationsのデータは以下のようになりました。
mysql> select * from migrations; +----+------------------------------------------------+-------+ | id | migration | batch | +----+------------------------------------------------+-------+ | 1 | 2014_10_12_000000_create_users_table | 1 | | 2 | 2014_10_12_100000_create_password_resets_table | 1 | | 3 | 2020_01_08_191742_create_password_resets_table | 2 | | 4 | 2020_01_08_191742_create_users_table | 2 | +----+------------------------------------------------+-------+ 4 rows in set (0.00 sec)
すでに、php artisan migrate
が実行されていたので、最初の2つのレコードはそのときに生成されていたものです。これらはLaraelのデフォルトのmigrationファイルです。
一方、generateで生成されたのは次の2つのレコードですが、見ての通り既存のものと重複となってしまいました。既存のDBをもとに1からDBテーブルを作成するという目的では、generate実行の前にmigrationsテーブルを空としたほうが良さそうですね。
さて、生成されたものと、デフォルトのmigrationファイルを比べてみましょう。
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->bigIncrements('id'); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('users'); } }
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('users', function(Blueprint $table) { $table->bigInteger('id', true)->unsigned(); $table->string('name'); $table->string('email')->unique(); $table->dateTime('email_verified_at')->nullable(); $table->string('password'); $table->string('remember_token', 100)->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('users'); } }
やや違いがありますね。例えば、email_verified_atの定義、なぜかtimestampからdateTimeとなっています。
また、bigIncrementやrememberTokenに対応するフィールドも生成では変わっています。しかし、これらは、実行されるDBテーブルでは同じとなります。
ということで、mysqldumpの結果と見比べて、手動での調整が必要となりそうです。しかし、かなりの部分を作成してくれるので十分使えそうです。
メルマガ購読の申し込みはこちらから。