Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

chrisml's avatar

How to cache Laravel paginate()?

Hey guys,

I have an Event model which has many Status'. I am paginating the statuses and using render() in the view to generate page links. I'm also caching these statuses like so:

// $id is the event ID
$statuses = Cache::remember('statuses_' . $id, 3, function() use ($event, $sort) {
    return $event->statuses()
        ->with('comments')
        ->latest()
        ->paginate(10);
});

However, this doesn't work as expected because the cache simply caches what it's given - and in this case it's given the first page of results. So when you navigate to the second page, you still get the first page of results.

Someone suggested not using paginate() and using skip() and take() to achieve the same effect:

// $id is the event ID
$page = $request->has('page') ? $request->query('page') : 1;

$statuses = Cache::remember('statuses_' . $id . '_page_' . $page, 3, function() use($event, $page) {
    return $event->statuses()
        ->with('comments')
        ->latest()
        ->take(10)
        ->skip( ($page - 1) * 10)
        ->get();
});

However, this means I can't use the render() method to generate the pagination links in the view. I need the links for non-js users and for search engines to crawl the pages.

I saw this code on github that caches pagination but have no idea where to start with it and not sure if it works with L5. - https://github.com/fideloper/Implementing-Laravel

If anyone has any pointers/suggestions that would be great!

Thanks

0 likes
8 replies
chrisml's avatar

The answer was staring me right in the face! I just have to add the page number to the cache.

$statuses = Cache::remember('statuses_' . $id . '_page_' . $page, 3, function() use ($event, $sort) {
    return $event->statuses()
        ->with('comments')
        ->latest()
        ->paginate(10);
});
10 likes
jadamec's avatar

How to forget these keys on newly added record, please (without Cache Tags because of 'file' driver..)?

GaryC's avatar

Nice! This just saved me a lot of time. I love this forum!!

Muzammil's avatar
$page=Request::input('page','1');

$statuses = Cache::remember('statuses_' . $id . '_page_' . $page, 3, function() use ($event, $sort) 
1 like
Amaury's avatar

I would prefer if the full collection is not to large:

  1. Cache the full collection
  2. Paginate through it after using Illuminate\Pagination\LengthAwarePaginator
$all = Cache::remember($key, $duration, function() {
    return Model::all();
});

$page = Input::get('page', 1);
$perPage = 10;

$data = new LengthAwarePaginator(
    $all->forPage($page, $perPage), $all->count(), $perPage, $page
);
7 likes
maturski's avatar

This is very interesting and I have a list of users that I would like to cache as well. I have implemented caching like this, however, I am curious how you would know what page to forget from the cache when a user is edited or deleted from the system.

Any thoughts on that? I do not want to have an admin delete a user and have to wait X minutes before the user is removed from the user paginated list. We are using softDeletes but the Eloquent call ignores the softDeleted items.

Amaury's avatar

@maturski

We are using softDeletes but the Eloquent call ignores the softDeleted items.

You have to use withTrashed method on the query:

App\User::withTrashed()->get();

See the Laravel documentation

Amaury's avatar

If you are caching paginated queries and user can change the perPage parameter in his preferences, don't forget to add the Paginator length in the cache key name.

Example: Caching items of a category

// from the request
$page = request()->has('page') ? request()->get('page') : 1;
// from user's preferences
$perPage = auth()->user()->preferences->perPage;

$items = Cache::remember('items_' . $category . '_pp_' . $perPage.'_p_'.$page, function () use ($category, $perPage, $page) {
  return Item::whereCategory($category)->paginate($perPage, ['*'], 'page', $page);
}
3 likes

Please or to participate in this conversation.