Laravel Livewire で親子関係のデータを非同期更新する方法

前回、 Livewire で Eloquent モデルを直接バインドする方法をご紹介しました。

Laravel Livewire を使って非同期な編集フォームを簡単に作る方法

今回はこれの応用で、 バインドした Eloquent モデルの親子関係にあたるモデルのプロパティをいい感じに非同期更新させる方法をご紹介します。

前提

Laravel Livewire 2.x を利用しています。

子モデルを一覧表示する

下図のような1対多の親子関係を持つ Post モデルと Comment モデルを例にご紹介していきます。

app/Models/Post.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{

    // 子モデルを関連づけ
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

Livewire の Component クラスでは親にあたる Post モデルをバインドします。

app/Http/Livewire/piyo.php
<?php

namespace App\Http\Livewire;

use App\Models\Post;

class Piyo extends Component
{    
    public Post $post; // 親モデルをバインド
}

Model クラスでの関連付けが済んでいる子モデルは、普段 blade ファイルに記述するのと全く同じ方法で各パラメータ値の出力が可能です。

resources/views/livewire/piyo.blade.php
@foreach ($post->comments as $comment)
{{ $comment->message }}
@endforeach

更新処理を書く

Component クラスの更新用メソッドで、 Livewire と Laravel のルールに則って更新処理を書きます。

app/Http/Livewire/piyo.php
use App\Models\Post;
use App\Models\Comment;

class Piyo extends Component
{

    public Post $post;
    public $message; // ユーザ入力とバインドさせたパラメータ
    protected $rules = ['message' => 'required'];

    public function save()
    {
        $validated = $this->validate();

        $comment = new Comment(['message' => $validated['message']]);
        $this->post->comments->save($comment);
    }
}

Eloquent モデルを再描画する

更新したばかりのデータは、そのままだとブラウザをリロードするまで反映されません。

これを非同期で即反映させるためには、 refresh() メソッドで $post プロパティの再描画を行う必要があります。

app/Http/Livewire/piyo.php
function save()
{
    $validated = $this->validate();

    $comment = new Comment(['message' => $validated['message']]);
    $this->post->comments->save($comment);

    $this->post = $this->post->refresh(); // 再描画
}

これで子モデルの更新と表示ができるようになりました!