📖

LaravelをAPIサーバーで利用するときのページネーションの実装「ページあたりの件数」「現ページindex」を指定してページネーション

2022/07/03に公開

Nuxt/Laravel、SSRでの業務システムの開発に携わっているのですが、LaravelをAPIサーバとして使うときの実装でややハマったのでメモ。

pagenate()メソッドの仕様

クエリビルダ or Eloquentクエリでのpagenate()メソッドですが、今までの案件で見てきたソースの記述だと

User::where('id', '>', '100')->paginate(15); //1ページあたり15件づつ取得する

このような数値型の引数が1つだけ渡され「1ページあたりの数」のみを指定している実装しか見たことがなかったのですがページネーションって、「1ページあたりの数」と「現在のページインデックス」の2つの値が必要じゃない??と疑問に思ったところなんと、pagenate()は自動でGETリクエストのパラメータpageの値を現在のページ番号として参照しているのでした。
フロントに.blade利用しているときはlinks()を利用すれば上記の仕様に合わせてページリンクを出力するというブラックボックス化されています。
但し、対応してるのはGETのみであり、POSTにpageパラメータで数値渡しても機能してくれませんでした。
(取得系のエンドポイントまでも全てPOSTでルーティングされてる変な設計の案件でこの壁にぶつかった。)

「1ページあたりの件数」「現ページインデックス」を指定してページネーションを実装する方法

HTTPメソッドにPOST使いたい時orパラメータ名にpage以外を使いたいときは「1ページあたりの数」と「現在のページ数」を明示的に引数に渡します。

User::paginate(
    $perPage, // 1ページあたりの件数
    ['*'],
    'page', 
    $currentPage // 現在のページインデックス値
);

第2,3引数は上記の定数で良いと思います。

APIが返すJSONデータ

paginate()はLengthAwarePaginator型を返し、データは下記の構造になります。jsonで返され、フロント側でもこのオブジェクトを扱うことになります。

{
    "total":13, // 全ページのアイテム総数
    "per_page":3, // 1ページあたりの件数
    "current_page":1, // 現ページのインデックス
    "last_page":5, // 最終ページのインデックス
    "next_page_url":"http:\/\/localhost:8000\/list?page=2", // 次のページのURLフルパス
    "prev_page_url":null, // 前のページのURLフルパス
    "from":1, // ページ内1要素目のアイテムインデックス(○~○件/全○件中)の表示に使える
    "to":3, // ページ内最後の要素のアイテムのインデックス(○~○件/全○件中)の表示に使える
    "data":[
        // データ。連想配列の配列
    ]
}

参考

https://pgmemo.tokyo/data/archives/1278.html
https://www.slideshare.net/ShoheiOkada/laravel-paginate

Discussion