🐕

Laravel Filamentで子テーブルに保存する

2024/09/16に公開

Laravel Filamentで管理画面を実装した際に、子テーブルに同時に保存する方法があるか調べてみました。

前提

今回は犬とその犬の画像を登録するフォームを作成します。
Filamentの導入は既に行っている前提で行います。

dogsテーブル

論理名 物理名
ID id
犬の名前 name
作成日時 created_at
更新日時 updated_at

dog_imagesテーブル

論理名 物理名
ID id
犬ID dog_id
並び順 sort
画像ファイルパス image
作成日時 created_at
更新日時 updated_at

やりたいこと

  • dogsテーブルにレコードを新規作成・編集した際にdog_imagesテーブルにも登録されるようにする。

実装手順

実装方法は非常に簡単で、relationship()を呼ぶだけでFilament側がdog_imagesテーブルに保存までしてくれます。

Resourceクラスにリレーション先のテーブル用の項目を追加する

  • 予めModelクラスにリレーションメソッドを定義してください。
app/Models/Dog.php
public function dogImages(): HasMany
{
    return $this->hasMany(DogImage::class);
}
  • DogResourceクラスのform()でレコード登録時の項目を追加します。
  • 複数登録できるようRepeaterを使い、その中のschemaに画像アップロード用のFileUploadを使って項目を追加します。
  • その後relationship()でリレーション先を指定します。
app\Filament\Resources\DogResource.php
class DogResource extends Resource
{
    protected static ?string $model = Dog::class;

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                TextInput::make('name')
                    ->label('犬の名前'),
                // 追加
                Repeater::make('images')
                    ->relationship('dogImages') // Dog.phpに定義したリレーションメソッドを指定
                    ->schema([
                        FileUpload::make('image')
                            ->label('画像')
                            ->directory('dogs'),
                    ])
                    ->reorderable()
                    ->orderColumn('sort'),
            ]);
    }
}

これだけでフォームに入力欄が表示され、設定した内容がdog_imagesテーブルに保存されます。

並び順も保存したい場合

  • 画像を複数登録した際の並び順も子テーブルに保存したい場合、Repeaterにreorderable()orderColumn()を指定してください。
  • orderColumnの引数に指定したカラムに自動的に並び順の番号を保存してくれます。

参考

Repeater - Form Builder - Filament

Discussion