Help us understand the problem. What is going on with this article?

Laravel 5.7 + GraphQL(Pagination編)

今回はLaravel5.7とGraphQLを使ってページネーションを実装します。

シリーズ記事

Laravel 5.7 ページネーション

$users = DB::table('users')->paginate(15);
$users = App\User::paginate(15);

Laravelではいくつページネーションする方法がありますが、
一番簡単な方法はQueryBuilderやEloquentBuilderから paginate メソッドを使う方法です。

Laravel 5.7 + GraphQL + paginate

GraphQLにて実装します。
前回までのソースコードからの詳細な差分はコミットを参照ください。
https://github.com/ucan-lab/practice-laravel-graphql/commit/cbbe5a812e01bdfde155f12286e24115ec40649e

app/GraphQL/Query/PostsQuery.php

PostsQueryをページネーションに対応します。

    public function type() : PaginationType
    {
        return GraphQL::pagination(GraphQL::type('PostType'));
    }

GraphQLライブラリにPaginationTypeの型が用意されているので設定します。
Folklore\GraphQL\Support\PaginationType

    public function args() : array
    {
        return [
            'id' => [
                'name' => 'id',
                'type' => Type::id(),
            ],
            'ids' => [
                'name' => 'ids',
                'type' => Type::listOf(Type::id()),
            ],
            // take, page のパラメータを追加
            'take' => [
                'type' => Type::int(),
            ],
            'page' => [
                'type' => Type::int(),
            ],
        ];
    }

takepage のパラメータを定義します。
takeは1ページに表示する件数、pageは何ページ目かの指定です。

    public function resolve($root, $args, $context, ResolveInfo $info) : LengthAwarePaginator
    {
        $query = Post::query();

        if (isset($args['id'])) {
            $query->where('id', $args['id']);
        }

        if (isset($args['ids'])) {
            $query->whereIn('id', $args['ids']);
        }

        // ページネーションの処理を追加
        $perPage = $args['take'] ?? 20;
        $page = $args['page'] ?? 1;

        return $query->paginate($perPage, ['*'], 'page', $page);
    }

paginateメソッドに1ページあたりの取得件数とページ番号を渡してあげればokです。
Illuminate\Pagination\LengthAwarePaginator を返してあげます。

動作確認

{
  posts(take: 3, page: 5) {
    items {
      id
      title
    }
    cursor {
      total
      perPage
      currentPage
      hasPages
    }
  }
}

items で PostType に定義したフィールドを指定します。
また、 cursor で ページネーションの情報を取得できます。

{
  "data": {
    "posts": {
      "items": [
        {
          "id": "13",
          "title": "Voluptas eos ducimus sit blanditiis qui."
        },
        {
          "id": "14",
          "title": "In quas ex et officia est natus incidunt."
        },
        {
          "id": "15",
          "title": "Harum quaerat consequatur placeat nam est veritatis et."
        }
      ],
      "cursor": {
        "total": 500,
        "perPage": 3,
        "currentPage": 5,
        "hasPages": true
      }
    }
  }
}

所感

Laravel + GraphQLでページネーションをどうするか?
と情報を探していたところ、PaginationTypeを追加するIssueがmasterにマージされていたことを発見しました。
https://github.com/Folkloreatelier/laravel-graphql/pull/242

思ったよりシンプルに書けて凄かったです😊
ページネーションのテストコードがとても参考になりましたので参考にしたコード一覧も載せておきます!

参考コード

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away