0
votes

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
Using limits and offset, you query only the data that you need. So you have something like LIMIT 100, and OFFSET 100*($pagenumber-1).Qirel

2 Answers

1
votes

You can use Laravel Telescope to see how Laravel works. On the queries tab you will see what queries executed when you make requests (if caching is not enabled). enter image description here

0
votes

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 like LIMIT 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.