Skip to content
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

[5.5] Prevent negative offsets when paginating collection #21658

Merged
merged 1 commit into from
Oct 13, 2017

Conversation

tautvydasr
Copy link
Contributor

Recently I faced a problem with collection pagination because it calculates negative offset and returns entries from the end of collection items.

For example:

$c = new Collection(['one', 'two', 'three', 'four']);
$c->forPage(0, 2)->all() // returns ['three', 'four']

I believe it would be nice if offset could not be negative and only positive numbers could be accepted as page.

@tillkruss tillkruss changed the title Prevent negative offsets when paginating collection [5.5] Prevent negative offsets when paginating collection Oct 13, 2017
@GrahamCampbell
Copy link
Member

Instead of wriapping, perhapse we should throw an invalid argument exception?

@taylorotwell taylorotwell merged commit 0c64ff0 into laravel:5.5 Oct 13, 2017
@vlakoff
Copy link
Contributor

vlakoff commented Oct 14, 2017

Agree with Graham. Silently "fixing" the argument doesn't sound right.

@vlakoff
Copy link
Contributor

vlakoff commented Oct 15, 2017

Similar issue in Query Builder's forPage(), it uses offset() which also has a "0 capping", see #3017.

@vlakoff
Copy link
Contributor

vlakoff commented Oct 16, 2017

@tautvydasr Out of curiosity, could you quickly explain your use case, where the application calculates negative offsets (and capping to 0 is an acceptable solution)?

@tautvydasr tautvydasr deleted the patch-collection-pagination branch October 16, 2017 05:04
@tautvydasr
Copy link
Contributor Author

@vlakoff I detected the problem when page number comes from request and if there is no page in request query it becomes 0 and offset becomes -10 (because for example we are showing 10 entries per page)

$page = (int)$request->get('page'); // here page parameter becomes 0
$entries = $collection->forPage($page, 10); // here we pass 0 as page and offset becomes -10 and we get last 10 entries from collection

@devcircus
Copy link
Contributor

You shouldn't be using a cast non-existent value as a valid parameter. Either get the page number from the request or default to 1. Now that we've hacked a solution into the core, I guess it doesn't matter, but you shouldn't be trusting that value.

@vlakoff
Copy link
Contributor

vlakoff commented Oct 16, 2017

That's what I was fearing. It should be your application's responsibility to filter the user input:

// specify default value for clarity,
// even if it would work without it (thanks to the sanitization below)
$page = (int) $request->input('page', '1');

// if value is invalid (out of range), fall back to default value
if ($page < 1) {
    $page = 1;
}

$entries = $collection->forPage($page, 10);

@devcircus, no release has been tagged since, so it's still time to revert this, if desired so. I still think it should be reverted, and an exception thrown instead, but that's only my opinion.

edit: The change has been released, with laravel 5.5.15. I guess we'll have to live with it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants