Skip to content

Commit 7667adc

Browse files
nigeldgreenMikk Mihkel Nurges
authored andcommitted
Updated PaginationType to allow custom fields to be injected (#118)
* Updated PaginationType to allow custom fields to be injected * Updated name of project in composer.json
1 parent 4854402 commit 7667adc

File tree

3 files changed

+106
-8
lines changed

3 files changed

+106
-8
lines changed

docs/advanced.md

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,12 +454,94 @@ Query `posts(limit:10,page:1){data{id},total,per_page}` might return
454454
...
455455
],
456456
"total": 21,
457-
"per_page": 10"
457+
"per_page": 10
458458
]
459459
}
460460
}
461461
```
462462

463+
Note that you need to add in the extra 'data' object when you request paginated resources as the returned data gives you
464+
the paginated resources in a data object at the same level as the returned pagination metadata.
465+
466+
#### Customising the pagination results
467+
You can add in additional metadata results alongside the Laravel 'standard' ones. To keep the Posts theme going, we could
468+
create some additional metadata to show the total number of posts, comments and likes for the posts returned in the paginated
469+
results.
470+
471+
First, create a class that returns the custom fields you want to see:
472+
473+
```
474+
use Illuminate\Pagination\LengthAwarePaginator;
475+
use GraphQL\Type\Definition\Type as GraphQLType;
476+
477+
class MyCustomPaginationFields
478+
{
479+
public static function getPaginationFields()
480+
{
481+
return [
482+
// Pass through a User object that we can use to calculate the totals
483+
'totals_for_user' => [
484+
'type' => \GraphQL::type('total'),
485+
'description' => 'Total posts, comments and likes for the result set',
486+
'resolve' => function () {
487+
return app()->make('App\User');
488+
},
489+
'selectable' => false,
490+
],
491+
// Add in the 'last page' value from the Laravel Paginator
492+
'last_page' => [
493+
'type' => GraphQLType::nonNull(GraphQLType::int()),
494+
'description' => 'Last page of the result set',
495+
'resolve' => function (LengthAwarePaginator $data) {
496+
return $data->lastPage();
497+
},
498+
'selectable' => false,
499+
],
500+
];
501+
}
502+
}
503+
```
504+
505+
Then add a config entry to map this class:
506+
507+
```
508+
'custom_paginators' => [
509+
'post_pagination' => \Namespace\Of\The\MyCustomPaginationFields::class,
510+
],
511+
```
512+
You can now query against the new fields in the same way as for the core pagination metadata. We could now extend the example
513+
query from earlier to get the new fields.
514+
515+
Query: `posts(limit:10,page:1){data{id},totals_for_user,total,per_page,last_page}`:
516+
517+
```
518+
{
519+
"data": {
520+
"posts: [
521+
"data": [
522+
{"id": 3},
523+
{"id": 5},
524+
...
525+
],
526+
"totals_for_user": [
527+
{"posts": 12},
528+
{"comments": 42},
529+
{"likes": 101}
530+
],
531+
"total": 21,
532+
"per_page": 10,
533+
"last_page": 3
534+
]
535+
}
536+
}
537+
```
538+
539+
540+
If you want to change the name of a default field to fit with users expectations (maybe you want 'total_records' rather
541+
than 'total'), just copy the entry for the field you want to replace (they're in Rebing/GraphQL/Support/PaginationType.php)
542+
and add it to your custom class.
543+
544+
463545
### Batching
464546

465547
You can send multiple queries (or mutations) at once by grouping them together. Therefore, instead of creating two HTTP requests:

src/Rebing/GraphQL/Support/PaginationType.php

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,22 @@ class PaginationType extends ObjectType {
1212
public function __construct($typeName, $customName = null)
1313
{
1414
$name = $customName ?: $typeName . '_pagination';
15+
16+
$customPaginator = config('graphql.custom_paginators.' . $name, null);
17+
$customFields = $customPaginator ? $customPaginator::getPaginationFields() : [];
18+
1519
$config = [
1620
'name' => $name,
17-
'fields' => array_merge($this->getPaginationFields(), [
18-
'data' => [
19-
'type' => GraphQLType::listOf(GraphQL::type($typeName)),
20-
'resolve' => function(LengthAwarePaginator $data) { return $data->getCollection(); },
21-
],
22-
])
21+
'fields' => array_merge(
22+
$this->getPaginationFields(),
23+
$customFields,
24+
[
25+
'data' => [
26+
'type' => GraphQLType::listOf(GraphQL::type($typeName)),
27+
'resolve' => function(LengthAwarePaginator $data) { return $data->getCollection(); },
28+
],
29+
]
30+
)
2331
];
2432

2533
parent::__construct($config);
@@ -61,4 +69,4 @@ protected function getPaginationFields()
6169
];
6270
}
6371

64-
}
72+
}

src/config/config.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,14 @@
139139
'disable_introspection' => false
140140
],
141141

142+
// You can define custom paginators to override the out-of-the-box fields
143+
// Useful if you want to inject some parameters of your own that apply at the top
144+
// level of the collection rather than to each instance returned. Can also use this
145+
// to add in more of the Laravel pagination data (e.g. last_page).
146+
'custom_paginators' => [
147+
// 'my_custom_pagination' => \Path\To\Your\CustomPagination::class,
148+
],
149+
142150
/*
143151
* Config for GraphiQL (see (https://github.com/graphql/graphiql).
144152
*/

0 commit comments

Comments
 (0)