Search by

assertchris / laravel-tagged-cache

assertchris

A fluent tag-aware cache reference helper for Laravel.

Package info

github.com/assertchris/laravel-tagged-cache

pkg:composer/assertchris/laravel-tagged-cache

Statistics

Installs: 17

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0 2026-10-10 19:19 UTC

This package is auto-updated.

Last update: 2026-10-10 19:22:39 UTC


README

One entry point, immutable tags, no boilerplate. Tag-scoped caching for Laravel.

Requirements

  • PHP 8.2+
  • Laravel 10+
  • A tag-compatible cache driver (Redis or Memcached — not the database or file driver)

Installation

composer require assertchris/laravel-tagged-cache

No service provider registration needed.

Concept

TaggedCache::for() binds a set of tags to a derived cache key. Every operation on that reference targets only that key, scoped to those tags. Tags are immutable after construction.

Flushing a tag clears every entry stored under it, regardless of key. That's the main reason to use tags.

Usage

The core pattern — remember on read, flush on write:

use AC\LaravelTaggedCache\TaggedCache;

// Single entry
TaggedCache::for(tags: ['notes'], context: ['id' => $note->id])
    ->remember(now()->addHour(), fn () => $note->toArray());

// List query — full param set becomes the key
TaggedCache::for(tags: ['notes'], context: $request->validated())
    ->remember(now()->addHour(), fn () => Note::paginate()->toArray());

TaggedCache::for(tags: ['notes'])->flush();
TaggedCache::for(tags: ['notes'], context: ['id' => $note->id])->forget();

The flush() call with no context is the pattern to use in model observers — every saved, deleted, and restored hook just flushes the tag.

Other operations
$ref = TaggedCache::for(tags: ['notes'], context: ['id' => $note->id]);

$ref->put($data, now()->addHour());
$ref->forever($data);
$ref->rememberForever(fn () => $data);
$ref->get();
$ref->has();
$ref->missing();
$ref->pull(); // get + delete atomically

$ref->put(0, now()->addDay());
$ref->increment();
$ref->increment(4);
$ref->decrement(2);

Key derivation

The cache key is md5(serialize(ksort($context ?: $tags))).

  • If context is provided, we serialize and hash it.
  • If context is empty, we fall back to $tags.
  • The array is sorted by key before hashing — ['b' => 2, 'a' => 1] and ['a' => 1, 'b' => 2] produce the same key, so passing $request->validated() is safe.

Keys are opaque and never user-facing.

Blocked methods

These methods aren't available on TaggedCache. They'll throw BadMethodCallException:

Blocked method list
Method Reason
tags Would re-scope to different tags, breaking immutability
clear Flushes the entire store, not just tagged entries
setStore Replaces the underlying store for all callers
setDefaultCacheTime Mutates shared TTL state on the underlying repository
setEventDispatcher Mutates shared dispatcher state on the underlying repository

Everything else proxies through __call and gets the derived key prepended automatically.

Full API surface

All available methods
TaggedCache::for(tags: ['tag'], context: ['key' => 'value'])
    ->get(default: null)
    ->has()
    ->missing()
    ->put(value: $data, ttl: now()->addHour())
    ->add(value: $data, ttl: now()->addHour())   // only stores if key doesn't exist
    ->forget()
    ->pull(default: null)
    ->forever(value: $data)
    ->remember(ttl: now()->addHour(), callback: fn () => $data)
    ->rememberForever(callback: fn () => $data)
    ->increment(value: 1)
    ->decrement(value: 1)
    ->touch(ttl: now()->addHour())               // resets TTL without changing value
    ->flush()                                    // flushes entire tag group, key is ignored