Weave Code
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

Rememberable Laravel Package

watson/rememberable

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require watson/rememberable
    

    Add the trait to your base model (e.g., app/Models/Model.php or app/Models/Concerns/Rememberable.php):

    use Watson\Rememberable\Rememberable;
    
    class Model extends Illuminate\Database\Eloquent\Model
    {
        use Rememberable;
    }
    

    Or apply it selectively to specific models.

  2. First Use Case: Cache a query result for a model relationship (e.g., posts for a User):

    $user = User::find(1);
    $cachedPosts = $user->remember(now()->addHour())->posts()->get();
    

    The query will now be cached for 1 hour.

  3. Where to Look First:

    • README for basic syntax and examples.
    • Source Code for advanced usage (e.g., Rememberable trait internals).
    • Laravel’s query caching docs for context on how caching works under the hood.

Implementation Patterns

Usage Patterns

  1. Caching Relationships: Cache eager-loaded relationships to avoid N+1 queries:

    $user = User::with(['posts' => function ($query) {
        $query->remember(now()->addDays(7));
    }])->find(1);
    
  2. Conditional Caching: Dynamically enable caching based on logic (e.g., skip caching for admin users):

    $user = User::find(1);
    if (!$user->isAdmin()) {
        $user->remember(now()->addHour())->posts()->get();
    } else {
        $user->posts()->fresh()->get(); // Bypass cache
    }
    
  3. Global Defaults: Set a default cache duration in config/cache.php or via a model’s boot() method:

    class User extends Model
    {
        protected static $rememberDuration = now()->addDays(1);
    
        use Rememberable;
    }
    

    Now all queries on User will cache for 1 day unless overridden.

  4. Scopes and Local Scopes: Cache scoped queries:

    class User extends Model
    {
        public function scopeActive($query)
        {
            return $query->remember(now()->addMinutes(30))->where('active', true);
        }
    }
    
  5. Manual Cache Invalidation: Invalidate cache for a specific model or relationship:

    $user = User::find(1);
    $user->posts()->remember(now()->addHour())->get();
    // Later...
    $user->posts()->remember()->get(); // Forces fresh query
    

Workflows

  1. API Endpoints: Cache responses for read-heavy endpoints (e.g., dashboards):

    Route::get('/dashboard', function () {
        return User::find(auth()->id())
            ->remember(now()->addMinutes(15))
            ->posts()
            ->with('comments')
            ->get();
    });
    
  2. Scheduled Jobs: Use caching to reduce database load during off-peak hours:

    // In a scheduled job
    $popularPosts = Post::popular()->remember(now()->addDays(1))->get();
    
  3. Testing: Disable caching in tests by mocking the trait or using Laravel’s cache helpers:

    $this->app->singleton('cache.store', function () {
        return Cache::store('array');
    });
    

Integration Tips

  1. Cache Stores: Configure the cache driver in .env (e.g., CACHE_DRIVER=redis or CACHE_DRIVER=database). Rememberable uses Laravel’s built-in cache, so leverage existing cache tags or prefixes for organization.

  2. Cache Tags: Tag cached queries for bulk invalidation (e.g., Cache::tags(['users'])->remember()):

    $user->remember(now()->addHour())->tag(['users'])->posts()->get();
    
  3. Event Listeners: Invalidate cache on model updates:

    class PostUpdatedListener
    {
        public function handle($event)
        {
            Cache::forget("rememberable:{$event->post->user_id}:posts");
        }
    }
    
  4. Laravel Mixins (Laravel 8+): Use mixins to add remember() to all models without modifying base classes:

    Model::macro('remember', function ($duration = null) {
        return (new Rememberable())->remember($duration);
    });
    

Gotchas and Tips

Pitfalls

  1. Cache Key Collisions: Rememberable generates keys like rememberable:{model}:{query_hash}. Ensure unique queries to avoid collisions. For complex queries, manually specify a key:

    $user->remember(now()->addHour(), 'custom:key:posts')->posts()->get();
    
  2. Lazy Loading Issues: Caching relationships may interfere with lazy loading. Prefer eager loading (with()) when caching:

    // Avoid this (lazy loading bypasses cache):
    $user->posts->remember()->first();
    
  3. Time Zone Sensitivity: Cache durations use the server’s time zone. Normalize times (e.g., UTC) for consistency:

    $user->remember(now('UTC')->addHours(1))->posts()->get();
    
  4. Memory Leaks: Long-lived caches (e.g., remember(now()->addYears(1))) can bloat storage. Monitor cache size and set reasonable TTLs.

  5. Soft Deletes: Cached queries ignore soft deletes. Use withTrashed() or manually filter:

    $user->remember()->posts()->whereNull('deleted_at')->get();
    

Debugging

  1. Cache Misses: Check if queries are hitting the database by enabling query logging:

    DB::enableQueryLog();
    $user->remember()->posts()->get();
    dd(DB::getQueryLog()); // Verify no duplicate queries
    
  2. Key Inspection: Inspect generated cache keys to debug issues:

    $key = $user->remember()->posts()->getQuery()->getCacheKey();
    dd(Cache::has($key)); // Check if key exists
    
  3. Cache Store Issues: If caching fails, verify the cache driver is configured and accessible:

    php artisan cache:clear
    php artisan cache:table # If using database driver
    

Tips

  1. Cache Warmup: Pre-load caches during deployment or via a command:

    Artisan::command('cache:warmup', function () {
        User::all()->remember(now()->addDays(7))->posts()->get();
    });
    
  2. Partial Caching: Cache only specific columns to reduce payload size:

    $user->remember()->posts()->select('id', 'title')->get();
    
  3. Fallback Logic: Combine caching with fallback logic for stale data:

    $posts = Cache::remember("user:{$user->id}:posts", now()->addHour(), function () use ($user) {
        return $user->posts()->get()->filter(fn ($post) => $post->isPublished());
    });
    
  4. Environment-Specific Caching: Disable caching in development:

    if (app()->environment('local')) {
        $user->posts()->get(); // Bypass cache
    } else {
        $user->remember()->posts()->get();
    }
    
  5. Testing Cache Behavior: Use Cache::shouldReceive('get')->andReturn(...) in PHPUnit to mock cached responses:

    Cache::shouldReceive('get')
        ->with('rememberable:user:1:posts')
        ->andReturn(collect([new Post()]));
    
  6. Performance Tuning: For high-traffic apps, use a distributed cache (Redis) and monitor hit/miss ratios:

    php artisan cache:config # Check cache stats
    
  7. Custom Cache Tags: Extend the trait to support custom tags:

    class TaggedRememberable extends Rememberable
    {
        public function tag($tags)
        {
            $this->tags = is_array($tags) ? $tags : explode(',', $tags);
            return $this;
        }
    }
    
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.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle