Symfony FilesystemTagAwareAdapter添加标签后无法读取缓存项问题
解决PHPUnit测试中FilesystemTagAwareAdapter加标签后缓存无法读取的问题
针对你在PHP 8.1、Windows 10环境下遇到的问题——PHPUnit测试中手动使用FilesystemTagAwareAdapter时,加标签的缓存项返回null,但通过KernelTestCase获取容器里的cache.app.taggable服务却正常,核心原因是手动实例化时缺少标签缓存池的独立配置,结合Windows环境的路径特性导致标签关联数据无法正确读写。以下是具体解决步骤:
1. 不要直接用FilesystemTagAwareAdapter的简化实例化
FilesystemTagAwareAdapter本质是TagAwareAdapter的封装,需要两个独立的缓存池:一个存储实际缓存数据,另一个存储标签与缓存项的关联关系。如果手动实例化时只传入主缓存的参数,标签池会默认复用主缓存的目录和命名空间,导致标签数据和业务缓存互相覆盖,或者Windows下路径解析异常。
正确实例化方式:
use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\Cache\Adapter\TagAwareAdapter; // 为数据和标签分别指定独立的缓存目录 $cacheDir = __DIR__ . '/../var/test_cache_data'; $tagCacheDir = __DIR__ . '/../var/test_cache_tags'; // 确保目录存在且可写 $fs = new \Symfony\Component\Filesystem\Filesystem(); $fs->mkdir($cacheDir, 0777); $fs->mkdir($tagCacheDir, 0777); // 创建两个独立的FilesystemAdapter $mainAdapter = new FilesystemAdapter( 'app_cache', 0, null, ['directory' => $cacheDir] ); $tagAdapter = new FilesystemAdapter( 'app_tags', 0, null, ['directory' => $tagCacheDir] ); // 组合成TagAwareAdapter(替代FilesystemTagAwareAdapter的简化调用) $adapter = new TagAwareAdapter($mainAdapter, $tagAdapter);
2. 避免Windows路径与权限问题
Windows的文件系统大小写不敏感,且系统临时目录(sys_get_temp_dir())可能存在权限限制,导致标签缓存文件无法正常写入。建议:
- 使用项目内的测试专属缓存目录,而非系统临时目录
- 确保目录权限为0777(测试环境下无需过于严格)
3. 测试用例间的缓存隔离
如果测试用例之间共享缓存目录,残留的旧标签数据可能导致读取异常。在setUp或tearDown方法中清理缓存:
protected function setUp(): void { parent::setUp(); $fs = new \Symfony\Component\Filesystem\Filesystem(); $fs->remove(__DIR__ . '/../var/test_cache_data'); $fs->remove(__DIR__ . '/../var/test_cache_tags'); }
4. 优先使用容器中的taggable缓存服务
如果测试场景允许,直接通过KernelTestCase获取容器里的cache.app.taggable服务,避免手动实例化的配置错误:
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; class MyCacheTest extends KernelTestCase { public function testTaggableCache(): void { self::bootKernel(); $cache = self::getContainer()->get('cache.app.taggable'); // 执行缓存读写操作 $item = $cache->getItem('test_key'); $item->tag('msc')->set('test_value'); $cache->save($item); $fetchedItem = $cache->getItem('test_key'); $this->assertEquals('test_value', $fetchedItem->get()); } }
内容的提问来源于stack exchange,提问作者OVG
相关产品推荐
相关产品推荐

