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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:24:52