PHPackages                             ghostcompiler/laravel-model-caching - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. ghostcompiler/laravel-model-caching

ActiveLibrary[Database &amp; ORM](/categories/database)

ghostcompiler/laravel-model-caching
===================================

Relationship-aware Eloquent model caching for Laravel with dependency tracking, cache tags, pagination-safe keys, and opt-in model APIs.

v1.0.0(1mo ago)312.3k3MITPHPPHP ^8.1CI passing

Since Jun 6Pushed 2w ago1 watchersCompare

[ Source](https://github.com/ghostcompiler/laravel-model-caching)[ Packagist](https://packagist.org/packages/ghostcompiler/laravel-model-caching)[ RSS](/packages/ghostcompiler-laravel-model-caching/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (7)Versions (2)Used By (0)

 [![Laravel Uploads Logo](https://camo.githubusercontent.com/7a311440d646263aeef835cc3b8d3f30b2c35f8fbf32c26ecf9a971070371ca9/68747470733a2f2f7265732e636c6f7564696e6172792e636f6d2f646a6776666c3174762f696d6167652f75706c6f61642f76313738303636363739312f6c6f676f5f6d716e716e342e706e67)](https://camo.githubusercontent.com/7a311440d646263aeef835cc3b8d3f30b2c35f8fbf32c26ecf9a971070371ca9/68747470733a2f2f7265732e636c6f7564696e6172792e636f6d2f646a6776666c3174762f696d6167652f75706c6f61642f76313738303636363739312f6c6f676f5f6d716e716e342e706e67)

 [![Laravel](https://camo.githubusercontent.com/04ac196cc9d1ede920f94387cae5075133cbd568d7b69f7b11f953f0e45e1281/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d3130253230746f25323031332d4646324432303f7374796c653d666f722d7468652d6261646765266c6f676f3d6c61726176656c266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/04ac196cc9d1ede920f94387cae5075133cbd568d7b69f7b11f953f0e45e1281/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d3130253230746f25323031332d4646324432303f7374796c653d666f722d7468652d6261646765266c6f676f3d6c61726176656c266c6f676f436f6c6f723d7768697465) [![PHP](https://camo.githubusercontent.com/0b828fae3809f5692b3303526d43b126732078cc61f176b8f877332096c98bc0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e312532422d3737374242343f7374796c653d666f722d7468652d6261646765266c6f676f3d706870266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/0b828fae3809f5692b3303526d43b126732078cc61f176b8f877332096c98bc0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e312532422d3737374242343f7374796c653d666f722d7468652d6261646765266c6f676f3d706870266c6f676f436f6c6f723d7768697465) [![Laravel Model Caching](https://camo.githubusercontent.com/5abef87ca71c04d236ec0eaef1992f815ee645210f88bebd8282ab958ff96885/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4275696c74253230576974682d4c61726176656c2532304d6f64656c25323043616368696e672d3046313732413f7374796c653d666f722d7468652d6261646765)](https://camo.githubusercontent.com/5abef87ca71c04d236ec0eaef1992f815ee645210f88bebd8282ab958ff96885/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4275696c74253230576974682d4c61726176656c2532304d6f64656c25323043616368696e672d3046313732413f7374796c653d666f722d7468652d6261646765)

 [![](https://camo.githubusercontent.com/8461229235fe5129c783b8320e7ec41c9d88469e1be58789e737312b43c2c726/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f67686f7374636f6d70696c65722f6c61726176656c2d6d6f64656c2d63616368696e673f7374796c653d666f722d7468652d6261646765266c6f676f3d676974687562)](https://camo.githubusercontent.com/8461229235fe5129c783b8320e7ec41c9d88469e1be58789e737312b43c2c726/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f67686f7374636f6d70696c65722f6c61726176656c2d6d6f64656c2d63616368696e673f7374796c653d666f722d7468652d6261646765266c6f676f3d676974687562) [![](https://camo.githubusercontent.com/ad0247ac8a356289f172f897e56d749f31e1850d52f9e2b6c5e00f4036bb4f0b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f67686f7374636f6d70696c65722f6c61726176656c2d6d6f64656c2d63616368696e673f7374796c653d666f722d7468652d6261646765266c6f676f3d7061636b6167697374)](https://camo.githubusercontent.com/ad0247ac8a356289f172f897e56d749f31e1850d52f9e2b6c5e00f4036bb4f0b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f67686f7374636f6d70696c65722f6c61726176656c2d6d6f64656c2d63616368696e673f7374796c653d666f722d7468652d6261646765266c6f676f3d7061636b6167697374)

Laravel Model Caching
=====================

[](#laravel-model-caching)

Relationship-aware Eloquent model caching for Laravel.

This package is designed for applications where cached parent queries must be invalidated when loaded child models change. It is not only a query cache. It stores deterministic query results and records a lightweight dependency index from model instances to cache keys.

Features
--------

[](#features)

- Opt-in model caching through `HasModelCaching`
- `remember()`, `rememberForever()`, `dontCache()`, and optional `auto_remember` for trait-enabled models
- Cached read operations: `get`, `first`, `firstOrFail`, `find`, `findOrFail`, and pagination methods
- Nested eager-load aware cache keys
- Pagination-safe keys for `paginate()`, `simplePaginate()`, and `cursorPaginate()`
- Morph map versioning in cache keys
- Dependency index for precise invalidation on child updates
- Structured cache payloads for models and collections (safe for morph relations and eager loads)
- Cache tags when the selected Laravel cache driver supports them
- Model observer invalidation for saved, deleted, restored, and force deleted events
- Artisan commands for warming, inspecting, and flushing tracked entries

Installation
------------

[](#installation)

```
composer require ghostcompiler/laravel-model-caching
```

Publish the config:

```
php artisan vendor:publish --tag=model-cache-config
```

Redis is recommended for production because the dependency index can use native Redis sets.

Quick Start
-----------

[](#quick-start)

Add the trait to models that should be cacheable:

```
use GhostCompiler\LaravelModelCaching\Concerns\HasModelCaching;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    use HasModelCaching;
}
```

The trait alone does not cache queries. Either call `remember()` on the chain or enable `auto_remember` in config.

Use `remember()` on normal Eloquent queries:

```
$users = User::with('posts.comments')
    ->where('active', true)
    ->remember(60)
    ->get();

$tenant = User::whereHas('brand.domains', fn ($q) => $q->where('domain', $host))
    ->with('brand')
    ->remember(300)
    ->firstOrFail();
```

Enable automatic caching for all read queries on trait-enabled models:

```
// config/model-cache.php
'auto_remember' => true,
```

Then `User::where('active', true)->first()` is cached with `default_ttl`. Use `dontCache()` on chains that must always hit the database.

Use the convenience APIs:

```
$user = User::findCached(1);

$user->loadCached('posts.comments');
```

Disable caching on a query chain:

```
$users = User::remember(600)
    ->dontCache()
    ->where('active', true)
    ->get();
```

Cache Key Safety
----------------

[](#cache-key-safety)

Each key includes:

- Model class, table, and connection
- SQL and bindings
- Selected columns
- Limit, offset, groups, and orders
- Eager loads, including nested relation names
- Closure constraint source fingerprints when available
- Pagination page, page name, cursor, and per-page values
- Morph map and configured morph map version
- Optional auth and tenant context

These queries generate different keys:

```
User::with('posts')->remember(60)->get();
User::with('posts.comments')->remember(60)->get();
User::with(['posts', 'roles'])->remember(60)->get();
```

Dependency Invalidation
-----------------------

[](#dependency-invalidation)

On a cache miss, the package stores the query result and walks the returned models plus loaded relations. It records only model primary keys in a dependency index:

```
model-cache:dependency:user:1 -> [cache-key-a]
model-cache:dependency:post:5 -> [cache-key-a, cache-key-b]
model-cache:dependency:comment:9 -> [cache-key-b]

```

When `Post #5` is saved, deleted, or force deleted, only keys listed under `model-cache:dependency:post:5` are forgotten. No full application cache flush is required.

When a new `Post` is **created** (or soft-deleted row is **restored**), every cached query rooted on that model class is forgotten too — for example paginated user lists — so new rows can appear on the next request without waiting for TTL expiry:

```
model-cache:dependency:user:{class-hash}:_class -> [page-1-key, page-2-key, ...]

```

Updates to an existing row still invalidate only that row's dependencies plus any list page that included that instance.

Cache tags are used as an extra layer when supported. Per-entry tag metadata is stored separately so entries can include result-specific tags such as `post:5` while still being readable later from a deterministic query key.

Morph Relations
---------------

[](#morph-relations)

Polymorphic relations are supported through the actual related models returned by Eloquent and through morph context in the cache key. If you change Laravel's morph map aliases, bump:

```
'morph_map_version' => 2,
```

This prevents old entries from colliding with new alias meanings.

Pagination
----------

[](#pagination)

Pagination methods are cached at the top-level builder operation:

```
$users = User::with('posts')->remember(300)->paginate(10);
```

The key includes the page name, current page, per-page value, and cursor state where applicable.

Configuration
-------------

[](#configuration)

```
return [
    'enabled' => true,
    'default_ttl' => 3600,
    'auto_remember' => false,
    'store' => null,
    'prefix' => 'model-cache',
    'cache_tags' => true,
    'dependency_ttl' => 604800,
    'use_redis_sets' => true,
    'auto_observe_models' => true,
    'include_auth_id' => false,
    'context_callbacks' => [],
    'morph_map_version' => 1,
    'debug' => false,
];
```

For multi-tenant apps, add a context callback:

```
'context_callbacks' => [
    'tenant' => fn () => tenant('id'),
],
```

Commands
--------

[](#commands)

Warm a query:

```
php artisan model-cache:warm "App\Models\User" --with=posts --with=posts.comments --ttl=600 --limit=1000
```

Inspect keys depending on a model instance:

```
php artisan model-cache:inspect "App\Models\Post" 5
```

Flush keys depending on a model instance:

```
php artisan model-cache:flush "App\Models\Post" 5
```

Flush every key known to the package dependency index:

```
php artisan model-cache:flush --known
```

Production Notes
----------------

[](#production-notes)

- Treat `auto_remember` carefully: incidental reads on cacheable models are cached until TTL or model invalidation. Use `dontCache()` in admin or debug paths.
- Prefer Redis for high traffic APIs.
- Keep cacheable queries deterministic.
- Include tenant/auth context when query results differ by user or tenant.
- Use eager loading intentionally. The package tracks loaded relations, not unloaded graph possibilities.
- Bump `morph_map_version` after morph map changes.
- Use `rememberForever()` only for data that is always invalidated by model events.

Testing
-------

[](#testing)

```
composer install
composer test
```

###  Health Score

48

—

FairBetter than 94% of packages

Maintenance94

Actively maintained with recent releases

Popularity35

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 55.6% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

48d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/fdfc8e246731b39477bdf1668097bd52dfa52a1a9588235cbdd75d2dc7c6b927?d=identicon)[ghostcompiler](/maintainers/ghostcompiler)

---

Top Contributors

[![ghost-maintainer](https://avatars.githubusercontent.com/u/269910969?v=4)](https://github.com/ghost-maintainer "ghost-maintainer (5 commits)")[![ghostcompiler](https://avatars.githubusercontent.com/u/269910969?v=4)](https://github.com/ghostcompiler "ghostcompiler (4 commits)")

---

Tags

backendcachecache-tagscachingdatabasedeveloper-toolseloquentlaravellaravel-cachelaravel-cachinglaravel-model-cachinglaravel-packagemodel-cacheopensourceoptimizationormperformancephpquery-cacheredis

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/ghostcompiler-laravel-model-caching/health.svg)

```
[![Health](https://phpackages.com/badges/ghostcompiler-laravel-model-caching/health.svg)](https://phpackages.com/packages/ghostcompiler-laravel-model-caching)
```

###  Alternatives

[laravel/ai

The official AI SDK for Laravel.

1.0k3.2M246](/packages/laravel-ai)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M136](/packages/laravel-pulse)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M133](/packages/roots-acorn)[propaganistas/laravel-disposable-email

Disposable email validator

6023.0M7](/packages/propaganistas-laravel-disposable-email)[mike-bronner/laravel-model-caching

Automatic caching for Eloquent models.

2.4k96.5k1](/packages/mike-bronner-laravel-model-caching)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
