Recently I moved CakePHP 3.2
project to web hosting ( CentOS
, php 7.0/5.6
tried both, OpCache
enabled), and found that query results caching doesn't work.
I use default file cache engine for navigation menu.
$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();
I had not problems with this code on local OpenServer
, IIS7
and IIS8
servers and other Linux
server.
so, what is happening:
When I run script for the first time, cake fetches the data from DB and writes cache to /src/tmp/cache/long/cake_sitemenu__menu_items
. File has serialized contents as usual.
But when I refresh the page I see empty result.
There is nothing in error or debug log.
I've tried to lowercase cache key, but with no luck.
Any ideas ?
I've added test code to check basic caching itself:
public function qwe(){
$data = ['key' => 'value'];
//Cache::write('test', $data, 'long');
$result = Cache::read('test', 'long');
$result[] = 'xxx';
$this->setJsonResponse($result);
}
and this code returns correct result.
so far I found that there is some problem read()
method of Cake\\Cache\\Egine\\FileEngine
class. line 223:
$data = unserialize((string)$data);
$data
has the same value before call on hosting and local machine. and then unserialize
returns ResultSet
object with empty items
field;
it seems there is something with SplFixedArray
and unserialize
hah, nice: PHP 7.0.15 and PHP 7.1.0 ResultSet Caching #10111
As you can see, during dubugging I found that problem was caused by SplFixedArray
which ResultSet
uses and unserialize()
.
After that I found this topic: PHP 7.0.15 and PHP 7.1.0 ResultSet Caching #10111 .
In my case I tried to use PHP 7.0.24
, 7.1.5
, 5.6.30
and 5.5.38
. And 5.5 worked well.
This problem was fixed during that topic discussion, so I copied ResultSet::serialize
and unserialize
methods from CakePHP 3.5
. The trick was to serialize data as usual array, not 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: }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.