From f87a9571e459a77e32327a2416081d2723585a45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20M=C3=A4ki?= Date: Thu, 11 Jun 2026 23:53:46 +0200 Subject: [PATCH] Fix README usage examples, add CI badges, document README-sync convention --- CLAUDE.md | 1 + README.md | 31 ++++++++++++++++++++----------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 70c9676..015fad9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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/`. diff --git a/README.md b/README.md index 2e54099..7d457b5 100644 --- a/README.md +++ b/README.md @@ -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: @@ -41,14 +45,16 @@ namespace My\Services; use Trm42\CacheDecorator\CacheDecorator; +/** @extends CacheDecorator */ 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 @@ -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 */ class CachedReportingService extends CacheDecorator { - protected $prefix_key = 'reports'; + protected ?string $prefix_key = 'reports'; + #[\Override] protected function decoratedClass(): ?string { return ReportingService::class; @@ -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 @@ -118,14 +126,15 @@ namespace My\Repositories; use Trm42\CacheDecorator\RepositoryCacheDecorator; +/** @extends RepositoryCacheDecorator */ 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;