Cache Eloquent queries in Laravel
Cache Eloquent queries in Laravel
When it comes to speeding up your application, caching can be the best thing to achieve. Laravel comes up with cache drivers pre-installed so you can enjoy the experience out-of-the-box. Redis, Memcached or just using local files, Laravel comes packed with this.
This time, we will talk about caching Eloquent queries directly from the models, thus making database caching a breeze!
The package can be found on GitHub, where the documentation will approach all of the main points of the app. However, during this article, you’ll learn just the basics of caching and clearing cache so you can get started before you will dig deeper.
Installation
The package can be installed through Composer:
composer require rennokki/laravel-eloquent-query-cache
Your models will need the QueryCacheable trait:
use Rennokki\QueryCache\Traits\QueryCacheable;
class Article extends Model
{
use QueryCacheable;
}
Enable the caching behavior by default
By default, the package does not enable query caching. To achieve this, add the $cacheFor
variable in your model:
use Rennokki\QueryCache\Traits\QueryCacheable;
class Article extends Model
{
use QueryCacheable;
protected $cacheFor = 180; // 3 minutes
}
Whenever a query will be triggered, the cache will intervene and in case the cache is empty for that query, it will store it and next time will retrieve it from the caching database; in case it exists, it will retrieve it and serve it, without hitting the database.
// database hit; the query result was stored in the cache
Article::latest()->get();
// database was not hit; the query result was retrieved from the cache
Article::latest()->get();
If you simply want to avoid hitting the cache, you can use the ->dontCache()
before hitting the final method.
Article::latest()->dontCache()->firstOrFail();
Enable the caching behavior query-by-query
The alternative is to enable cache query-by-query if caching by default doesn’t sound like a good option to you.
First of all, remove the $cacheFor
variable from your model if you have any set previously.
On each query, you can call ->cacheFor(...)
to specify that you want to cache that query.
Article::cacheFor(now()->addHours(24))->paginate(15);
Organize better with tags
Some cache storage, like Redis or Memcached, comes up with the support of tagging your keys. This is useful because we can tag our queries in-cache and invalidate the needed cache whenever we want to.
As a simple example, this can be useful if we want to invalidate the articles list cache when one article gets updated.
$articles = Article::cacheFor(60)->cacheTags(['latest:articles'])->latest()->get();
$article = Article::find($id);
$article->update(['title' => 'My new title']);
Article::flushQueryCache(['latest:articles']);
The method flushQueryCache
invalidates only the caches that were tagged with latest:articles
. If some other queries would have been tagged with tags other than latest:articles
, they would be kept in the cache.
Digging deeper
For more about this package, check out the project’s page on GitHub.