简体   繁体   中英

CakePHP Query results caching

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM