I need some clarifications about how Laravel's paginator works in the background:
Say I have a table with 1000 rows and I use
$results = Model::paginate(100);
If I understood correctly, Eloquent will bring back a collection containing all the rows (1000) from the table, slice it in smaller, 100 rows collections and attach the pagination buttons data to them. Now $results
contains the Page 1
collection and the pagination data for the buttons.
My question is: what happens in the background when I press Page 2
button?
Will Eloquent query the database again, retrieve the whole 1000 rows collection again, slice it and return the Page 2 collection, or does it work on the collection already retrieved back by my previous request?
Or, does Eloquent's ::paginate(100)
query the database using limits? Like
select * from table limit 100
?
2 Answers
The page that probably contains all the info: https://laravel.com/docs/5.8/pagination
Looking at the Illuminate\Database\Eloquent\Builder
class (Laravel 5.8):
/**
* Paginate the given query.
*
* @param int $perPage
* @param array $columns
* @param string $pageName
* @param int|null $page
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
*
* @throws \InvalidArgumentException
*/
public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
You can derive:
- It is a query builder function, therefore it acts upon the mysql that is being executed.
- reading from the docs, "The paginate method automatically takes care of setting the proper limit and offset based on the current page being viewed by the user". This means that the
page
url parameter (ie.example.com?page=2
) will automatically be taken into account and show the correct page. You can modify the name of this property using$pageName
). Page defaults to 1. - When you do
paginate(100)
and the page is 2, the query will fetch records 101-200 using something likeLIMIT 100 OFFSET 100
. So yes, it only retrieves the records it needs to view and it's therefore efficient.
As a sidenote: there are solutions to paginate a Collection
instance which is less efficient because you end up querying for instance 100 records each time, and dividing a collection of 100 items in pages of 10 (so 90 items are not being used). However this is usually not needed unless you have to compose collections manually (like a collection containing different types of Eloquent models).
Also as a sidenote, you might want to use
https://packagist.org/packages/barryvdh/laravel-debugbar
composer require barryvdh/laravel-debugbar
It allows you easy viewing of queries and many other application things.
LIMIT 100
, andOFFSET 100*($pagenumber-1)
. – Qirel