Skip to content

Fix Pagination when Using Laravel Page Cache

Update [April 17, 2019]: I updated the original workaround (for Apache), which completely disabled caching for URLs containing a query string, with a similar ‘fix’ for NGINX. I will soon be adding have since added a second, real fix, too—one that fully enables caching, also for those URLs with a page query parameter.

Note: this article’s all about Laravel websites that rely on the Laravel Page Cache package for page caching.

While it is perfectly possible to disable caching for URLs that contain a query string, such routes may still get served a previously cached page. We need to not only prevent URLs with a query string from being cached, but also prevent serving a cached page.

Luckily, completely disabling page caching for URLs sporting a query string is easy enough. It only requires slightly modified rewrite conditions in your site’s public/.htaccess file—note the added %{QUERY_STRING} conditions:

RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} ^/?$
RewriteCond %{DOCUMENT_ROOT}/page-cache/pc__index__pc.html -f
RewriteRule .? page-cache/pc__index__pc.html [L]

RewriteCond %{QUERY_STRING} ^$
RewriteCond %{DOCUMENT_ROOT}/page-cache%{REQUEST_URI}.html -f
RewriteRule . page-cache%{REQUEST_URI}.html [L]

This way, a cached page’ll only get served if the query string is absent.

In case your web server’s running NGINX rather than Apache, the following lines, which go inside a server block, do the trick:

error_page 418 = @skip_cache;
recursive_error_pages on;

location = / {
  if ($arg_page) {
    return 418;
  }

  try_files /page-cache/pc__index__pc.html /index.php?$query_string;
}

location / {
  if ($arg_page) {
    return 418;
  }

  try_files $uri $uri/ /page-cache/$uri.html /index.php?$query_string;
}

location @skip_cache {
  try_files $uri $uri/ /index.php?$query_string;
}

Note: you can’t have multiple try_files directives inside a single location block, and if statements should only ever contain return …; or rewrite … last;.