Livewire では、Eloquent モデルを直接バインドさせることができ、非同期でデータを反映させたり保存するときに大変便利です。
例として、実際に Post モデルのプロパティを編集するためのフォームを作成しながら実装手順といくつかのポイントをご紹介します。
目次
前提
Laravel Livewire 2.x を利用しています。
コンポーネントを新規作成する
まず artisan コマンドを実行して、コンポーネントのひな形を作成します。
$ php artisan make:livewire post.show
COMPONENT CREATED 🤙
CLASS: app/Http/Livewire/Post/Show.php
VIEW: resources/views/livewire/post/show.blade.php
このように表示されたら成功です。
「php artisan make:livewire コンポーネント名」だけでも作成できますが、「post.show」のように「サブディレクトリ名.コンポーネント名」を指定すると自動で各サブディレクトリも作成してくれます。
ファイルを綺麗に配置することができてオススメです。
blade ファイルに Livewire コンポーネントを出力する
ルーティングや Controller は通常通りに実装します。
ここでは下記のように実装しました。
Route::get('/post/{uname}/edit', [PostController::class, 'edit']);
use App\Models\Post;
public function edit(String $uname)
{
$post = Post::where('uname', $uname)->first();
// 略
return view('post.edit', compact('post'));
}
blade ファイルの中で、 Livewire コンポーネントを表示したい場所に @livewire ディレクティブを書きます。
@livewire('post.show', ['post' => $post])
これで show コンポーネントが呼び出されるようになりました。
<livewire:post.show :post=”$post” /> のようにタグで書くこともできます。
くわしい書き方のルールはこちらをご覧ください。
非同期に値を更新する機能をつけたいとき、コンポーネントに渡す値は上記のように Eloquent モデル丸ごとがオススメです。後述する手順で Eloquent モデルと直接バインドできるようになります。
Eloquent モデルにバインドする
artisan コマンドで生成された app/Http/Livewire/Post/Show.php を編集して、 blade ファイル経由で受け渡された Eloquent モデルとバインドさせます。
use App\Models\Post;
class Show extends Component
{
public Post $post;
protected $rules = [
'post.title' => 'required|string|max:100',
'post.summary' => 'string|max:500'
];
}
Post モデルの $post を public プロパティとして定義し、 Post モデルのうちバインドしたいプロパティ( title と summary )のバリデーションを $rules プロパティで定義しました。これでバインド完了です。
view ファイルで各プロパティを出力してみます。
<div>
<input type="text" wire:model="post.title">
<textarea wire:model="post.summary"></textarea>
</div>
各プロパティの値が表示されていれば成功です!
必ず $rules プロパティを設定しなければいけないことに注意してください。
$rules プロパティに代入されたキーのみが正常にバインドされます。
非同期で更新する機能を実装する
Show クラスで更新用の public メソッドを用意します。
public function save()
{
$this->validate();
$this->post->save();
}
validate() メソッドでは $rules プロパティに設定されたルールでの検証が行われ、不適合の場合は処理が中断されます。
view ファイルには、フォームを送信( submit )すると save() メソッドを呼び出せるように記述します。
<form wire:submit.prevent="save">
<input type="text" wire:model="post.title">
<textarea wire:model="post.summary"></textarea>
<button type="submit">Save</button>
</form>
ついでにエラー表示もできるようにしておきましょう。
<form wire:submit.prevent="save">
<input type="text" wire:model="post.title">
@error('post.title')<p class="text-red-500 text-xs">{{ $message }}</p>@enderror
<textarea wire:model="post.summary"></textarea>
@error('post.summary')<p class="text-red-500 text-xs">{{ $message }}</p>@enderror
<button type="submit">Save</button>
</form>
@error(‘post.title’) @enderror 内の $message には post.title に対するエラーが、 @error(‘post.summary’) @enderror 内の $message には post.summary に対するエラーが自動で代入されています。
これで、 Save ボタンを押すと非同期で Post モデルが更新される機能ができました!
フラッシュメッセージを表示する
最後に、データを保存したことをユーザにお知らせするフラッシュメッセージ表示処理を追加します。
public function save()
{
$this->validate();
$this->post->save();
session()->flash('message', '保存しました');
}
<div>
@if (session()->has('message'))
<div class="alert alert-success">
{{ session('message') }}
</div>
@endif
</div>
Show クラスで message セッションに値を代入し、それを view ファイルで表示しています。
CSSで見た目を整えたら完成です!