アイレット株式会社 DX開発事業部 IoT×クラウドセクション コアエンジニアリンググループの井上です!
前々回の記事:Laravel on Cloud Run:gcloud run jobs executeで複数引数を扱う方法では、
Cloud Run Jobs における複数引数の渡し方について解説しました。
また、前回の記事:Laravel on Cloud Run:DBをプライベート化した本番環境で、安全にマイグレーションを実行する方法では、
DBをプライベート化した環境でのマイグレーション実行についても触れました。
課題:直接インスタンス化すると実行できない?
Laravelのマイグレーションファイル内でマスターデータなどを投入したい際、以下のようにSeederクラスを直接呼び出すコードも一般的かと思います。
// web/app/database/migrations/0001_01_01_000000_create_xxxxx_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Database\Seeders\XxxxxSeeder;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
// Schema::create();の記述
// // Seeder実行
(new XxxxxSeeder())->run();
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('xxxxx');
}
};
ローカル環境や通常のサーバー環境ではこれでも動作しますが、
Cloud Run Jobs(コンテナ環境)で実行した際、クラスのオートロードの関係や実行コンテキストの違いにより、うまく動作しないケースがありました。
解決策:Artisan::call を経由させる
この問題を解決するために、直接クラスを呼び出すのではなく、Artisan::call を経由して Seeder を実行する形に変更しました。
// web/app/database/migrations/0001_01_01_000000_create_xxxxx_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Artisan;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
// Schema::create();の記述
// Seeder実行(Artisan経由)
Artisan::call('db:seed', [
'--class' => 'Database\\Seeders\\XxxxxSeeder'
]);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('xxxxx');
}
};
なぜこの変更が必要だったのか
- 依存関係の解決: Artisan::call を使うことで、Laravelフレームワークが持つサービスコンテナやオートローダーの仕組みを正しく通して実行されるため、コンテナ環境特有のパスの問題を回避できます。
- 実行の堅牢性: 直接 run() メソッドを叩くよりも、コマンドライン経由と同じ挙動になるため、ログの出力やエラーハンドリングがLaravelの標準仕様に則って行われ、デバッグが容易になります。
終わりに
Cloud Run Jobs のようなサーバーレスコンテナ環境では、「できるだけフレームワークの標準機能(Artisan)に乗っかる」ことが、予期せぬエラーを防ぐ近道です。
もしマイグレーションの中でデータ投入がうまくいかず悩んでいる方がいれば、ぜひこの方法を試してみてください!