今回はLaravel5.7とGraphQLを使ってページネーションを実装します。
シリーズ記事
- LaravelとGraphQLでAPI開発
- Laravel 5.7 + GraphQL(Install編)
- Laravel 5.7 + GraphQL(ScalarType編)
- Laravel 5.7 + GraphQL(Relation編)
- Laravel 5.7 + GraphQL(Dump Server編)
- Laravel 5.7 + GraphQL(Pagination編)
- Laravel 5.7 + GraphQL(ErrorHandling編)
- Laravel 5.7 + GraphQL(Test編)
Laravel 5.7 ページネーション
$users = DB::table('users')->paginate(15);
$users = App\User::paginate(15);
Laravelではいくつページネーションする方法がありますが、
一番簡単な方法はQueryBuilderやEloquentBuilderから paginate
メソッドを使う方法です。
- https://readouble.com/laravel/5.7/ja/pagination.html
- Illuminate\Database\Query\Builder
- Illuminate\Database\Eloquent\Builder
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(),
],
];
}
take
と page
のパラメータを定義します。
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
思ったよりシンプルに書けて凄かったです😊
ページネーションのテストコードがとても参考になりましたので参考にしたコード一覧も載せておきます!
参考コード
- https://github.com/Folkloreatelier/laravel-graphql/blob/master/src/Folklore/GraphQL/Support/PaginationType.php
- https://github.com/Folkloreatelier/laravel-graphql/blob/master/src/Folklore/GraphQL/Support/PaginationCursorType.php
- https://github.com/Folkloreatelier/laravel-graphql/blob/develop/tests/Objects/ExamplesPaginationQuery.php