PHP8.3下Laminas Cache与Doctrine集成:缓存值存为字符串问题排查
Doctrine ORM v6 + Laminas Cache 缓存异常排查与适配方案
环境与依赖
PHP 8.3 纯净环境,使用以下Composer包:
"doctrine/doctrine-orm-module": "^6.1", "doctrine/doctrine-module": "^6.1", "laminas/laminas-cache": "^3.12", "laminas/laminas-cache-storage-adapter-redis": "^2.9"
配置信息
... 'service_manager' => [ 'factories' => [ 'Service\Redis' => Service\Factory\RedisFactory::class, ], ], 'doctrine' => [ 'connection' => [ 'orm_default' => [ 'driverClass' => \Doctrine\DBAL\Driver\PDO\MySQL\Driver::class, 'params' => [ 'host' => 'localhost', 'port' => '3306', 'user' => 'db_user', 'password' => 'my_password', 'dbname' => 'db_skeleton', 'charset' => 'utf8mb4', ], ], ], 'driver' => [ 'annotation_driver' => [ 'class' => AttributeDriver::class, 'cache' => 'array', 'paths' => [ __DIR__ . '/../src/Entity', ], ], 'orm_default' => [ 'drivers' => [ 'Application\Entity' => 'annotation_driver', ], ], ], 'cache' => [ 'redis' => [ 'namespace' => 'skeleton', 'instance' => 'Service\Redis', ], ], 'configuration' => [ 'orm_default' => [ 'result_cache' => 'redis', 'query_cache' => 'redis', 'metadata_cache' => 'redis', 'hydration_cache' => 'redis', 'generate_proxies' => false, ] ] ], ...
Redis工厂类代码
<?php namespace Application\Service\Factory; use Laminas\Cache\Storage\Adapter\Redis; use Psr\Container\ContainerInterface; class RedisFactory { public function __invoke(ContainerInterface $container, $requestedName, array $options = null) { $redis = new Redis([ 'server' => ['host' => '127.0.0.1', 'port' => 6379], ]); return $redis; } }
问题现象
可正常连接Redis实例并生成缓存键,但缓存值被存储为"Array"和"Object"字符串,导致缓存无法命中,查询重复执行。
问题分析与解决
核心原因
Laminas Cache的Redis适配器默认未配置序列化插件,数组/对象直接被转换为字符串(如PHP中直接输出数组会得到"Array"),无法完成正确的序列化/反序列化,导致缓存内容无效。
修复步骤
1. 为Redis适配器添加序列化插件
修改RedisFactory,集成Laminas Cache的序列化插件,确保数组/对象能正确序列化存储:
<?php namespace Application\Service\Factory; use Laminas\Cache\Storage\Adapter\Redis; use Laminas\Cache\Storage\Plugin\Serializer; use Psr\Container\ContainerInterface; class RedisFactory { public function __invoke(ContainerInterface $container, $requestedName, array $options = null) { $redis = new Redis([ 'server' => ['host' => '127.0.0.1', 'port' => 6379], ]); // 添加序列化插件,处理数组/对象的序列化与反序列化 $redis->addPlugin(new Serializer()); return $redis; } }
2. 适配Doctrine ORM v6的缓存接口要求
Doctrine ORM v6推荐使用PSR-6标准缓存接口,直接修改Doctrine配置,将缓存类型指定为psr6并关联Redis实例:
'doctrine' => [ // ... 其他配置 'configuration' => [ 'orm_default' => [ 'result_cache' => [ 'type' => 'psr6', 'pool' => 'Service\Redis', ], 'query_cache' => [ 'type' => 'psr6', 'pool' => 'Service\Redis', ], 'metadata_cache' => [ 'type' => 'psr6', 'pool' => 'Service\Redis', ], 'hydration_cache' => [ 'type' => 'psr6', 'pool' => 'Service\Redis', ], 'generate_proxies' => false, ] ] ],
3. 可选:使用官方适配包
若需要更完善的Doctrine集成,可安装laminas/laminas-cache-doctrine包,它提供了专门的桥接器适配Doctrine缓存接口:
composer require laminas/laminas-cache-doctrine
之后配置Doctrine缓存使用该桥接器:
'service_manager' => [ 'factories' => [ 'Service\Redis' => Service\Factory\RedisFactory::class, 'Doctrine\Common\Cache\Cache' => Laminas\Cache\Doctrine\CacheFactory::class, ], ], 'doctrine' => [ 'cache' => [ 'redis' => [ 'namespace' => 'skeleton', 'instance' => 'Doctrine\Common\Cache\Cache', ], ], // ... 其他配置 ],
内容的提问来源于stack exchange,提问作者smozgur
相关产品推荐
相关产品推荐

