🌱

Laravel Seederクラスと対話して任意の値を渡す

2023/08/10に公開

はじめに

Seederクラスを使ってテストデータを作る際にdb:seedコマンドを使いますが、
ここに任意のオプションで何件作るとか指定したいけど、実際に指定すると怒られたので別の方法を模索した結果を残しておきます。

環境

  • PHP 8.2.8
  • Laravel 10.18.0

オプションで指定すると怒られる

この記事のはじめに書いたけど、実際に指定すると怒られます。

$ php artisan db:seed --class=\\Database\\Seeders\\DatabaseSeeder --count=1

                                        
  The "--count" option does not exist.  
                                        

なぜ怒られるか

いろいろ追いかけると、コマンドの起動時にオプションのチェックが動くようで、
SeedCommandクラスのgetOptionsメソッドに指定している内容以外はエラーにしているようです。

  • getOptionsメソッド

https://github.com/laravel/framework/blob/v10.18.0/src/Illuminate/Database/Console/Seeds/SeedCommand.php#L132-L139

  • 実際にエラーにしている箇所

https://github.com/symfony/console/blob/v6.3.2/Input/ArgvInput.php#L219-L224

どのようにして任意の値を渡すのか

コマンドクラスを自作するとか、環境変数やconfigで渡すとかなどやり方は色々ありますが、
今回は記事のタイトルに書いてある通りSeederクラスと対話します!!

Seederクラスにはプロパティには$commandというプロパティがあり、このプロパティにはSeederクラスのインスタンス作成時にSeedCommandクラスのインスタンスを設定しています。

https://github.com/laravel/framework/blob/v10.18.0/src/Illuminate/Database/Seeder.php#L21-L26

https://github.com/laravel/framework/blob/v10.18.0/src/Illuminate/Database/Console/Seeds/SeedCommand.php#L98-L100

つまり、コマンドクラスに用意されているこちらのコマンド実行中に任意の値を入力ができる対話機能が使えるわけですね。
https://laravel.com/docs/10.x/artisan#prompting-for-input

実装

対話機能を使って、雑にサクッとSeederクラスを作ってみます。

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        $count = $this->command->ask('何件作る? 数字で入力してね');
        if (is_numeric($count) === false) {
            $this->command->error('数字で入力してね');
            return ;
        }

        $this->command->info('作成前' . \App\Models\User::count() . '件');

        \App\Models\User::factory((int) $count)->create();

        $this->command->info('作成後' . \App\Models\User::count() . '件');
    }
}

実行

では、作ったやつを実行してみます。

$ php artisan db:seed --class=\\Database\\Seeders\\DatabaseSeeder

   INFO  Seeding database.  

 何件作る? 数字で入力してね:
 >  

数字で入力してね

$ php artisan db:seed --class=\\Database\\Seeders\\DatabaseSeeder

   INFO  Seeding database.  

 何件作る? 数字で入力してね:
 > q

数字で入力してね

数字でない場合はエラーにしていますね。

$ php artisan db:seed --class=\\Database\\Seeders\\DatabaseSeeder

   INFO  Seeding database.  

 何件作る? 数字で入力してね:
 > 5

作成前0件
作成後5件

登録した内容は別として、
無事にSeederクラスと対話して、5を指定して、5件のテストデータを作成できたことがわかりますね。

まとめ

今回はSeederクラスと対話って形で任意の値を渡して対応しました。
将来的にはもっと楽な方法が生まれるかもしれないですが、こういう方法もあるってことで
1つLaravelの雑学を知ることができましたね。

Discussion