Vortos
Cache

Cache

PSR-16 cache with tag-based invalidation — Redis for production, InMemory for tests, ArrayAdapter for request-scoped memoization.

Cache

Vortos cache provides PSR-16 CacheInterface extended with tag-based invalidation via TaggedCacheInterface. Three adapters cover every scenario — Redis for production persistence, InMemoryAdapter for tests, and ArrayAdapter for within-request memoization.

Three Adapters

AdapterScopeTTLTagsUse Case
RedisAdapterCross-request, cross-workerRespectedSupportedProduction
InMemoryAdapterPer-processRespected (lazy expiry)SupportedTests
ArrayAdapterPer-request onlyIgnoredSupportedRequest memoization

Installation

composer require vortos/vortos-cache

Package Registration

bootstrap/app.php
use Vortos\Cache\DependencyInjection\CachePackage;

$packages = [
    new CachePackage(),  // MUST be first — other packages depend on CacheInterface
    new MessagingPackage(),
    new CqrsPackage(),
    // ...
];

CachePackage Must Be First

CachePackage must be the first package registered. MessagingPackage (idempotency) and CqrsPackage (command idempotency) both depend on CacheInterface being registered before they load.

Environment Variables

REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=        # optional
APP_ENV=prod           # used in key prefix to prevent collisions

Configuration

config/cache.php
use Vortos\Cache\DependencyInjection\VortosCacheConfig;

return static function (VortosCacheConfig $config): void {
    $config
        ->dsn(sprintf('redis://%s:%s', $_ENV['REDIS_HOST'], $_ENV['REDIS_PORT']))
        ->prefix($_ENV['APP_ENV'] . '_myapp_')  // always include env + app name
        ->defaultTtl(3600);                     // 1 hour default
};

All settings have defaults — no config file is required for zero-config startup.

All Config Options

MethodDefaultDescription
->driver(string)RedisAdapter::classFQCN of TaggedCacheInterface implementation
->dsn(string)redis://redis:6379Redis connection DSN
->prefix(string)vortos_Key prefix — always include APP_ENV
->defaultTtl(int)3600Default TTL in seconds for keys without explicit TTL

Swap Driver Per Environment

config/test/cache.php
use Vortos\Cache\Adapter\InMemoryAdapter;

return static function (VortosCacheConfig $config): void {
    $config->driver(InMemoryAdapter::class);
    // Redis connection not registered when InMemory is the driver
};

Services Registered

\Redis::class           — only when driver = RedisAdapter (lazy connection)
RedisAdapter::class     — always registered, injectable by class
InMemoryAdapter::class  — always registered, injectable by class
ArrayAdapter::class     — always registered, public (needed by Runner::cleanUp)
CacheInterface          — alias → configured driver
TaggedCacheInterface    — alias → configured driver

Both CacheInterface and TaggedCacheInterface point to the configured driver — swapping the driver in config routes all injections automatically.

Inject the Cache

use Psr\SimpleCache\CacheInterface;
use Vortos\Cache\Contract\TaggedCacheInterface;

// Inject via interface — gets the configured driver
final class MyService
{
    public function __construct(private TaggedCacheInterface $cache) {}
}

// Inject a specific adapter directly
use Vortos\Cache\Adapter\ArrayAdapter;

final class AuthMiddleware
{
    public function __construct(private ArrayAdapter $arrayAdapter) {}
}

Module Overview

On this page