Can I pass per_page on query parameters like:
http://localhost:8000/api/company?per_page=100
and get the correct per page using only:
return response()->json(Company::paginate())
You can just pass the query parameter to paginate():
return response()->json(Company::paginate((int) request()->per_page));
return response()->json(Company::paginate((int) $request->per_page));
@staudenmeir thanks, but I things that can be automatically, and we don't need to expose this.. maybe?
I don't think that's possible.
But why?! It is very weird that the "page" number is determined by URL query parameter, but the "limit" (items per page) is taken from Eloquent Model. Why is Model telling what the default limit (items per page) is?! That is so weird! 🙄
https://github.com/illuminate/database/blob/v6.0.2/Eloquent/Builder.php#L698
What I did – I created a macro. In your app/Providers/AppServiceProvider.php file, inside boot method add this:
// Paginate the Eloquent results and allow the user to choose the amount of results per page
\Illuminate\Database\Eloquent\Builder::macro('paginateAuto', function ($perPage = null, ...$args) {
if ($perPage === null) {
$perPage = request()->query('limit');
$defaultPerPage = 10;
$maxPerPage = 100;
$perPage = (filter_var($perPage, FILTER_VALIDATE_INT) === false || (int) $perPage < 1)
? $defaultPerPage
: min((int) $perPage, $maxPerPage);
}
return $this->paginate($perPage, ...$args);
});
So now I can allow the user to decide how many results he wants (also I have max limit 100) and I don't have to change any Model. Of course, I have to change Controllers and instead of that long and complicated version, I have to write only this:
return response()->json(Company::paginateAuto());
Notice that in my macro I use query parameter called "limit", so you may want to change that to "per_page".
And no, there is no easy way to change/extend/tap the Illuminate\Database\Eloquent\Builder class, so the less painful way is using my macro.
Hey, @taylorotwell @tillkruss , could you please re-open this issue so we could at least talk about this with others? Or is there a legit reason why "per_page" should be extracted from the Model? 🤷♂
If you want to keep all the actual query variables in the paginated links (which seems to be useful in most cases), you can use:
return response()->json(Company::paginate()->withQueryString());
Most helpful comment
But why?! It is very weird that the "page" number is determined by URL query parameter, but the "limit" (items per page) is taken from Eloquent Model. Why is Model telling what the default limit (items per page) is?! That is so weird! 🙄
https://github.com/illuminate/database/blob/v6.0.2/Eloquent/Builder.php#L698
What I did – I created a macro. In your
app/Providers/AppServiceProvider.phpfile, insidebootmethod add this:So now I can allow the user to decide how many results he wants (also I have max limit 100) and I don't have to change any Model. Of course, I have to change Controllers and instead of that long and complicated version, I have to write only this:
Notice that in my macro I use query parameter called "limit", so you may want to change that to "per_page".
And no, there is no easy way to change/extend/tap the
Illuminate\Database\Eloquent\Builderclass, so the less painful way is using my macro.Hey, @taylorotwell @tillkruss , could you please re-open this issue so we could at least talk about this with others? Or is there a legit reason why "per_page" should be extracted from the Model? 🤷♂