### Install Model Caching Package Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Use Composer to require the package. The service provider is auto-discovered, so no additional setup is needed. ```bash composer require genealabs/laravel-model-caching ``` -------------------------------- ### Stack Trace Example Source: https://github.com/mikebronner/laravel-model-caching/blob/master/ISSUE_TEMPLATE.md Paste the relevant, complete stack trace here when reporting an issue. ```text *paste the relevant, complete stack trace here* ``` -------------------------------- ### Install AWS SDK for DynamoDB Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md If not already present, install the AWS SDK for PHP using Composer to enable DynamoDB cache store functionality. ```sh composer require aws/aws-sdk-php ``` -------------------------------- ### Real-World Example: Blog Posts with Relationships Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Demonstrates caching for posts with eager-loaded comments and tags. Cache invalidation is automatic on related model changes. ```php class Post extends BaseModel { public function comments() { return $this->hasMany(Comment::class); } public function tags() { return $this->belongsToMany(Tag::class); } } // All cached automatically — the query, the eager loads, everything. 🪄 $posts = Post::with('comments', 'tags') ->where('published', true) ->latest() ->paginate(15); ``` -------------------------------- ### Basic Query Caching with get() Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Use the get() method to retrieve all matching records. Results are automatically cached indefinitely and invalidated when model data changes. ```php get(); ``` -------------------------------- ### Publish Configuration File Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Use the Artisan command to publish the configuration file for customization. ```sh php artisan modelCache:publish --config ``` -------------------------------- ### Configuration Options Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Customize caching behavior by publishing the configuration file and using environment variables. ```php '', // Enable/disable caching globally // MODEL_CACHE_ENABLED=true 'enabled' => env('MODEL_CACHE_ENABLED', true), // Include database connection/name in cache keys (multi-tenant/multi-db) // MODEL_CACHE_USE_DATABASE_KEYING=true 'use-database-keying' => env('MODEL_CACHE_USE_DATABASE_KEYING', true), // Cache store from config/cache.php (null = default store) // MODEL_CACHE_STORE=redis 'store' => env('MODEL_CACHE_STORE'), // Fall back to database if cache unavailable (Redis down, etc.) // MODEL_CACHE_FALLBACK_TO_DB=false 'fallback-to-database' => env('MODEL_CACHE_FALLBACK_TO_DB', false), ]; // Example .env configuration // MODEL_CACHE_ENABLED=true // MODEL_CACHE_STORE=redis // MODEL_CACHE_USE_DATABASE_KEYING=true // MODEL_CACHE_FALLBACK_TO_DB=true ``` -------------------------------- ### Manual Cache Invalidation (Without Package) Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Demonstrates the manual cache key management and invalidation required without the package. This approach is error-prone and requires remembering to forget every relevant cache key. ```php $posts = Cache::remember('posts:active:page:1', 3600, function () { return Post::where('active', true)->with('comments')->paginate(); }); // And in every observer or event listener… Cache::forget('posts:active:page:1'); // Hope you remembered every key variant! 😅 ``` -------------------------------- ### Graceful Fallback Implementation Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Configure the application to query the database directly if the cache backend becomes unavailable. ```php get(); // If cache unavailable, runs: SELECT * FROM posts WHERE status = 'published' // Logs: "laravel-model-caching: cache read failed, falling back to database" } catch (\Exception $e) { // With fallback enabled, this block is not reached for cache failures } ``` -------------------------------- ### DynamoDB Cache Store Configuration Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Configure the package to use DynamoDB as the cache store by setting environment variables and defining the store in `config/cache.php`. ```php 'stores' => [ 'dynamodb-model' => [ 'driver' => 'dynamodb', 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 'table' => env('AWS_DYNAMODB_CACHE_TABLE', 'cache'), 'endpoint' => env('AWS_DYNAMODB_CACHE_ENDPOINT'), 'attributes' => [ 'key' => 'key', 'value' => 'value', 'expiration' => 'expires_at', ], ], ], ``` -------------------------------- ### Use Array Cache Driver for Testing Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Configure a specific cache store named 'model-test' with the 'array' driver and set the package to use this store. This is helpful for testing cache interactions without actual persistence. ```php config(['cache.stores.model-test' => ['driver' => 'array']]); config(['laravel-model-caching.store' => 'model-test']); ``` -------------------------------- ### Basic Query Caching with first() Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Use the first() method to retrieve the first matching record. This operation is also automatically cached. ```php // first() - retrieves first matching record, cached $post = Post::where('slug', 'my-post')->first(); ``` -------------------------------- ### Enable Graceful Fallback to Database Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Set this environment variable to true to allow the application to query the database directly if the cache backend is unavailable. This prevents exceptions and keeps the application running without caching. ```env MODEL_CACHE_FALLBACK_TO_DB=true ``` -------------------------------- ### Basic Query Caching with all() Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Use the all() method to retrieve all records from a model. This operation is cached. ```php // all() - retrieves all records, cached $allPosts = Post::all(); ``` -------------------------------- ### Extend CachedModel Directly Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Alternatively, extend the `CachedModel` class directly if you do not need a custom base model. ```php where('status', 'published'); } // Local scope with parameter public function scopeOfCategory(Builder $query, int $categoryId): Builder { return $query->where('category_id', $categoryId); } // Local scope with multiple parameters public function scopeCreatedBetween(Builder $query, $start, $end): Builder { return $query->whereBetween('created_at', [$start, $end]); } } // Scopes generate unique cache keys based on parameters $published = Post::published()->get(); // Cached $techPosts = Post::published()->ofCategory(1)->get(); // Different cache key $artPosts = Post::published()->ofCategory(2)->get(); // Different cache key $recentPosts = Post::createdBetween( now()->subWeek(), now() )->get(); // Cached with date parameters in key ``` -------------------------------- ### Default Configuration File Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md The published configuration file `config/laravel-model-caching.php` allows global settings for caching. ```php return [ 'cache-prefix' => '', 'enabled' => env('MODEL_CACHE_ENABLED', true), 'use-database-keying' => env('MODEL_CACHE_USE_DATABASE_KEYING', true), 'store' => env('MODEL_CACHE_STORE'), 'fallback-to-database' => env('MODEL_CACHE_FALLBACK_TO_DB', false), ]; ``` -------------------------------- ### Basic Query Caching with find() Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Use the find() method to retrieve records by their primary key. Both single IDs and arrays of IDs are supported and cached. ```php // find() - retrieves by primary key, cached $post = Post::find(1); $posts = Post::find([1, 2, 3]); // Array of IDs also cached ``` -------------------------------- ### Basic Query Caching with exists() Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Use the exists() method to check for the existence of records matching a query. This check is cached. ```php // exists() - checks existence, cached $exists = Post::where('email', 'test@example.com')->exists(); ``` -------------------------------- ### Set Cache Key Prefixes Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Isolate cache entries for multi-tenant applications by setting global or per-model cache key prefixes. ```php 'tenant-123', ]; // Per-model prefix via property namespace App\Models; use GeneaLabs\LaravelModelCaching\Traits\Cachable; use Illuminate\Database\Eloquent\Model; class TenantPost extends Model { use Cachable; protected $table = 'posts'; protected $cachePrefix = 'tenant-456'; } // Dynamic per-model prefix for multi-tenancy class Post extends Model { use Cachable; public function __construct(array $attributes = []) { parent::__construct($attributes); $this->cachePrefix = 'tenant-' . tenant()->id; } } ``` -------------------------------- ### Testing Configuration Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Adjust caching settings within test suites to ensure isolation and predictable behavior. ```php false]); } // Option 2: Use array driver to test cache behavior itself protected function setUp(): void { parent::setUp(); config(['cache.stores.model-test' => ['driver' => 'array']]); config(['laravel-model-caching.store' => 'model-test']); } // Example test with caching disabled public function test_post_creation() { config(['laravel-model-caching.enabled' => false]); $post = Post::create(['title' => 'Test', 'content' => 'Content']); $this->assertDatabaseHas('posts', ['title' => 'Test']); $this->assertEquals('Test', Post::find($post->id)->title); } ``` -------------------------------- ### Activate Cache Cool-down with Model Default Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Call the `withCacheCooldownSeconds()` method on a model query to activate the cache cool-down period using the model's default duration. ```php // Activate using the model's default (300 seconds) Comment::withCacheCooldownSeconds()->get(); ``` -------------------------------- ### Set Custom Cache Store via Environment Variable Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Specify a dedicated cache store for model caching by setting the `MODEL_CACHE_STORE` environment variable. ```env MODEL_CACHE_STORE=model-cache ``` -------------------------------- ### Set Cache Prefix Globally Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Configure a global cache prefix in your application's config file to isolate cache entries for multi-tenant applications. ```php 'cache-prefix' => 'tenant-123', ``` -------------------------------- ### Basic Query Caching with value() Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Use the value() method to retrieve a single column's value from the first matching record. This is cached. ```php // value() - retrieves single column value, cached $title = Post::where('id', 1)->value('title'); ``` -------------------------------- ### Basic Query Caching with pluck() Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Use the pluck() method to retrieve a list of column values. You can specify the key column for a keyed collection. These operations are cached. ```php // pluck() - retrieves column values as collection, cached $titles = Post::where('status', 'published')->pluck('title'); $titlesKeyed = Post::pluck('title', 'id'); ``` -------------------------------- ### Custom Cache Store Configuration Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Define dedicated cache stores in config/cache.php to isolate model caching from the main application cache. ```php [ 'model-cache' => [ 'driver' => 'redis', 'connection' => 'model-cache', 'lock_connection' => 'default', ], ], // .env // MODEL_CACHE_STORE=model-cache // For DynamoDB 'stores' => [ 'dynamodb-model' => [ 'driver' => 'dynamodb', 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 'table' => env('AWS_DYNAMODB_CACHE_TABLE', 'cache'), 'endpoint' => env('AWS_DYNAMODB_CACHE_ENDPOINT'), 'attributes' => [ 'key' => 'key', 'value' => 'value', 'expiration' => 'expires_at', ], ], ], // .env for DynamoDB // MODEL_CACHE_STORE=dynamodb-model // AWS_ACCESS_KEY_ID=your-access-key // AWS_SECRET_ACCESS_KEY=your-secret-key // AWS_DEFAULT_REGION=us-east-1 // AWS_DYNAMODB_CACHE_TABLE=cache ``` -------------------------------- ### Manual Cache Flushing Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Clear model caches using Artisan commands, the ModelCache facade, or directly on model instances. ```php flushCache(); // Flush with custom tags $post->flushCache(['custom-tag-1', 'custom-tag-2']); ``` -------------------------------- ### Implement Custom Query Builder with Caching Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Extend the Eloquent Builder to define custom methods and use the Cachable trait in your model. Include the @mixin annotation for proper IDE and static analysis support. ```php where('status', 'published'); } public function featured() { return $this->where('featured', true); } public function byCategory(int $categoryId) { return $this->where('category_id', $categoryId); } } // Model using custom builder with caching class Post extends Model { use Cachable; public function newEloquentBuilder($query) { return new PostQueryBuilder($query); } } // Custom builder methods work seamlessly with caching $posts = Post::published()->featured()->get(); // Cached $posts = Post::byCategory(5)->paginate(10); // Cached // For PHPStan/Larastan compatibility, add @mixin annotation /** * @mixin \GeneaLabs\LaravelModelCaching\CachedBuilder<\Illuminate\Database\Eloquent\Model> * @mixin \App\Models\PostQueryBuilder */ class Post extends Model { use Cachable; } ``` -------------------------------- ### Set Cache Prefix Per Model Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Define a protected property `$cachePrefix` on a model to set a specific cache prefix for that model's cache entries. ```php paginate(perPage: 25, total: 1000); ``` -------------------------------- ### Extend CachedModel Directly Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Alternatively, extend the CachedModel abstract class directly. This provides the same caching functionality without needing to use the trait explicitly. ```php hasMany(Book::class); } public function profile() { return $this->hasOne(Profile::class); } } // All Eloquent operations are cached $authors = Author::all(); $author = Author::find(1); $author = Author::where('email', 'like', '%@example.com')->first(); $authorWithBooks = Author::with('books', 'profile')->get(); ``` -------------------------------- ### Activate Cache Cool-down with Specific Duration Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Override the model's default cache cool-down duration by providing a specific number of seconds to the `withCacheCooldownSeconds()` method. ```php // Or override with a specific duration Comment::withCacheCooldownSeconds(30)->get(); ``` -------------------------------- ### Configure Cache Cool-Down Period Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Define a cool-down duration to prevent immediate cache flushes during high-traffic write operations. ```php get(); // Override with specific duration $comments = Comment::withCacheCooldownSeconds(30)->get(); // 30 seconds // During cool-down window: // - Writes do NOT flush cache immediately // - After window expires, next write triggers flush and cache re-warm $comment = Comment::create(['body' => 'New comment']); // Cache NOT flushed if in cool-down ``` -------------------------------- ### Custom Pagination Caching Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Customize pagination by specifying the per-page count, columns, page name, and current page number. These custom paginated results are also cached. ```php // Custom page name $posts = Post::paginate( perPage: 20, columns: ['*'], pageName: 'blog_page', page: 2 ); ``` -------------------------------- ### Identify Uncached Eloquent Queries Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt These query patterns bypass the caching layer. Use eager loading with 'with()' instead of lazy loading to ensure results are cached. ```php limit(5)->get(); // Queries with pessimistic locking - automatically uncached $post = Post::where('id', 1)->lockForUpdate()->first(); $post = Post::where('id', 1)->sharedLock()->first(); // Lazy-loaded relationships - NOT cached (only eager-loaded via with()) $post = Post::find(1); $comments = $post->comments; // Not cached, use with() instead // Queries with select() clauses - bypass cache $titles = Post::select('title')->get(); // Not cached // Raw expressions may affect caching $posts = Post::selectRaw('title, UPPER(title) as upper_title')->get(); ``` -------------------------------- ### Standard Pagination Caching Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Standard pagination queries are cached, with each page having its own cache key. This improves performance for paginated results. ```php orderBy('created_at', 'desc') ->paginate(15); ``` -------------------------------- ### Declare Default Cache Cool-down Duration Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Set the `$cacheCooldownSeconds` protected property on a model to define the default duration for cache cool-down. This alone does not activate the feature. ```php with('comments')->paginate(); ``` -------------------------------- ### Disable Cache Globally Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Disable caching for specific code blocks using the model-cache helper or the ModelCache facade. ```php runDisabled(function () { return Post::where('status', 'draft')->get(); }); // Using the ModelCache facade use GeneaLabs\LaravelModelCaching\Facades\ModelCache; $freshData = ModelCache::runDisabled(function () { return [ 'posts' => Post::all(), 'authors' => Author::with('books')->get(), ]; }); ``` -------------------------------- ### Disable Cache Globally via Environment Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Set the `MODEL_CACHE_ENABLED` environment variable to `false` to disable caching application-wide. ```dotenv MODEL_CACHE_ENABLED=false ``` -------------------------------- ### Disable Cache Per Query Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Use the `disableCache()` method on a model query to bypass caching for that specific query chain. This is useful in seeders to avoid stale data. ```php $results = MyModel::disableCache()->where('active', true)->get(); ``` -------------------------------- ### Disable Cache for a Block of Code (Service) Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Utilize the `runDisabled()` method on the `model-cache` service to disable caching for a specific block of code. ```php $result = app('model-cache')->runDisabled(function () { return MyModel::get(); }); ``` -------------------------------- ### Add Cachable Trait to Base Model Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Extend this base model to apply caching to all your Eloquent models. Ensure the `Cachable` trait is used. ```php count(); // sum() - cached $totalRevenue = Order::sum('amount'); $monthlyRevenue = Order::whereMonth('created_at', now()->month)->sum('amount'); // avg() - cached $averageOrderValue = Order::avg('amount'); // min() - cached $lowestPrice = Order::min('amount'); // max() - cached $highestPrice = Order::max('amount'); ``` -------------------------------- ### Disable Cache Per Query Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Use the disableCache() scope to bypass the cache for specific database queries. ```php where('status', 'draft')->get(); // Next query uses cache normally $cachedPosts = Post::where('status', 'published')->get(); // Useful in seeders to avoid pulling stale data class PostSeeder extends Seeder { public function run() { Post::disableCache()->truncate(); Post::factory()->count(100)->create(); } } ``` -------------------------------- ### Clear Model Cache via Artisan Command Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Use the modelCache:clear Artisan command to flush the cache for a specific model or all models. This is useful for manual cache management. ```sh php artisan modelCache:clear --model='App\Models\Post' ``` ```sh php artisan modelCache:clear ``` -------------------------------- ### Programmatically Invalidate Model Cache via Facade Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md The ModelCache facade provides methods to invalidate the cache for single or multiple models programmatically. This is an alternative to using Artisan commands. ```php use GeneaLabs\LaravelModelCaching\Facades\ModelCache; // Single model ModelCache::invalidate(App\Models\Post::class); // Multiple models ModelCache::invalidate([ App\Models\Post::class, App\Models\Comment::class, ]); ``` -------------------------------- ### Disable Model Caching in Tests Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md Configure the package to disable model caching entirely within your test suite by setting the 'enabled' configuration option to false. This is useful for isolating tests from caching behavior. ```php config(['laravel-model-caching.enabled' => false]); ``` -------------------------------- ### Add Cachable Trait to Base Model Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Add the Cachable trait to a base model to enable automatic caching for all extending models. This is the recommended approach for applying caching across your application. ```php hasMany(Comment::class); } public function tags() { return $this->belongsToMany(Tag::class); } } class Comment extends BaseModel { protected $fillable = ['body', 'post_id']; public function post() { return $this->belongsTo(Post::class); } } // Usage - all queries are automatically cached and invalidated $posts = Post::where('published', true) ->with('comments', 'tags') ->latest() ->paginate(15); // When a post is updated, cache is automatically flushed $post = Post::find(1); $post->update(['title' => 'Updated Title']); ``` -------------------------------- ### Handle Increment and Decrement Cache Invalidation Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Increment and decrement operations on models automatically invalidate the cache to ensure subsequent queries retrieve fresh data. ```php increment('views'); Post::where('id', 1)->increment('views', 5); // increment with additional updates Post::where('id', 1)->increment('views', 1, [ 'last_viewed_at' => now() ]); // decrement - invalidates cache Product::where('id', 1)->decrement('stock'); Product::where('id', 1)->decrement('stock', 10); // decrement with additional updates Product::where('id', 1)->decrement('stock', 1, [ 'last_sold_at' => now() ]); // Subsequent queries get fresh cached data $freshPost = Post::find(1); $freshProduct = Product::find(1); ``` -------------------------------- ### Add @mixin for Static Analysis Source: https://github.com/mikebronner/laravel-model-caching/blob/master/README.md When using the Cachable trait, add a @mixin annotation to your model to help static analysis tools like PHPStan correctly infer methods from the CachedBuilder. This resolves 'undefined method' errors. ```php use GeneaLabs\LaravelModelCaching\Traits\Cachable; use Illuminate\Database\Eloquent\Model; /** * @mixin \GeneaLabs\LaravelModelCaching\CachedBuilder<\Illuminate\Database\Eloquent\Model> */ class Post extends Model { use Cachable; } ``` -------------------------------- ### Manage BelongsToMany Pivot Caching Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Pivot operations like attach, detach, sync, and updateExistingPivot automatically trigger cache invalidation. ```php tags()->attach([1, 2, 3]); // attach with pivot data $post->tags()->attach([ 1 => ['added_by' => auth()->id()], 2 => ['added_by' => auth()->id()], ]); // detach - flushes caches $post->tags()->detach([1, 2]); $post->tags()->detach(); // Detach all // sync - flushes caches $post->tags()->sync([1, 2, 3]); // sync without detaching $post->tags()->syncWithoutDetaching([4, 5]); // updateExistingPivot - flushes caches $post->tags()->updateExistingPivot(1, ['featured' => true]); // All subsequent queries return fresh cached data $freshPost = Post::with('tags')->find(1); ``` -------------------------------- ### Cache Eager Loaded Relationships Source: https://context7.com/mikebronner/laravel-model-caching/llms.txt Eager-loaded relationships are cached alongside the parent query. Cache invalidation occurs when any related model is modified. ```php get(); // Nested eager loading $authors = Author::with(['books.publisher', 'books.comments'])->get(); // Constrained eager loading $authors = Author::with(['books' => function ($query) { $query->where('published', true) ->orderBy('title'); }])->get(); // Multiple relationship types $posts = Post::with([ 'author', // BelongsTo 'comments', // HasMany (morphMany) 'tags', // BelongsToMany 'image' // MorphOne ])->where('featured', true)->get(); // When any related model changes, relevant cache is invalidated $author = Author::first(); $author->books()->create(['title' => 'New Book']); // Flushes Author and Book caches ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.