今日は、Laravelアプリケーションにインタラクティブな要素を簡単に追加する方法、その名もLivewireについてお話ししようと思います。Ajaxを書かずにリアルタイムのインタラクティブなインターフェイスを実現するLivewireは、まさに魔法のようなフレームワークです。さあ、その魔法を見てみましょう!
Livewireとは?
Livewireは、Laravel用のフルスタックフレームワークで、サーバー側のレンダリングパワーとフロントエンドのリアクティビティを組み合わせます。これにより、複雑なJavaScriptを書かずに、動的なUIを簡単に構築できます。
Livewireのコンセプト
Livewireは、Laravelアプリケーションを豊かにするために開発された、画期的なフレームワークです。一言で言えば、Livewireはサーバーサイドのレンダリングの力を活用し、JavaScriptのようなクライアントサイドスクリプト言語に頼ることなく、ダイナミックなユーザーインターフェイスを実現します。
サーバーサイドレンダリングのパワー
従来のウェブアプリケーションでは、動的なインタラクションを実現するために、多量のJavaScriptが必要でした。これには、データのフェッチ、DOMの操作、ユーザーイベントのハンドリングなどが含まれます。しかし、LivewireはLaravelの強力なサーバーサイドレンダリングを活用して、これらのプロセスをサーバー側で処理します。
LivewireコンポーネントはPHPクラスとBladeビューで構成されており、サーバーサイドでの変更がリアルタイムでビューに反映されるようになっています。これは、サーバーからビューへのデータの受け渡しを簡単にし、フロントエンドの複雑さを大幅に削減します。
リアクティビティの秘密
Livewireの魔法は、サーバーとのリアルタイムの通信にあります。ユーザーがインターフェイス上でアクションを起こすたびに、例えばボタンをクリックするたびに、Livewireはそのアクションを検知し、適切なサーバーサイドのPHPメソッドを呼び出します。そして、その結果を元にビューを更新し、ユーザーに即座に反映させます。
このプロセスは、AjaxリクエストやWebSocket通信のような技術を裏で使用していますが、開発者はこれらの複雑なフロントエンドの詳細を一切意識することなく、Laravelの知識だけでリッチなインタラクティブアプリケーションを構築できます。
JavaScriptの省力化
Livewireのもう一つの大きな利点は、動的なUIコンポーネントを作成する際に、JavaScriptのコードを書く必要がほとんど、あるいは全くないことです。バリデーション、リアルタイム検索、フォームの入力といった一般的な機能は、LivewireのシンプルなAPIを介して直接PHPで処理できます。これにより、フロントエンドとバックエンドのコードベースが一元化され、開発の生産性が大幅に向上します。
結論
Livewireは、フロントエンドとバックエンドの境界を曖昧にし、Laravel開発者がサーバーサイドのコードだけでフルスタックの機能を実現できるようにする、革新的なフレームワークです。複雑なJavaScriptの代わりに、Laravelのエレガントな文法でリアクティブなUIを構築できるため、開発者はユーザーエクスペリエンスに集中することができます。
Livewireの基本設定
Livewireのインストール
まずは、以下のコマンドでLivewireをインストールしましょう。
composer require livewire/livewire
このコマンドは、Livewireの依存関係をプロジェクトに追加し、必要なファイルを設定します。
コンポーネントの作成
Livewireの魔法は「コンポーネント」によって行われます。次のコマンドで新しいコンポーネントを作成します。
php artisan make:livewire Counter
これにより、Counter というPHPクラスと関連するBladeビューが下記の場所に生成されます。
- コンポーネント:app/Http/Livewire/Counter.php
- ビューファイル:resources/views/livewire/counter.blade.php
コンポーネントの設定
上記で生成されたコンポーネントを開き、必要なプロパティやメソッドを定義します。以下は、カウンターをインクリメントとデクリメントするメソッドを持つコンポーネントの例です。
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class Counter extends Component
{
public $count = 0;
public function increment()
{
$this->count++;
}
public function decrement()
{
$this->count--;
}
public function render()
{
return view('livewire.counter');
}
}
コンポーネントビューの設定
ビューファイル counter.blade.php は、コンポーネントのHTMLマークアップを定義します。Livewireのディレクティブを使用して、コンポーネントクラスのメソッドやプロパティと対話します。
<div>
<button wire:click="decrement">-</button>
<span>{{ $count }}</span>
<button wire:click="increment">+</button>
</div>
wire:click ディレクティブは、ボタンがクリックされたときに対応するコンポーネントクラスのメソッドを呼び出します。この場合、-
ボタンは decrement メソッドを、+
ボタンは increment メソッドを呼び出します。
コンポーネントの使用
コンポーネントをページに組み込むには、そのビューファイル内で以下のように記述します。
@livewire('counter')
また、Livewireのスクリプトとスタイルを適切に読み込むために、アプリケーションのレイアウトファイル(通常は resources/views/layouts/app.blade.php)の適切な場所に以下を追加します。
<head>
...
@livewireStyles
</head>
<body>
...
@livewireScripts
</body>
@LivewireStyles はLivewireによって生成されるスタイルを、@LivewireScripts はJavaScriptの依存関係を読み込むために使用します。
実践例1
Sampleレイアウトテンプレートの作成
layouts/app.blade.phpのテンプレートは、JetStreamで使用しているので、別途レイアウトテンプレートとして、Sampleレイアウトテンプレートを作成します。
php artisan make:component SampleLayout
このコマンドは、App\View\Components 名前空間の下に SampleLayout コンポーネントを作成します。これにより、以下の2つのファイルが生成されます:
- コンポーネントクラス:app/View/Components/SampleLayout.php
- ビューファイル:resources/views/components/sample-layout.blade.php
コンポーネントクラスの編集
コンポーネントクラス( SampleLayout.php )を編集して、必要なロジックを追加します。基本的な構造は次のようになります。今回は、レイアウトテンプレートを表示(render)するだけなので、自動生成されたファイルのままでOKです。
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class SampleLayout extends Component
{
/**
* Create a new component instance.
*/
public function __construct()
{
//
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.sample-layout');
}
}
レイアウトビューファイルの修正
対応するレイアウトビューファイル( sample-layout.blade.php )にHTMLコンテンツを追加します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>サンプル</title>
@vite(['resources/css/app.css', 'resources/js/app.js'])
@livewireStyles
</head>
<body class="font-sans antialiased">
<main>
{{ $slot }}
</main>
</div>
@livewireScripts
</body>
</html>
ビューファイルの作成
それでは、実際に表示するためのビューファイルをtop.blade.php名で作成します。
<x-sample-layout>
<h1 class="text-4xl font-bold text-center my-4">Hello World</h1>
@livewire('counter')
</x-sample-layout>
counter.blade.phpの修正
カウンターの見た目を若干修正します。
<div class="text-center">
<button wire:click="decrement" class="px-4 py-2 bg-red-500 text-white font-bold rounded hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-300">
-
</button>
<span class="mx-4 text-lg font-semibold">{{ $count }}</span>
<button wire:click="increment" class="px-4 py-2 bg-green-500 text-white font-bold rounded hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-300">
+
</button>
</div>
ボタンをクリックして、中央の数字が増減すればOKです。
実践例2
ヘッダーメニューの作成
Livewireを使って、このサイトのようなヘッダーメニューを作成してみたいと思います。
Livewireコンポーネントの作成
Artisan CLIを使用してLivewireコンポーネントを作成します。
php artisan make:livewire HeaderMenu
コンポーネントビューの設定
コンポーネントには対応するBladeビューファイルがあり、header-menu.blade.php名で生成されます。ここにナビゲーションバーのHTMLを追加します。
Tailwind CSSを使用した基本的な例を以下に示します。
<div x-data="{ isOpen: false }">
<div class="bg-gray-800">
<nav class="flex items-center justify-between flex-wrap py-1 px-4">
<div class="flex items-center flex-shrink-0 text-white mr-6">
<span class="font-semibold text-xl tracking-tight">WinRoad徒然草</span>
</div>
<div class="block lg:hidden">
<button @click="isOpen = !isOpen" class="flex items-center px-3 py-2 border rounded text-teal-200 border-teal-400 hover:text-white hover:border-white">
<svg class="fill-current h-3 w-3" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><title>Menu</title><path d="M0 3h20v2H0zM0 9h20v2H0zM0 15h20v2H0z"/></svg>
</button>
</div>
<div :class="{'block': isOpen, 'hidden': !isOpen}" class="w-full lg:flex lg:items-center lg:w-auto lg:justify-end">
<div class="text-sm lg:flex-grow">
<a href="#" class="block mt-4 lg:inline-block lg:mt-0 text-teal-200 hover:text-white mr-4">
Flutter<br>
<span class="text-ms lg:text-xs text-teal-200 hover:text-white">フラッター</span>
</a>
<a href="#" class="block mt-4 lg:inline-block lg:mt-0 text-teal-200 hover:text-white mr-4">
WordPress<br>
<span class="text-xs lg:text-xs text-teal-200 hover:text-white">ワードプレス</span>
</a>
<a href="#" class="block mt-4 lg:inline-block lg:mt-0 text-teal-200 hover:text-white mr-4">
Laravel<br>
<span class="text-sm lg:text-xs text-teal-200 hover:text-white">ララベル</span>
</a>
<a href="#" class="block mt-4 lg:inline-block lg:mt-0 text-teal-200 hover:text-white mr-4">
Ubuntu<br>
<span class="text-sm lg:text-xs text-teal-200 hover:text-white">ウブンツ</span>
</a>
<a href="#" class="block mt-4 lg:inline-block lg:mt-0 text-teal-200 hover:text-white mr-4">
Swell<br>
<span class="text-sm lg:text-xs text-teal-200 hover:text-white">スウェル</span>
</a>
</div>
</div>
</nav>
</div>
</div>
レスポンシブ機能の追加
JavaScriptを使用して、小さいスクリーン上でメニューアイテムの表示を切り替えることができます。Livewireはクリックイベントをリスンし、メニューアイテムの表示を制御するプロパティを切り替えることができます。
public $isOpen = false;
public function toggleNavbar()
{
$this->isOpen = !$this->isOpen;
}
そしてBladeビューで、ボタンを以下のように更新します。
<button @click="isOpen = !isOpen" ...>
$isOpenプロパティに基づいてメニューアイテムを条件付きでレンダリングします。
<div :class="{ 'block': isOpen, 'hidden': !isOpen }" class="hidden lg:block ...">
<!-- ナビゲーションリンク -->
</div>
レイアウトコンポーネントに追加
メインのレイアウトファイルにLivewireコンポーネントを含めます。
@livewire('header-menu')
下記の様に表示されました。
下記はPCサイズの表示です。
下記はスマホサイズの表示です。
コメント