皆さまこんにちは、ウチイダです。
LaravelのSeederが便利でよく使っています。
テスト用のレコードを生成する処理をまとめておくと、いろいろ使いまわしがしやすいです。
でも、困るのがファイル数が増えてきたときの取り扱いです。database/seeders ディレクトリに全部入れてしまうと、ファイルを探しづらくなってしまいます。
というわけで、Seederクラスをサブディレクトリに分けることにしました。
検証環境
- Laravel v9.43.0
- PHP v8.1.13
- Windows11 21H2
サブディレクトリにSeeder クラスファイルを作る
artisan で生成するときに、サブディレクトリを含めて指定するだけでOKです。
$ sail artisan make:seed Subfolder/SampleSeeder
INFO Seeder [database/seeders/Subfolder/SampleSeeder.php] created successfully.
database/seeders/Subfolder 配下に、Seeder クラスを作ってくれました。
artisan コマンドから、サブディレクトリのSeeder を直接呼び出す
ここからが本題です。artisan db:seed は、–class に実行するSeeder クラス名を指定することができます。
これを使って、サブディレクトリにあるSeeder を呼び出します。
ちょっとだけ修正して、テキストだけ表示するように変更します。
<?php
namespace Database\Seeders\Subfolder;
use Illuminate\Database\Seeder;
class SampleSeeder extends Seeder
{
public function run()
{
echo "サブフォルダのSeeder だよ~\n";
}
}
それでは、いざ実行!
# name space を記述しないとエラー
$ sail artisan db:seed --class='SampleSeeder'
INFO Seeding database.
Illuminate\Contracts\Container\BindingResolutionException
Target class [Database\Seeders\SampleSeeder] does not exist.
クラスの名前解決ができません。クラス名だけ書くと、Database/Seeders 内を探すようになっているようです。
では追加の名前空間を指定すると…?
# Seeders 以降のname space を記述してもエラー
$ sail artisan db:seed --class='Subfolder\SampleSeeder'
INFO Seeding database.
Illuminate\Contracts\Container\BindingResolutionException
Target class [Subfolder\SampleSeeder] does not exist.
これでもエラーです。
名前空間を指定する(–class に \ を含む文字列を渡す)と、Database/Seeders は使わなくなってしまいました。
仕方ないので、全部指定します。
# name space を全部書くと名前解決できる
$ sail artisan db:seed --class='Database\Seeders\Subfolder\SampleSeeder'
INFO Seeding database.
サブフォルダのSeeder だよ~
今度は実行できています。これは面倒…!
少し調べてみたところ、composer.json のautoload の設定を変えることで対応するやり方がいくつか見つかりました。
しかし、更新日付が古く、おそらくLaravel5 か 6 のころの話だと思われます。
また、クラス名の解決の仕方はdb:seed の挙動なので、autoload の設定でどうにかなるものではないような気がしています。
とりあえずname space を全部書くか、artisan CLI からの直接実行はあきらめるか、のどちらかになりそうです。
以上です。あなたのお役に立てればうれしいです。