Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ The classes use Laravel facades (`Cache`, `Config`, `Log` from `Illuminate\Suppo
- Inside custom method overrides, reference the inner object as `$this->decorated`.
- To customize caching for a single method, override it in the subclass and use the protected helpers `generateCacheKey()`, `getCache()`, `putCache()` (see README example).
- TTL values throughout (subclass `$ttl`, `cache_decorator.ttl` / `repository_cache.ttl` config, calls to `setTtl()`) are in seconds — this changed from "minutes" when upgrading from the Laravel 5.x line.
- **Keep the README in sync.** Any `src/` change that affects the main classes (`CacheDecorator`, `RepositoryCacheDecorator`, `ServiceProvider`) and their public-facing surface — property types/signatures, subclassing conventions, config keys, the `__call` flow, or anything a user copy-pastes from a usage example — must be documented in `README.md` as part of the same change. This is a core part of the package's DX and ease of use: the README usage examples should compile and run cleanly against the current code and follow the same conventions as the test stubs under `src/tests/Stubs/`.
31 changes: 20 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# (Magical) Cache Decorator for Laravel

[![Tests](https://github.com/trm42/CacheDecorator/actions/workflows/run-tests.yml/badge.svg)](https://github.com/trm42/CacheDecorator/actions/workflows/run-tests.yml)
[![PHPStan](https://github.com/trm42/CacheDecorator/actions/workflows/phpstan.yml/badge.svg)](https://github.com/trm42/CacheDecorator/actions/workflows/phpstan.yml)
[![Code style](https://github.com/trm42/CacheDecorator/actions/workflows/fix-php-code-style-issues.yml/badge.svg)](https://github.com/trm42/CacheDecorator/actions/workflows/fix-php-code-style-issues.yml)

A transparent caching decorator for any Laravel-side class — services, API clients, query objects, repositories, you name it. Sub-class `CacheDecorator`, point it at the object you want to cache, and every public method call is automatically cached on first run and served from the cache on subsequent calls.

Stop writing boilerplate like this for every class whose results you want to cache:
Expand Down Expand Up @@ -41,14 +45,16 @@ namespace My\Services;

use Trm42\CacheDecorator\CacheDecorator;

/** @extends CacheDecorator<ReportingService> */
class CachedReportingService extends CacheDecorator {

protected $ttl = 300; // cache ttl in seconds (or a DateInterval / DateTimeInterface)
protected $prefix_key = 'reports';
protected $excludes = ['recompute']; // methods listed here are never cached
protected ?string $prefix_key = 'reports';
protected array $excludes = ['recompute']; // methods listed here are never cached
}
```

> **TTL is read from config**, not from a `$ttl` property. The constructor calls `getConfig()`, which overwrites `$ttl` from `cache_decorator.ttl` (default `300` seconds; `repository_cache.ttl` for `RepositoryCacheDecorator`). To override it per-instance, call `setTtl(...)` after construction (e.g. in your subclass constructor) — it accepts `int` seconds, a `DateInterval`, a `DateTimeInterface`, or `null` to bypass the cache entirely.

…and use it like this:

```PHP
Expand All @@ -65,9 +71,11 @@ The decorator forwards any method not listed in `$excludes` to the underlying ob
If you don't want to wire the inner instance yourself, override `decoratedClass()` to return its FQCN and you can construct the decorator with no arguments:

```PHP
/** @extends CacheDecorator<ReportingService> */
class CachedReportingService extends CacheDecorator {
protected $prefix_key = 'reports';
protected ?string $prefix_key = 'reports';

#[\Override]
protected function decoratedClass(): ?string
{
return ReportingService::class;
Expand Down Expand Up @@ -105,8 +113,8 @@ public function findByX($x)
If your cache driver supports tags, declare which methods invalidate the tag bucket:

```PHP
protected $tag_cleaners = ['recompute'];
protected $tags = ['reports'];
protected array $tag_cleaners = ['recompute'];
protected array $tags = ['reports'];
```

## Using with repositories
Expand All @@ -118,14 +126,15 @@ namespace My\Repositories;

use Trm42\CacheDecorator\RepositoryCacheDecorator;

/** @extends RepositoryCacheDecorator<UserRepository> */
class CachedUserRepository extends RepositoryCacheDecorator {

protected $ttl = 300;
protected $prefix_key = 'users';
protected $excludes = ['allWithoutCache'];
protected $tag_cleaners = ['create'];
protected $tags = ['users'];
protected ?string $prefix_key = 'users';
protected array $excludes = ['allWithoutCache'];
protected array $tag_cleaners = ['create'];
protected array $tags = ['users'];

#[\Override]
protected function decoratedClass(): ?string
{
return UserRepository::class;
Expand Down