PHP code example of trm42 / cache-decorator

1. Go to this page and download the library: Download trm42/cache-decorator library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

trm42 / cache-decorator example snippets


namespace something\nice;

class CachedReportingService {

    protected $service;
    protected $cache;

    public function __construct(ReportingService $service, Cache $cache) {
        $this->service = $service;
        $this->cache = $cache;
    }

    public function dailyTotals($date)
    {
        $key = 'daily-totals-' . $date;
        if (!$this->cache->has($key)) {
            $results = $this->service->dailyTotals($date);
            $this->cache->save($key, $results);
        } else {
            $results = $this->cache->get($key);
        }

        return $results;
    }

    // ... and the same for every other method
}

namespace My\Services;

use Trm42\CacheDecorator\CacheDecorator;

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

    protected ?string $prefix_key = 'reports';
    protected array $excludes = ['recompute']; // methods listed here are never cached
}

$cached = new CachedReportingService(new ReportingService);

$cached->dailyTotals('2026-05-12'); // cache miss → calls ReportingService::dailyTotals
$cached->dailyTotals('2026-05-12'); // cache hit  → returns the cached value

$cached = (new CachedReportingService(new ReportingService))
    ->ttl(600)                 // TTL in seconds (also DateInterval / DateTimeInterface / null)
    ->prefix('reports')        // cache-key prefix
    ->withTags(['reports'])    // cache tags (tag-capable store)
    ->tagCleaners(['recompute']) // methods that flush the tags after running
    ->exclude('debugDump');    // never cache these methods

$cached->totals(); // configured and cached

$cached->reportFor($user);              // User implements UrlRoutable → keyed by getRouteKey()
$cached->reportFor($sameUserReloaded);  // same route key → cache hit

interface ReportingContract {
    public function forMonth(string $month): static; // fluent
    public function totals(): array;                  // cacheable
}

class ReportingService implements ReportingContract { /* ... */ }

/** @extends CacheDecorator<ReportingService> */
class CachedReportingService extends CacheDecorator {
    protected ?string $prefix_key = 'reports';
    protected array $excludes = ['forMonth']; // fluent method stays on the forward path
}

$cached = new CachedReportingService(new ReportingService);
$cached->forMonth('2026-05')->totals(); // forMonth() returns the decorator; totals() is cached

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

    #[\Override]
    protected function decoratedClass(): ?string
    {
        return ReportingService::class;
    }
}

$cached = new CachedReportingService;

public function findByX($x)
{
    $key = $this->generateCacheKey(__FUNCTION__, compact('x'));

    $res = $this->getCache($key);

    if ($res === $this->cacheMiss()) {
        $res = $this->decorated->findX($x);

        $this->putCache($key, $res);
    }

    return $res;
}

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

use Trm42\CacheDecorator\Exceptions\CacheDecoratorException;

try {
    $cached->dailyTotals('2026-05-12');
} catch (CacheDecoratorException $e) {
    // catches MissingDecoratedObjectException and UndefinedMethodException alike
    report($e);
}

namespace My\Repositories;

use Trm42\CacheDecorator\RepositoryCacheDecorator;

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

    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;
    }

    // optional per-method override
    public function findByX($x)
    {
        $key = $this->generateCacheKey(__FUNCTION__, compact('x'));

        $res = $this->getCache($key);

        if ($res === $this->cacheMiss()) {
            $res = $this->decorated->findX($x);
            $this->putCache($key, $res);
        }

        return $res;
    }
}
diff
-use Trm42\CacheDecorator\CacheDecorator;
+use Trm42\CacheDecorator\RepositoryCacheDecorator;

-class CachedUserRepository extends CacheDecorator {
+class CachedUserRepository extends RepositoryCacheDecorator {

-    public function repository()
+    protected function decoratedClass(): ?string
     {
         return UserRepository::class;
     }

-    $res = $this->repository->findX($x);
+    $res = $this->decorated->findX($x);