Install the Package
composer require cache/psr-6-doctrine-bridge
Ensure you already have a PSR-6 cache pool (e.g., symfony/cache, predis/predis, or stash/stash) configured in your Laravel app.
Register the Bridge
In config/cache.php, extend the stores array to include a Doctrine-compatible cache:
'stores' => [
'doctrine' => [
'driver' => 'psr6',
'pool' => 'default', // or a custom PSR-6 pool name
],
],
Bind the bridge in a service provider:
use Cache\Bridge\Doctrine\DoctrineCacheBridge;
use Psr\Cache\CacheItemPoolInterface;
$this->app->bind(DoctrineCacheBridge::class, function ($app) {
$pool = $app['cache']->driver('doctrine')->getPool();
return new DoctrineCacheBridge($pool);
});
First Use Case
Replace a Doctrine Cache instance (e.g., in a repository or service) with the bridge:
use Doctrine\Common\Cache\Cache;
use Cache\Bridge\Doctrine\DoctrineCacheBridge;
class UserRepository {
private Cache $cache;
public function __construct(DoctrineCacheBridge $cache) {
$this->cache = $cache;
}
public function getUser($id) {
$key = "user:{$id}";
if (!$this->cache->contains($key)) {
// Fetch from DB and save to cache
$this->cache->save($key, $user);
}
return $this->cache->fetch($key);
}
}
Leveraging PSR-6 Features Use PSR-6-specific features (e.g., tags, expiration) via the underlying pool:
$item = $pool->getItem('key');
$item->setTags(['users', 'admin']);
$item->expiresAfter(3600);
$pool->save($item);
The bridge automatically maps these to Doctrine’s Cache interface.
Dependency Injection Prefer constructor injection for testability:
public function __construct(DoctrineCacheBridge $cache) {}
Avoid static calls or global cache instances.
Cache Invalidation
Combine PSR-6 tags with Doctrine’s delete():
// Delete all items tagged 'users'
$pool->deleteItems($pool->getMetadataBag()->getItemsByTag('users'));
Fallback Strategies
Wrap the bridge in a fallback cache (e.g., Cache\Adapter\FallbackCache) for resilience:
$fallback = new FallbackCache([
new DoctrineCacheBridge($pool),
new ArrayCache(), // Fallback to in-memory
]);
Doctrine\Common\Cache\FilesystemCache or ApcuCache with the bridge.redis, database) for unified caching.DoctrineCacheBridge or use Psr6CacheItemPool implementations like Cache\Adapter\ArrayAdapter for unit tests.Tagging Limitations
The bridge does not expose PSR-6 tags directly in the Doctrine\Common\Cache\Cache interface. Workaround:
// Manually manage tags via the underlying PSR-6 pool
$pool->getItem('key')->setTags(['tag1', 'tag2']);
Serialization Issues
Doctrine’s Cache expects serialized data, but PSR-6 pools may handle serialization differently. Ensure your data is serializable or use a custom CacheItem serializer.
Expiration Mismatch
PSR-6 uses expiresAfter() (seconds), while Doctrine’s save() uses lifetime (seconds). The bridge handles this internally, but debug expiration issues by inspecting the underlying pool.
Thread Safety
PSR-6 pools are thread-safe, but Doctrine’s Cache implementations may not be. Ensure your PSR-6 pool (e.g., Redis, APCu) is configured for concurrent access.
getItem('key')->isHit() to debug PSR-6-specific behavior.$bridge = new DoctrineCacheBridge($pool);
$bridge->setLogger(new \Monolog\Logger('cache'));
Cache is strict about key types).Custom Cache Item Pool
Extend DoctrineCacheBridge to add metadata or logging:
class CustomDoctrineCacheBridge extends DoctrineCacheBridge {
public function fetchWithMetadata($key) {
$item = $this->pool->getItem($key);
return [
'data' => $item->get(),
'tags' => $item->getTags(),
];
}
}
PSR-16 Integration
Combine with Psr\SimpleCache\CacheInterface via Cache\Adapter\Psr6SimpleCacheAdapter for a unified API.
Cache Warmers
Use PSR-6’s getItems() to preload cache during bootstrapping:
$pool->getItems(['key1', 'key2']); // Loads all items at once
How can I help you explore Laravel packages today?