Tutorial

How To Limit and Paginate Query Results in Laravel Eloquent

Published on September 16, 2021

Developer Advocate

How To Limit and Paginate Query Results in Laravel Eloquent

Throughout this series, you have been adding new links to your demo application to test out several features from Laravel Eloquent. You may have noticed that the main index page is getting longer each time you add a new link, since there is no limit to the number of links shown in the application. Although that won’t be an issue when you have a small number of database entries, in the long term that might result in longer loading times for your page, and a layout that is more difficult to read due to the amount of content spread in a single page.

In this part of the series, you’ll learn how to limit the number of results in a Laravel Eloquent query with the limit() method, and how to paginate results with the simplePaginate() method.

Limiting Query Results

To get started, you’ll update your main application route (/) to limit the number of links that are listed on your index page.

Start by opening your web routes file in your code editor:

routes/web.php

Then, locate the main route definition:

routes/web.php
Route::get('/', function () {
    $links = Link::all()->sortDesc();
    return view('index', [
        'links' => $links,
        'lists' => LinkList::all()
    ]);
});

The highlighted line shows the query that obtains all links currently in the database, through the Link model all() method. As explained in a previous part of this series, this method is inherited from the parent Model class, and returns a collection with all database records associated with that model. The sortDesc() method is used to sort the resulting collection in descending order.

You’ll now change the highlighted line to use the database query sorting method orderBy(), which orders query results at the database level, instead of simply reordering the full set of rows that is returned as an Eloquent Collection via the all() method. You’ll also include a chained call to the limit() method in order to limit the query results. Finally, you’ll use the get() method to obtain the filtered resultset as an Eloquent Collection.

Replace your main route with the following code. The change is highlighted for your convenience:

routes/web.php
Route::get('/', function () {
    $links = Link::orderBy('created_at', 'desc')->limit(4)->get();

    return view('index', [
        'links' => $links,
        'lists' => LinkList::all()
    ]);
});

The updated code will now pull the latest 4 links added to the database, no matter at which list. Because all links are added to lists, visitors can still go to specific lists to see the full list of links.

Next, you’ll learn how to paginate results to make sure all links are still accessible, even though they don’t load all at once on a single page.

Paginating Query Results

Your index page now limits the number of links that are listed, so that your page isn’t overloaded with content, and gets rendered in a shorter amount of time. While this solution works well in many cases, you’ll need to make sure visitors can still access older links that aren’t visible by default. The most effective way to do so is by implementing a pagination where users can navigate between multiple pages of results.

Laravel Eloquent has native methods to facilitate implementing pagination on database query results. The paginate() and simplePaginate() methods take care of generating pagination links, handling HTTP parameters to identify which page is currently being requested, and querying the database with the correct limit and offset in order to obtain the expected set of results, depending on the number of records per page you want to list.

You’ll now update the Eloquent queries in routes/web.php to use the simplePaginate() method, which generates a basic navigation with previous and next links. Unlike the paginate() method, simplePaginate() doesn’t show information about the total number of pages in a query result.

Open the routes/web.php file in your code editor. Start by updating the / route, replacing the limit(4)->get() method call with the simplePaginate() method:

routes/web.php
...
Route::get('/', function () {
    $links = Link::orderBy('created_at', 'desc')->simplePaginate(4);

    return view('index', [
        'links' => $links,
        'lists' => LinkList::all()
    ]);
});
...

Next, locate the /{slug} route definition in the same file, and replace the get() method with the simplePaginate() method. This is how the code should look once you’re done:

routes/web.php
...
Route::get('/{slug}', function ($slug) {
    $list = LinkList::where('slug', $slug)->first();
    if (!$list) {
        abort(404);
    }

    return view('index', [
        'list' => $list,
        'links' => $list->links()->orderBy('created_at', 'desc')->simplePaginate(4),
        'lists' => LinkList::all()
    ]);
})->name('link-list');
...

This is how the finished routes/web.php file will look once you’re finished. The changes are highlighted for your convenience:

routes/web.php
<?php

use Illuminate\Support\Facades\Route;
use App\Models\Link;
use App\Models\LinkList;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    $links = Link::orderBy('created_at', 'desc')->simplePaginate(4);

    return view('index', [
        'links' => $links,
        'lists' => LinkList::all()
    ]);
});

Route::get('/{slug}', function ($slug) {
    $list = LinkList::where('slug', $slug)->first();
    if (!$list) {
        abort(404);
    }

    return view('index', [
        'list' => $list,
        'links' => $list->links()->orderBy('created_at', 'desc')->simplePaginate(4),
        'lists' => LinkList::all()
    ]);
})->name('link-list');

