🔥

Laravel カーソルページングを試してみる

2021/12/15に公開

本題

Laravel Ver.8.41(2021年5月)より、カーソルページング機能が追加されています。

これは何かという話は、詳しくは、ドキュメントやプルリクを参照いただきたいのですが、
https://readouble.com/laravel/8.x/ja/pagination.html#cursor-pagination
https://github.com/laravel/framework/pull/37216

利点としては、OFFSETなどの場合と比較して、データが追加・削除等されても、抜けが発生しなかったり、また、INDEXを張ったキーでソートすれば、パフォーマンスが向上するという事です。(一説では、OFFSET 100000 だと、最大400倍速いとか)

但し、いつもの paginate() の時のように、1 2 3 4 5 ... の数字番号は付きません。また、URLは以下の感じになるので、現在何ページ目なのかは見ても分かりません。
/?cursor=eyJpZCI6MjkxLCJfcG9pbnRzVG9OZXh0SXRlbXMiOnRydWV9

ただ、そういうのが不要な場合、特に無限スクロールなどで、利用価値がありそうです。

という事で、以下の感じで試してみました。

Route::get('/', function () {
    $users = User::query()
        ->orderByDesc('id')
        ->cursorPaginate(10);

    return view('welcome', compact('users'));
});

すると、次を押した後のURLは、以下のようになりました。
/?cursor=eyJpZCI6MjkxLCJfcG9pbnRzVG9OZXh0SXRlbXMiOnRydWV9

で、この時発行された SQL は、以下の感じです。

select * from `users` where (`id` < 291) order by `id` desc limit 11

いや、なんか凄いですね。

ちなみに、Lavel Livewire でも

数日前にリリースされた Lavel Livewire v2.8.2 でも、カーソルページングの対応がされました。
[Feature] Add cursor pagination to Livewire #3215
Laravel と Livewire が共に対応していれば、同じ感じで行けます。

    public function render()
    {
        $users = User::query()
            ->orderByDesc('id')
            ->cursorPaginate(10); // ← ここ

        return view('livewire.show-users', [
            'users' => $users,
        ]);
    }

ただ、デフォルトの Tailwind CSS テーマでは問題ありませんが、Bootstrap テーマを使用すると、ちょっとまだバグってエラーとなる状態です。 次のバージョンで直ります。 Fix cursor pagination in bootstrap #4406

雑感

今後、場面に応じて使って行こうと思います。

おかしな箇所等ありましたらコメント下さい。

Discussion