Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Cacheable Laravel Package

ahmedzidan/laravel-cacheable

Laravel Cacheable adds automatic caching to your Eloquent models, so frequent queries are served from cache and invalidated on create, update, or delete. Drop in the trait, configure a TTL, and cut database load with almost no code changes.

View on GitHub
Deep Wiki
Context7

Getting Started

Before you install anything, verify compatibility. This package is archived and marked abandoned. Its composer.json constraints target older Laravel versions, so on Laravel 9+ you may need to fork it, relax the constraint, or use --ignore-platform-reqs only as a short-term experiment. Treat it as a legacy utility: fine for an existing app already on it, risky for a new build.

Minimal setup:

composer require rinvex/laravel-cacheable
php artisan vendor:publish --provider="Rinvex\Cacheable\Providers\CacheableServiceProvider"

The published config/cacheable.php controls the cache store, TTL, and key prefix. Point it at Redis or Memcached if you want tag-based invalidation:

// config/cacheable.php
return [
    'store'  => env('CACHE_DRIVER', 'redis'),
    'ttl'    => 60,          // confirm units in your version — commonly minutes
    'prefix' => 'cacheable.',
];

Then opt individual models in:

use Rinvex\Cacheable\CacheableEloquent;

class Category extends Model
{
    use CacheableEloquent;
}

Where to look first: the query builder the trait swaps in. Cacheable works by intercepting Eloquent reads (find, first, where(...)->get(), etc.) and replaying them through the cache, then flushing on model saved/deleted events. Once that mental model clicks, the rest is configuration and edge cases.

First use case: a read-heavy lookup table — categories, countries, settings, plan definitions. Something queried on nearly every request and written rarely.

$categories = Category::where('active', true)->orderBy('name')->get(); // cached
$category   = Category::findOrFail($id);                              // cached

If the second call in a request is measurably faster and your database query count drops, it is wired correctly.

Implementation Patterns

Be selective. Add the trait only to models with a high read-to-write ratio. Applying it to a busy transactional model (orders, ledger entries) turns every write into a cache flush and gains little.

Pair every “dirty” write path with an explicit flush. Model events cover save(), create(), delete(), but not everything:

Category::where('parent_id', $id)->update(['active' => false]);
Category::flushCache(); // call this yourself

Wrap bulk operations in a small service method that flushes after the write, rather than scattering flushCache() calls through controllers.

Use tags when the store supports them. Redis and Memcached support tags; file and database stores do not. Without tags, flushing falls back to prefix-based invalidation, which is coarser and can be slower on large caches. If you need per-model or per-tenant flushing, use a tag-capable store.

Namespace by tenant or environment. Set the prefix from config to include tenant and app environment so two tenants or a staging/dev pair never collide:

'prefix' => 'cacheable.'.tenant()->id.'.'.app()->environment().'.',

Keep cached queries deterministic. Avoid embedding now(), random values, or request-scoped state inside cached query scopes. If a query varies per user, ensure that context is part of the SQL bindings (e.g. a where user_id = ? global scope) so keys differ, or bypass the cache entirely.

Warm after deploy. After schema or seed changes, run the hot reads once or flush and let the cache rebuild:

Category::flushCache();

Testing pattern: use the array cache store in phpunit.xml, and flush in setUp() so tests do not observe each other’s cached models:

protected function setUp(): void
{
    parent::setUp();
    Cache::flush();
}

Gotchas and Tips

  • Abandoned status is the biggest gotcha. No security patches, no Laravel 10/11 compatibility guarantees, no fixes for Eloquent internals changes. If you adopt it, pin the version and plan a migration to Cache::remember(), a repository layer, or a maintained alternative.
  • Query-builder writes bypass invalidation. ->update(), ->increment(), ->decrement(), ->insert(), DB::table(...), and raw SQL do not fire model events. Cached rows go stale silently. Audit these paths and flush explicitly.
  • Relationship data goes stale. If you cache Post::with('author')->find($id) and the author’s name changes, the Post cache is unaffected. Either avoid eager-loading volatile relations in cached queries or flush related models on write.
  • Tag support depends entirely on the store. File/database stores silently degrade to prefix flushing. Test invalidation explicitly rather than assuming it worked.
  • Verify the TTL unit. Versions have differed between minutes and seconds. A “60” that you assumed was seconds but is minutes is a debugging session waiting to happen.
  • Transactions + events. Model events fire inside the transaction. A rollback after a flush leaves the cache cold (safe) but a cache repopulation mid-transaction can observe uncommitted state (unsafe). Flush after commit where correctness matters: DB::afterCommit(fn () => Category::flushCache()).
  • Serialization coupling. Cached entries are serialized model instances. Renaming a column, removing an attribute, or changing a cast can make previously cached payloads incompatible. Flush after every deploy that touches model shape.
  • Cache stampede. Concurrent requests on a cold key all hit the database. Under load, add a short lock or accept the spike; the package does not provide stampede protection.
  • Debugging tips: disable the trait in local by conditionally applying it, or switch the store to array. Inspect raw keys in Redis (KEYS 'cacheable.*') to confirm prefixing and TTLs. Add temporary logging inside your flush calls to verify they fire.
  • Extension points: the trait is the seam — override flushCache() on a model to add custom invalidation (e.g. clearing a response cache alongside), or listen to saved/deleted to fan out flushes to related models. Do not rely on internals you cannot read; the package is not maintained, so anything undocumented is effectively private API.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel