Livewireの普通の使い方とVoltの比較 ==== ## バージョン - Laravel 10.x - Livewire 3.2.6 https://github.com/livewire/livewire - Volt 1.6.0 https://github.com/livewire/volt 最近でも機能が追加されてるので2023年12月時点の情報。 ## ドキュメント https://livewire.laravel.com/docs/volt ## 3つのスタイル 一つのLaravelプロジェクト内で3つのスタイルを同時に使える。簡単なページはVolt functional、複雑なページは普通などで使い分けしてもいい。最初はVolt functionalで作ったけど複雑になってきたので普通の使い方に作り変えるなんてこともよく発生する。 ### Livewire スタンダード PHPファイルとBladeファイルが分かれた普通の使い方。 実装例:JetstreamのLivewireスタック。 Voltの前に普通の使い方の理解は必須。 この記事は普通の使い方でのこの機能はVoltでどう書くのかって情報のまとめ。 ### Volt functional BladeファイルだけでLivewireを使う新しい方法。Vue.js風の表現ならシングルファイルLivewireコンポーネント。 実装例:Breezeのlivewire-functionalスタック。 https://github.com/laravel/breeze/tree/1.x/stubs/livewire-functional/resources/views/livewire ```php 0]); $increment = fn () => $this->count++; ?>

{{ $count }}

``` Laravel Folioと似てるし一緒に発表されたけどFolioとは関係ない。 ### Volt Class-based Voltを普通の使い方に近い無名classを使うスタイルにしたもの。 実装例:Breezeのlivewireスタック。 https://github.com/laravel/breeze/tree/1.x/stubs/livewire/resources/views/livewire ```php count++; } } ?>

{{ $count }}

``` 複雑化しただけでこれの追加は余計だった気がする。Laravelは複数の使い方ができるのが混乱の元なのに余計な選択肢を増やすのは明らかに悪い。 ## コンポーネント作成コマンド ### Livewire スタンダード ``` php artisan make:livewire counter ``` ### Volt functional ``` php artisan make:volt counter ``` ファイル一つなので2回目からはコマンドを使うより既存のコンポーネントを複製して書き換えが現実的な使い方。 ### Volt Class-based functionalと同じ。 ## ファイルの場所 ### Livewire スタンダード - `app/Livewire/`にPHPファイル - `resources/views/livewire`にBladeファイル ### Volt functional `resources/views/livewire`にBladeファイルのみ。 `resources/views/pages`に置いたBladeファイルも使える。Folio用に作ったページだけど機能を追加したくなってVoltに変更、みたいな使い方を想定しているのだろう。FolioのファイルベースルーティングとVoltを同時に使えるかは試してないので不明。 ### Volt Class-based functionalと同じ。 ## プロパティとmount ### Livewire スタンダード ```php posts = Post::all(); } } ``` ### Volt functional ```php posts = Post::all(); }); ?>
``` ### Volt Class-based ```php posts = Post::all(); } } ?>
``` ## アクション ### Livewire スタンダード ```php namespace App\Livewire; use Livewire\Component; use App\Models\Post; class CreatePost extends Component { public $title = ''; public $content = ''; public function save() { Post::create([ 'title' => $this->title, 'content' => $this->content, ]); return redirect()->to('/posts'); } } ``` ```php
``` ### Volt functional ```php $this->title, 'content' => $this->content, ]); return redirect()->to('/posts'); }; ?>
``` ### Volt Class-based スタンダードとほぼ同じなので以降は省略。 ## バリデーション ### Livewire スタンダード `Validate`アトリビュートで指定。 ```php use Livewire\Attributes\Validate; use Livewire\Component; use App\Models\Post; class CreatePost extends Component { #[Validate('required|min:3')] public $title = ''; #[Validate('required|min:3')] public $content = ''; } ``` ### Volt functional `rules()`で指定。 ```php 'required|min:6', 'email' => 'required|email']); $submit = function () { $this->validate(); // ... }; ?>
//
``` ## Computed プロパティ ### Livewire スタンダード ```php use Livewire\Attributes\Computed; use Livewire\Component; use App\Models\User; class ShowUser extends Component { #[Computed] public function count() { return User::count(); } ``` ### Volt functional ```php
{{ $this->count }}
``` ## ページネーション ### Livewire スタンダード `WithPagination`の追加を忘れやすい。 ```php Post::paginate(10), ]); } } ``` ### Volt functional ```php ['posts' => Post::paginate(10)]); ?>
@foreach ($posts as $post) // @endforeach {{ $posts->links() }}
``` ## ファイルアップロード ### Livewire スタンダード ```php photo->store('photos'); } } ``` ### Volt functional ```php use function Livewire\Volt\{state, usesFileUploads}; usesFileUploads(); state(['photo']); $save = function () { $this->validate([ 'photo' => 'image|max:1024', ]); $this->photo->store('photos'); }; ``` ## Full-page component レイアウト指定 ### Livewire スタンダード render()かclassにLayoutアトリビュートで指定。レイアウトは基本的に固定なのでアトリビュートでの指定でいいだろう。 ```php {{ $title ?? config('app.name') }} ``` ### Livewire スタンダード ```php title($this->post->title); } } ``` ちなみにLivewire3のドキュメントからは消えてるけどtitle以外のデータをレイアウトに渡す`layoutData()`もある。 ```php public function render() { return view('livewire.post-show') ->layoutData(['foo' => 'bar']); } ``` `Title`アトリビュートで指定する方法もあるけど固定のtitleでしか使えないので使うことはほとんどない。 ```php use Livewire\Attributes\Title; use Livewire\Component; class CreatePost extends Component { // ... #[Title('Create Post')] public function render() { return view('livewire.create-post'); } } ``` ### Volt functional ```php use function Livewire\Volt\{state, title}; state('post'); title(fn() => $this->post->title); ``` 固定のtitleなら`titie('Post');`も可能だけどこれもほとんど使わないだろう。 ### Volt Class-based ここだけ特殊で`rendering()`で指定。 ```php title('Create Post'); // ... } // ... ``` ## Full-page component ルーティング ### Livewire スタンダード PHPファイルを指定。 ```php use App\Livewire\CreatePost; Route::get('/posts/create', CreatePost::class)->name('post.create'); ``` ### Volt functional Bladeファイルを指定。`Volt::route()`の戻り値はRouteなので通常通りnameの指定なども可能。 ```php use Livewire\Volt\Volt; Volt::route('/users', 'user-index')->name('user.index'); ``` ## URLクエリパラメータ ### Livewire スタンダード ```php url(); ``` ## イベントリスナー ### Livewire スタンダード ```php use Livewire\Component; use Livewire\Attributes\On; class Dashboard extends Component { #[On('post-created')] public function updatePostList($title) { // ... } } ``` ### Volt functional ```php use function Livewire\Volt\{on}; on(['post-created' => function () { // }]); ``` ## 以上 よく使うだろう機能はまとめたのでこれ以上はドキュメントを参照。 アドベントカレンダー用の記事。 https://qiita.com/advent-calendar/2023/laravel ここは長文を想定してないけど最近は外部に書いてないのでここに書く。 ドメインを破棄した時用にGitHubにも残している。 https://github.com/puklipo/articles/blob/main/livewire-volt.md