Laravel Livewire入門!PHPでreact/vueライクなアプリケーション開発

シェアしてね〜🤞

記事の対象者

この記事は、Laravelは経験があるがLivewireは初めて使う方を対象にしています。Livewireの使い方を素早く理解できるよう内容を絞り込んでいますが、理解の幅を広げたい方のために公式ドキュメントへのリンクも積極的に取り入れています。

通常のLaravelの機能については詳しく解説していませんのでご了承ください。

Livewireとは

LivewireはLaravel向けのフレームワークです。ページやコンポーネントに状態を持たせることができ、フルページリロードの必要がないSPA的なページをLaravelの簡潔さを損なわずに実装することができます。

Livewireのバージョンについて

Livewire3は最近(2023年8月)公式リリースされたので、検索してもLivewire2の記事が多く出てきます。後方互換性がかなりあるようなので、2のスタイルで書いてもたいていは動きますが、この記事では3の公式ドキュメントのスタイルを優先します。

超簡易アプリの作成を通してLivewireを理解しよう

超簡易記事投稿アプリの作成を通して、Livewireの書き方を高速で体験してください。

インストール

通常のLaravelプロジェクトをお好きな方法で構築してください。

参考記事:Laravel9+Sail(Docker)で環境構築してみた

プロジェクトが作成されたら、Livewireをインストールします。

composer require livewire/livewire

これだけでLivewireの機能が使えるようになります。

テーブル・モデルを作成する

テーブルやモデルについてはLaravelの基本機能をそのまま使います。このチュートリアルで使用するテーブル・モデルを作成しましょう。

php artisan make:model Post -m

database/migrations/xxxx_xx_xx_xxxxxx_create_posts_table.php(xxxxは作成日時)

Schema::create('posts', function (Blueprint $table) {

    $table->id();

    $table->string('title');

    $table->timestamps();

});

まずはページを作る

Livewireの基本要素はLivewireコンポーネントです。Laravelのコンポーネントと似ていますが、状態をリクエスト間で維持できるのがウリです。このコマンドで作成できます。

php artisan make:livewire CreatePost

以下のファイルが自動生成されました。クラスとBladeビューが作成されます。Laravelのテンプレートと似ていますね。

  • app/Livewire/CreatePost.php
  • resources/views/livewire/create-post.blade.php

Bladeテンプレート内に配置することもできますが、ルートに指定してページとして扱うこともできます(フルページコンポーネント

routes/web.php

use App\Livewire\CreatePost;

Route::get('/', CreatePost::class);

レイアウトを用意する

しかし、この時点でアクセスしてもエラーが出ます。Livewireコンポーネントを包むレイアウトが存在しないからです。resources/views/components/layouts/app.blade.phpがデフォルトのレイアウトに指定されているので、作成しましょう(レイアウトのパスを変更したい場合はこちら

php artisan make:component layouts.app --view

resources/views/components/layouts/app.blade.php

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>高速!Livewire3入門</title>
    </head>
    <body>
        {{ $slot }}
    </body>
</html>

エラーが出ずに真っ白なページが表示されれば動作確認OKです。

Livewireコンポーネントの中身を書く

クラス側

Livewireコンポーネントのクラスのpublicなプロパティやメソッドは特別な意味を持っています。

publicプロパティは値の内容はリクエスト間で維持され、フロント側のフォームの内容と同期を取ることができます。ReactやVueをご存じの方はステートをご存じでしょう。同じことがPHPコードでできます(Livewireプロパティ

publicメソッドはBladeビューから呼び出すことができます(Livewireアクション

app/Livewire/CreatePost.php

<?php

namespace App\Livewire;

use App\Models\Post;
use Livewire\Component;

class CreatePost extends Component
{
    public $title = '';  // ←Livewireプロパティ

    public function render()
    {
        return view('livewire.create-post');
    }

    public function create()  // ←Livewireアクション
    {
        $post = new Post;

        $post->title = $this->title;

        $post->save();
    }
}

Bladeビュー側

続いて、Bladeビュー側でwire:から始まるディレクティブ使って挙動を定義します。

wire:modelにはLivewireプロパティ名を指定し、フォーム要素の内容とPHP変数の内容を同期します。

wire:submitにはLivewireアクション名を指定し、submitイベントを合図にサーバー側のメソッドを呼び出すことができます。他にもwire:clickなどあらゆるブラウザイベントに対応しています。

wire:keyはループでレンダーする要素に忘れずにつけましょう。そうしないとLivewireが要素を特定できなくなり、不具合の原因になります。

resources/views/livewire/create-post.blade.php

<div>
    <form wire:submit="create">
        <input wire:model="title" />
        <button>投稿</button>
    </form>
    <div>
        @foreach(App\Models\Post::all() as $post)
            <p wire:key="{{ $post->id }}">{{ $post->title }}</p>    
        @endforeach
    </div>
</div>

バリデーションを実装する

Livewireプロパティはプロパティごとにバリデーションを記述することができます。DBにデータを保存する前にバリデーションチェックをしましょう。

クラス側

バリデーションルールは#[Rule]を使ってプロパティに直接指定することができます。通常のLaravelと同じバリデーションルールを使います。

app/Livewire/CreatePost.php

<?php

namespace App\Livewire;

use App\Models\Post;
use Livewire\Attributes\Rule;  // ←追加
use Livewire\Component;

class CreatePost extends Component
{
    #[Rule('required|string|max:10')]  // ←追加

    public $title = '';

    public function render()
    {
        return view('livewire.create-post');
    }

    public function create()
    {
        $this->validate();  // ←追加

        $post = new Post;

        $post->title = $this->title;

        $post->save();
    }
}

Bladeビュー側

Bladeビュー側にエラーを表示しましょう。表示方法は通常のLaravelと全く同じです。

resources/views/livewire/create-post.blade.php

<div>
    <form wire:submit="create">
        <input wire:model="title" />
        <button>投稿</button>

        {{-- ↓追加 --}}
        @error('title')
            <span>{{ $message }}</span>
        @enderror  

    </form>
    <div>
        @foreach(App\Models\Post::all() as $post)
            <p>{{ $post->title }}</p>    
        @endforeach
    </div>
</div>

完成

極めて簡素ですが、記事投稿アプリの完成です。Laravel単体で実装すと

  • ルート定義
  • コントローラー
  • バリデーション

の記述などで煩雑になりそうですが、Livewireで簡潔に書くことができました。

さらに学びを深めよう

Livewireはシンプルに見えますが、多機能で奥が深いです。以下は筆者が実務で便利だと感じた機能へのお役立ちリンク集です。

  • Url Query Parameters - この機能は感動です。検索条件が多いページなどを簡潔に実装できます。
  • Locked Properties - Livewireはサーバー側の変数がフロントに疑似的に晒されるため、セキュリティ上の懸念があります。筆者はフロントでの変更を意図しないLivewireプロパティには全て#[Locked]を付けています。
  • wire:loading - 二重送信対策に便利なのがこのディレクティブ。
  • Alpine.jsからアクセス - JSでしかできないようなことをPHPでできてしまうLivewireですが、Alpine.jsを使った方が便利なときがあります。
シェアしてね〜🤞