Database: Pagination

Introduction

In other frameworks, pagination can be very painful. Laravel's paginator is integrated with the query builder and Eloquent ORM and provides convenient, easy-to-use pagination of database results out of the box. The HTML generated by the paginator is compatible with the Bootstrap CSS framework.

Basic Usage

Paginating Query Builder Results

There are several ways to paginate items. The simplest is by using the paginate method on the query builder or an Eloquent query. The paginate method automatically takes care of setting the proper limit and offset based on the current page being viewed by the user. By default, the current page is detected by the value of the page query string argument on the HTTP request. This value is automatically detected by Laravel, and is also automatically inserted into links generated by the paginator.

In this example, the only argument passed to the paginate method is the number of items you would like displayed "per page". In this case, let's specify that we would like to display 15 items per page:

  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Http\Controllers\Controller;
  4. use Illuminate\Support\Facades\DB;
  5. class UserController extends Controller
  6. {
  7. /**
  8. * Show all of the users for the application.
  9. *
  10. * @return Response
  11. */
  12. public function index()
  13. {
  14. $users = DB::table('users')->paginate(15);
  15. return view('user.index', ['users' => $users]);
  16. }
  17. }

{note} Currently, pagination operations that use a groupBy statement cannot be executed efficiently by Laravel. If you need to use a groupBy with a paginated result set, it is recommended that you query the database and create a paginator manually.

"Simple Pagination"

If you only need to display simple "Next" and "Previous" links in your pagination view, you may use the simplePaginate method to perform a more efficient query. This is very useful for large datasets when you do not need to display a link for each page number when rendering your view:

  1. $users = DB::table('users')->simplePaginate(15);

Paginating Eloquent Results

You may also paginate Eloquent queries. In this example, we will paginate the User model with 15 items per page. As you can see, the syntax is nearly identical to paginating query builder results:

  1. $users = App\User::paginate(15);

You may call paginate after setting other constraints on the query, such as where clauses:

  1. $users = User::where('votes', '>', 100)->paginate(15);

You may also use the simplePaginate method when paginating Eloquent models:

  1. $users = User::where('votes', '>', 100)->simplePaginate(15);

Manually Creating A Paginator

Sometimes you may wish to create a pagination instance manually, passing it an array of items. You may do so by creating either an Illuminate\Pagination\Paginator or Illuminate\Pagination\LengthAwarePaginator instance, depending on your needs.

The Paginator class does not need to know the total number of items in the result set; however, because of this, the class does not have methods for retrieving the index of the last page. The LengthAwarePaginator accepts almost the same arguments as the Paginator; however, it does require a count of the total number of items in the result set.

In other words, the Paginator corresponds to the simplePaginate method on the query builder and Eloquent, while the LengthAwarePaginator corresponds to the paginate method.

{note} When manually creating a paginator instance, you should manually "slice" the array of results you pass to the paginator. If you're unsure how to do this, check out the array_slice PHP function.

Displaying Pagination Results

When calling the paginate method, you will receive an instance of Illuminate\Pagination\LengthAwarePaginator. When calling the simplePaginate method, you will receive an instance of Illuminate\Pagination\Paginator. These objects provide several methods that describe the result set. In addition to these helpers methods, the paginator instances are iterators and may be looped as an array. So, once you have retrieved the results, you may display the results and render the page links using Blade:

  1. <div class="container">
  2. @foreach ($users as $user)
  3. {{ $user->name }}
  4. @endforeach
  5. </div>
  6. {{ $users->links() }}

The links method will render the links to the rest of the pages in the result set. Each of these links will already contain the proper page query string variable. Remember, the HTML generated by the links method is compatible with the Bootstrap CSS framework.

Customizing The Paginator URI

The withPath method allows you to customize the URI used by the paginator when generating links. For example, if you want the paginator to generate links like http://example.com/custom/url?page=N, you should pass custom/url to the withPath method:

  1. Route::get('users', function () {
  2. $users = App\User::paginate(15);
  3. $users->withPath('custom/url');
  4. //
  5. });

Appending To Pagination Links

