Недавно я переехал CakePHP 3.2
проект для веб-хостинга (CentOS
, php 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();
У меня не было проблем с этим кодом на локальном OpenServer
, IIS7
а также IIS8
серверы и прочее Linux
сервер.
Итак, что происходит:
Когда я запускаю скрипт в первый раз, торт выбирает данные из БД и записывает кеш в /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);
}
и этот код возвращает правильный результат.
до сих пор я обнаружил, что есть какая-то проблема read()
метод Cake\Cache\Egine\FileEngine
учебный класс. строка 223:
$data = unserialize((string)$data);
$data
имеет одинаковое значение перед звонком на хостинг и локальную машину. а потом unserialize
возвращается ResultSet
объект с пустым items
поле;
кажется, что-то с SplFixedArray
а также unserialize
ха, приятно PHP 7.0.15 и PHP 7.1.0 ResultSet Caching # 10111
Как вы можете видеть, во время дублирования я обнаружил, что проблема была вызвана SplFixedArray
который ResultSet
использует и unserialize()
,
После этого я нашел эта тема: PHP 7.0.15 и PHP 7.1.0 ResultSet Caching # 10111.
В моем случае я пытался использовать PHP 7.0.24
, 7.1.5
, 5.6.30
а также 5.5.38
, И 5.5 работал хорошо.
Эта проблема была исправлена во время обсуждения темы, поэтому я скопировал ResultSet::serialize
а также unserialize
методы из CakePHP 3.5
, Хитрость заключалась в том, чтобы сериализовать данные как обычный массив, а не 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: }
Других решений пока нет …