CakePHP 查询结果缓存

CakePHP Query results caching

最近我将 CakePHP 3.2 项目移至虚拟主机(CentOSphp 7.0/5.6 都尝试了,OpCache 已启用),发现查询结果缓存不起作用.

我使用导航菜单的默认文件缓存引擎。

$mt = TableRegistry::get('MenuItems');
$menu = $mt->find('active')
           ->select([
                      "MenuItems.id",'Nodes.id','title', 'header', 'route', 'link',
                      'parent_id' => 'Nodes.parent_id' ])
           ->orderAsc('Nodes.num')
           ->cache("sitemenu_MenuItems", 'long')
           ->hydrate(false)
           ->toArray();

我在本地 OpenServerIIS7IIS8 服务器以及其他 Linux 服务器上使用此代码没有问题。

那么,发生了什么:

当我第一次运行编写脚本时,cake从数据库中获取数据并将缓存写入/src/tmp/cache/long/cake_sitemenu__menu_items。文件已像往常一样序列化内容。
但是当我刷新页面时,我看到的结果是空的。

错误或调试日志中没有任何内容。

我试过将缓存键小写,但没有成功。

有什么想法吗?


我添加了测试代码来检查基本缓存本身:

    public function qwe(){
            $data = ['key' => 'value'];
            //Cache::write('test', $data, 'long');
            $result = Cache::read('test', 'long');
            $result[] = 'xxx';
            $this->setJsonResponse($result);
    }

此代码 returns 正确结果。


到目前为止,我发现 Cake\Cache\Egine\FileEngine class 的 read() 方法存在一些问题。第 223 行:

$data = unserialize((string)$data);

$data 在调用主机和本地计算机之前具有相同的值。然后 unserialize returns ResultSetitems 字段的对象;


SplFixedArrayunserialize

好像有点问题

哈,不错:PHP 7.0.15 and PHP 7.1.0 ResultSet Caching #10111

如您所见,在调试过程中我发现问题是由 ResultSet 使用的 SplFixedArrayunserialize() 引起的。

之后我找到了this topic: PHP 7.0.15 and PHP 7.1.0 ResultSet Caching #10111

在我的例子中,我尝试使用 PHP 7.0.247.1.55.6.305.5.38。 5.5 效果很好。

这个问题在那个话题的讨论中被解决了,所以我从CakePHP 3.5复制了ResultSet::serializeunserialize方法。诀窍是将数据序列化为通常的数组,而不是 SplFixedArray

\Cake\ORM\ResultSet

313:     public function serialize()
314:     {
315:         if (!$this->_useBuffering) {
316:             $msg = 'You cannot serialize an un-buffered ResultSet. Use Query::bufferResults() to get a buffered ResultSet.';
317:             throw new Exception($msg);
318:         }
319: 
320:         while ($this->valid()) {
321:             $this->next();
322:         }
323: 
324:         if ($this->_results instanceof SplFixedArray) {
325:             return serialize($this->_results->toArray());
326:         }
327: 
328:         return serialize($this->_results);
329:     }
330: 

339:     public function unserialize($serialized)
340:     {
341:         $results = (array)(unserialize($serialized) ?: []);
342:         $this->_results = SplFixedArray::fromArray($results);
343:         $this->_useBuffering = true;
344:         $this->_count = $this->_results->count();
345:     }