Paginating Laravel Database Results with Custom Scopes

  • September 24, 2015

Welcome to the incredibly popular Easy Laravel 5 companion blog. To celebrate the new edition's release (updated for Laravel 5.5!) use the discount code easteregg to receive 20% off the book or book/video package! » Buy the book

It's a common practice to retrieve an ordered set of table records, such as a list of books according to the number of times they've been starred (favorited) by users. One convenient way to do this in Laravel is by adding a static method to the model.

static function starred()
{
    return \Book::where('star_count' > 0)
        ->orderBy('star_count', 'desc');
}

In your controllers you could then retrieve the list of ordered results by calling the starred method statically:

$books = Book::starred();

This is great, but what if you wanted to paginate results? Unfortunately, you can't just chain Laravel's paginate method to the custom static method:

$books = Book::starred()->paginate(20);

This doesn't work because the method doesn't know anything about the page number, offset, and limit values used for the pagination query. However, all is not lost thanks to Laravel's custom scope support. A custom scope suiting our needs will look almost identical to the above:

static function scopeStarred($query)
{
    return $query
    ->where('star_count', '>', 0)
    ->orderBy('star_count', 'desc');
}

With the custom scope in place, you can now chain the paginator to your custom method as desired:

$books = Book::starred()->paginate(20);