You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony 7中如何自动注入兼容双接口的自定义缓存池?

Symfony 7 自定义缓存池同时调用两类缓存方法的注入方案

问题背景

已在Symfony 7中定义自定义Redis标签缓存池:

framework:
    cache:
        default_redis_provider: '%env(resolve:REDIS_URL)%'
        pools:
            cache.score:
                adapter: cache.adapter.redis_tag_aware

根据文档使用CacheInterface $cacheScore自动注入时,仅能调用CacheInterface的方法,无法使用Psr\Cache\CacheItemPoolInterface提供的getItem()等方法。而缓存适配器同时实现了这两个接口,需要同时使用两类方法,且要求仅修改cache.yaml即可切换适配器,无需改动业务代码。

尝试直接注入AbstractAdapter或RedisTagAwareAdapter均抛出依赖注入异常。

附symfony console debug:autowiring cache输出:

Autowirable Types
=================

The following classes & interfaces can be used as type-hints when autowiring:
(only showing classes/interfaces matching cache)

CacheItemPoolInterface generates CacheItemInterface objects.
Psr\Cache\CacheItemPoolInterface - alias:cache.app
Psr\Cache\CacheItemPoolInterface $cacheScore - target:cache.score    

Covers most simple to advanced caching needs.
Symfony\Contracts\Cache\CacheInterface - alias:cache.app
Symfony\Contracts\Cache\CacheInterface $cacheScore - target:cache.score

Allows invalidating cached items using tags.
Symfony\Contracts\Cache\TagAwareCacheInterface - alias:cache.app.taggable
Symfony\Contracts\Cache\TagAwareCacheInterface $cacheScore - target:cache.score

解决方案

利用Symfony自动注入的参数名匹配特性,通过以下两种方式即可同时调用两类方法,且满足适配器灵活切换的需求:

方案1:双参数注入

在服务构造函数中同时注入CacheInterface和Psr\Cache\CacheItemPoolInterface,通过参数名$cacheScore匹配目标缓存池:

use Psr\Cache\CacheItemPoolInterface;
use Symfony\Contracts\Cache\CacheInterface;

class YourBusinessService
{
    private CacheInterface $cache;
    private CacheItemPoolInterface $cachePool;

    public function __construct(
        CacheInterface $cacheScore,
        CacheItemPoolInterface $cacheScore
    ) {
        $this->cache = $cacheScore;
        $this->cachePool = $cacheScore;
    }

    public function handleBusinessLogic()
    {
        // 使用Symfony缓存契约的get方法
        $cachedValue = $this->cache->get('user_score', function () {
            return $this->calculateScore();
        });

        // 使用PSR-6规范的getItem方法
        $cacheItem = $this->cachePool->getItem('user_score');
        if (!$cacheItem->isHit()) {
            $cacheItem->set($this->calculateScore());
            $this->cachePool->save($cacheItem);
        }
    }

    private function calculateScore()
    {
        // 业务逻辑计算
        return 95;
    }
}

方案2:单参数+类型断言

仅注入一个接口实例,通过类型断言确保它同时实现另一接口:

use Psr\Cache\CacheItemPoolInterface;
use Symfony\Contracts\Cache\CacheInterface;

class YourBusinessService
{
    private CacheInterface $cache;
    private CacheItemPoolInterface $cachePool;

    public function __construct(CacheInterface $cacheScore)
    {
        $this->cache = $cacheScore;
        // 断言实例同时实现CacheItemPoolInterface
        assert($cacheScore instanceof CacheItemPoolInterface);
        $this->cachePool = $cacheScore;
    }

    // 业务方法同上
}

优势说明

两种方案均无需修改services.yaml,仅通过自动注入的参数名匹配即可绑定目标缓存池。后续若需切换适配器(如从Redis改为文件缓存),只需修改cache.yaml中的adapter配置,业务代码无需任何改动,完全符合需求。

内容的提问来源于stack exchange,提问作者michnovka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 15:45:23