Laravelで「もっと見る」をLivewireで実装:都度読み込みを実現

by

in

ページングの実現方法の1つである「もっと見る」の機能は ajaxなどを使用して実現するのが一般的ですが、これをLaravelの新機能である Livewireを使用すると簡単に実現することができます。

この記事では「もっと見る」の機能をLaravelで実装するためにLivewireを使う方法や、Livewireを使ってみたい人が実践形式のサンプルを確認できる記事になります。

ページング実装で「もっと見る」にする実装コストの問題

Laravelアプリケーションに限らずページングの表示方法の一つとして「もっと見る」のボタンを押下すれば一覧の続きが読み込まれる機能が存在します。

この「もっと見る」は2パターン存在し、一度に大量に読み込んで非表示にした内容を表示させたり、都度読むように実装する2つ存在します。

一度に大量に読み込むパターンは簡単ですが際限なく読ませることは出来ないため、この記事では後者のパターンについて取り扱います。

都度読み込む場合ではJavaScriptを使用した実装が必要になり、LaravelアプリケーションだとBladeテンプレートに記述したHTML以外にもJavaScriptで読み込み可能なHTMLを別途用意する必要があります。

つまり同じ内容のHTMLが2箇所存在する事になり、保守性が低くなります。

解決策としてはJavaScriptで表示するHTMLに寄せてしまう事で解決するのですが、この1機能のためにロジックを用意するのも大変コストがかかってしまいます。

普通のページリンクであれば10分とかからないでしょう。

例えるならば、ハガキを送りたいのだけれど近くのポストには徒歩1分で出せるが、消印を富士山からのものにしたいので1日かけて富士山の郵便局に出しに行くような。

「可能だけどそれやります?」案件なのがこの「もっと見る」機能といっても良いかもしれません。

ですがLaravelには便利な物が用意されており、30分あれば実装出来てしまうのがこれから紹介する Livewire です。

Livewireで実装した場合のソースコード

完成イメージはこちらです。

$ composer require livewire/livewire
$ php artisan make:livewire ProgramListing
app/Http/Livewire/ProgramListing.php
resources/views/livewire/program-listing.blade.php
...
    @livewireStyles
</head>
<body>
    ...
 
    @livewireScripts
</body>
</html>
...
        <div class="page-wrapper">
            @include("_side_bar")

            @livewire('program-listing', ['params' => $params])
        </div>
...
<main>
    <ul class="program-card-list">
        @if (count($programs))
        @foreach ($programs as $program)
            @include('_program', ['program' => $program])
        @endforeach
        @else
        <p>見つかりませんでした</p>
        @endif
    </ul>

    @if ($hasMorePages)
    <div class="text-center">
        <button class="btn" wire:click="fetchPage">
            もっと見る
        </button>
    </div>
    @endif
</main>
<?php

namespace App\Http\Livewire;

use App\Models\Program;
use Illuminate\Support\Collection;
use Livewire\Component;

class ProgramListing extends Component
{
    public Collection $programs;
    public array $params;

    public int $pageNumber = 0;
    public bool $hasMorePages = false;

    public function mount(array $params)
    {
        $this->params = $params;

        $this->programs = new Collection();

        $this->fetchPage();
    }

    public function fetchPage()
    {
        $this->pageNumber += 1;

        $programs = Program::query();
        if (count($this->params)) {
            // 取得条件の色々を設定
        }
        $paginate = $programs->paginate(12, ['*'], 'page', $this->pageNumber);

        $this->hasMorePages = $paginate->hasMorePages();

        $this->programs->push(...$paginate->items());
    }

    public function render()
    {
        return view('livewire.program-listing');
    }
}

以上で完了です。

DevToolsを開いて「もっと見る」を押下して通信が走るので都度データを取得しているのがわかります。

解説

Livewireを使用することでJavaScriptを記述する必要なく動的コンテンツの作成が可能になります。

Bladeテンプレートの中に @livewire('program-listing', ['params' => $params]) を記述することで読み込んだりパラメータを渡す事ができます。

呼び出されるとまずは app/Http/Livewire/ProgramListing.php クラスが読み込まれて mount()関数が呼び出されて render()関数で記述されたテンプレートが表示されます。

呼び出されたテンプレート内の wire:click="fetchPage" によって記述されたfetchPage()関数が都度実行されてクラス内変数が更新されるとテンプレートでの表示も更新されます。

注意する点としてはLivewireで作成されたクラス内変数は全てクライアントサイドに公開されてしまうので、パスワードやメールアドレスなどの値は渡さないように気をつけましょう。

終わりに

以上、Livewireを使用した「もっと見る」機能の実装でした。

JavaScriptを記述することなく、気軽に動的表示させる機能を実装することができます。APIも自動で作ってくれるので素早い開発が可能になります。

ただ、「もっと読む」機能はGoogleBotによるクローリングに対してはあまり良い機能とは言えないと感じています。

参考: https://developers.google.com/search/docs/specialty/ecommerce/pagination-and-incremental-page-loading?hl=ja

buttonタグで実装するとクロールすらしてくれません。Googleによるインデックスを重視したい場合にはページ分けによる実装にしましょう。

ですが、使用してきた Livewire はとても簡単に実装できるので使いこなしていきたいところです。

Livewireを使用した実装については TALL stack を使ったプロジェクトが参考にできると思います。例えばLaravelの管理画面を作れる Filament なんかはTALL stackなので実装方法を眺めるだけでLivewireを使いこなすヒントになると思います。

以上、お疲れ様でした。

参考リンク

今回の記事を書くにあたって参考にしたリンク

https://laravel-livewire.com/docs/2.x/quickstart

https://postsrc.com/posts/how-to-implement-laravel-livewire-load-more-pagination#google_vignette

レンタルサーバーを最大限使いこなすための方法

Laravelの記事を厳選して紹介

投稿者


Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA