Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
6
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

@ucan-lab

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 not register and get more from Qiita?
  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
6
Help us understand the problem. What are the problem?