You may append to the query string of pagination links using the appends method. For example, to append sort=votes to each pagination link, you should make the following call to appends:

  1. {{ $users->appends(['sort' => 'votes'])->links() }}

If you wish to append all current query string values to the pagination links you may use the withQueryString method:

  1. {{ $users->withQueryString()->links() }}

If you wish to append a "hash fragment" to the paginator's URLs, you may use the fragment method. For example, to append #foo to the end of each pagination link, make the following call to the fragment method:

  1. {{ $users->fragment('foo')->links() }}

Adjusting The Pagination Link Window

You may control how many additional links are displayed on each side of the paginator's URL "window". By default, three links are displayed on each side of the primary paginator links. However, you may control this number using the onEachSide method:

  1. {{ $users->onEachSide(5)->links() }}

Converting Results To JSON

The Laravel paginator result classes implement the Illuminate\Contracts\Support\Jsonable Interface contract and expose the toJson method, so it's very easy to convert your pagination results to JSON. You may also convert a paginator instance to JSON by returning it from a route or controller action:

  1. Route::get('users', function () {
  2. return App\User::paginate();
  3. });

The JSON from the paginator will include meta information such as total, current_page, last_page, and more. The actual result objects will be available via the data key in the JSON array. Here is an example of the JSON created by returning a paginator instance from a route:

  1. {
  2. "total": 50,
  3. "per_page": 15,
  4. "current_page": 1,
  5. "last_page": 4,
  6. "first_page_url": "http://laravel.app?page=1",
  7. "last_page_url": "http://laravel.app?page=4",
  8. "next_page_url": "http://laravel.app?page=2",
  9. "prev_page_url": null,
  10. "path": "http://laravel.app",
  11. "from": 1,
  12. "to": 15,
  13. "data":[
  14. {
  15. // Result Object
  16. },
  17. {
  18. // Result Object
  19. }
  20. ]
  21. }

Customizing The Pagination View

By default, the views rendered to display the pagination links are compatible with the Bootstrap CSS framework. However, if you are not using Bootstrap, you are free to define your own views to render these links. When calling the links method on a paginator instance, pass the view name as the first argument to the method:

  1. {{ $paginator->links('view.name') }}
  2. // Passing data to the view...
  3. {{ $paginator->links('view.name', ['foo' => 'bar']) }}

However, the easiest way to customize the pagination views is by exporting them to your resources/views/vendor directory using the vendor:publish command:

  1. php artisan vendor:publish --tag=laravel-pagination

This command will place the views in the resources/views/vendor/pagination directory. The bootstrap-4.blade.php file within this directory corresponds to the default pagination view. You may edit this file to modify the pagination HTML.

If you would like to designate a different file as the default pagination view, you may use the paginator's defaultView and defaultSimpleView methods within your AppServiceProvider:

  1. use Illuminate\Pagination\Paginator;
  2. public function boot()
  3. {
  4. Paginator::defaultView('view-name');
  5. Paginator::defaultSimpleView('view-name');
  6. }

Paginator Instance Methods

Each paginator instance provides additional pagination information via the following methods:

MethodDescription
$results->count()Get the number of items for the current page.
$results->currentPage()Get the current page number.
$results->firstItem()Get the result number of the first item in the results.
$results->getOptions()Get the paginator options.
$results->getUrlRange($start, $end)Create a range of pagination URLs.
$results->hasPages()Determine if there are enough items to split into multiple pages.
$results->hasMorePages()Determine if there is more items in the data store.
$results->items()Get the items for the current page.
$results->lastItem()Get the result number of the last item in the results.
$results->lastPage()Get the page number of the last available page. (Not available when using simplePaginate).
$results->nextPageUrl()Get the URL for the next page.
$results->onFirstPage()Determine if the paginator is on the first page.
$results->perPage()The number of items to be shown per page.
$results->previousPageUrl()Get the URL for the previous page.
$results->total()Determine the total number of matching items in the data store. (Not available when using simplePaginate).
$results->url($page)Get the URL for a given page number.
$results->getPageName()Get the query string variable used to store the page.
$results->setPageName($name)Set the query string variable used to store the page.