Save the file when you’re done.

The database queries are now updated, but you still need to update your front end view to include code that will render the navigation bar. The resulting Eloquent collection obtained with simplePaginate() contains a method called links(), which can be called from the front end view to output the necessary HTML code that will render a navigation section based on a paginated Eloquent query.

You can also use the links() method in a paginated Eloquent collection to access the inherent paginator object, which provides several helpful methods to obtain information about the content such as the current page and whether there are multiple pages of content or not.

Open the resources/views/index.blade.php application view in your code editor:

resources/views/index.blade.php

Locate the end of the section tagged with the links class, which contains a foreach loop where links are rendered. Place the following piece of code after that section and before the final </div> tag on that page:

resources/views/index.blade.php
        @if ($links->links()->paginator->hasPages())
            <div class="mt-4 p-4 box has-text-centered">
                {{ $links->links() }}
            </div>
        @endif

This code checks for the existence of multiple pages of results by accessing the paginator object and calling the hasPages() method. When that method returns true, the page renders a new div element and calls the links() method to print the navigation links for the related Eloquent query.

This is how the updated index.blade.php page will look like once you’re finished:

resources/views/index.blade.php
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>My Awesome Links</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css">

    <style>
        html {
            background: url("https://i.imgur.com/BWIdYTM.jpeg") no-repeat center center fixed;
            -webkit-background-size: cover;
            -moz-background-size: cover;
            -o-background-size: cover;
            background-size: cover;
        }

        div.link h3 {
            font-size: large;
        }

        div.link p {
            font-size: small;
            color: #718096;
        }
    </style>
</head>
<body>
<section class="section">
    <div class="container">
        <h1 class="title">
            @if (isset($list))
                {{ $list->title }}
            @else
                Check out my awesome links
            @endif
        </h1>
        <p class="subtitle">
            @foreach ($lists as $list)<a href="{{ route('link-list', $list->slug) }}" title="{{ $list->title }}" class="tag is-info is-light">{{ $list->title }} ({{ $list->links()->count() }})</a> @endforeach
        </p>

        <section class="links">
            @foreach ($links as $link)
                <div class="box link">
                    <h3><a href="{{ $link->url }}" target="_blank" title="Visit Link: {{ $link->url }}">{{ $link->description }}</a></h3>
                    <p>{{$link->url}}</p>
                    <p class="mt-2"><a href="{{ route('link-list', $link->link_list->slug) }}" title="{{ $link->link_list->title }}" class="tag is-info">{{ $link->link_list->title }}</a></p>
                </div>
            @endforeach
        </section>

        @if ($links->links()->paginator->hasPages())
            <div class="mt-4 p-4 box has-text-centered">
                {{ $links->links() }}
            </div>
        @endif
    </div>
</section>
</body>
</html>

Save the file when you’re done updating it. If you go back to your browser window and reload the application page now, you’ll notice a new navigation bar whenever you have more than 4 links in the general listing or in any individual link list page.

Updated application Landing Laravel with content pagination

With a functional pagination in place, you can grow your content while making sure that older items are still accessible to users and search engines. In cases where you need only a fixed amount of results based on a certain criteria, where pagination is not necessary, you can use the limit() method to simplify your query and guarantee a limited result set.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products


Tutorial Series: A Practical Introduction to Laravel Eloquent ORM

Eloquent is an object relational mapper (ORM) that is included by default within the Laravel framework. In this project-based series, you’ll learn how to make database queries and how to work with relationships in Laravel Eloquent. To follow along with the examples demonstrated throughout the series, you’ll improve a demo application with new models and relationships. Visit the series introduction page for detailed instructions on how to download and set up the project.

About the authors
Default avatar

Developer Advocate

Dev/Ops passionate about open source, PHP, and Linux.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
2 Comments


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

This comment has been deleted

    This comment has been deleted

      Try DigitalOcean for free

      Click below to sign up and get $200 of credit to try our products over 60 days!

      Sign up

      Join the Tech Talk
      Success! Thank you! Please check your email for further details.

      Please complete your information!

      Become a contributor for community

      Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

      DigitalOcean Documentation

      Full documentation for every DigitalOcean product.

      Resources for startups and SMBs

      The Wave has everything you need to know about building a business, from raising funding to marketing your product.

      Get our newsletter

      Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

      New accounts only. By submitting your email you agree to our Privacy Policy

      The developer cloud

      Scale up as you grow — whether you're running one virtual machine or ten thousand.

      Get started for free

      Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

      *This promotional offer applies to new accounts only.