-
-
Notifications
You must be signed in to change notification settings - Fork 866
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[GraphQl] Better pagination support #2142
Conversation
The phpstan errors seem to be unrelated to this PR, they are also thrown on the base master branch. The new behavior now working as intended. PHPUnit and Behat tests are updated to reflect this. The docs PR is almost ready, just figuring out the wording and spelling. And then I'll finalize this :) |
rebasing should do ! |
I've rebased my commits, but unfortunately something doesn't seem right :-/ But at least I've included the docs PR api-platform/docs#561 :) |
if (isset($collectionArgs[$resourceClass]['before'])) { | ||
$before = \base64_decode($collectionArgs[$resourceClass]['before'], true); | ||
$firstResult = (int) $before - $itemsPerPage; | ||
$firstResult = (false === $before) ? 0 : (int) $firstResult; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cast is not needed.
$before = \base64_decode($collectionArgs[$resourceClass]['before'], true); | ||
$firstResult = (int) $before - $itemsPerPage; | ||
$firstResult = (false === $before) ? 0 : (int) $firstResult; | ||
if (false !== $before && 0 > $firstResult) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can remove the false !== $before
part. Since $firstResult
will be negative only if $before
is not false
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this part tested?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is correct I'll change that.
It is tested in features/graphql/collection.feature starting on line 424
@@ -121,6 +122,19 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator | |||
$firstResult = (int) $after; | |||
$firstResult = false === $after ? $firstResult : ++$firstResult; | |||
} | |||
if (isset($collectionArgs[$resourceClass]['last'])) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are doing an extra query inside a building of a query. Maybe there is a better way to do this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's kinda hacky. It's for the case that before isn't set, so you can get the last items in the correct order. I have to think about another way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't come up with an idea so far :-/ How should we handle this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think doing backwards pagination in SQL is tricky and you need to know the total rows the first time in order to do it.
The current implementation needs to be changed though because getArrayResult
can be very big and I think it can eat all the memory. You need to use an SQL count.
The Doctrine Paginator is doing it anyway when you get the total items (see its method getCountQuery
). You need to do something like this.
} | ||
|
||
foreach ($collection as $index => $object) { | ||
if ($index === $collectionLastIndex) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this needed? The $collectionLastIndex
is always the endCursor doesn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are completly right, it's not needed at all
]; | ||
} | ||
|
||
if ($collection instanceof PaginatorInterface && ($totalItems = $collection->getTotalItems()) > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be moved inside the previous if
.
d2ad79f
to
10ef076
Compare
Add support for graphql before, last, startcursor
No further changes, only updated branch to match base branch |
@Reduxx Could you try to use an SQL count? |
2d4f1b7
to
0160051
Compare
This PR should be good. |
6536a32
to
6141b39
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
The ___
field and the hardcoded limit0
disturb me but I guess they're fine?
} | ||
|
||
if (isset($context['filters']['last']) && !isset($context['filters']['before'])) { | ||
$context['count'] = (new DoctrineOrmPaginator($queryBuilder))->count(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I assume that partial pagination is not compatible with Graphql?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. We could make it compatible later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code you annotated is only if you are doing backwards pagination though.
This PR misses the |
|
Thank @Reduxx 🙂 |
any plans to have this released soon? |
Need this now. My after cursor resulting in empty result after five iteration. Why this not in production? |
This is a WIP Pull Request. It aims to make the pagination support closer to the graphql-relay-js implementation.
Bug Fixes:
pageInfo.endCursor is now the last item of the current page
New Features:
pageInfo.startCursor: new Type for the first item of the current page
queryArguments last and before: the counterpart for first and after
PHPUnit Tests: passing
Behat:
I haven't figured out why the other tests aren't running properly, I have to check this.
Any help with the tests are appreciated, this is the first time I've ever seen Behat and used prophecies in PHPUnit
I'll open a PR for the docs and finish this up according to the guidelines when I have the time :)