ZF-6352: Zend_Cache::save() encoding problem

Description

When using Zend_Cache::start() to save a paginator object, encoding of stored db query result gets broken (originally UTF-8).

if (!$this->view->frontPageArticles = $this->_cache->load('frontPageArticles')) { $content = new CMS_Model_Content(); $this->view->frontPageArticles = $content->getFrontpageContent($this->_params['page']); //gets Zend_Paginator object $this->_cache->save($this->view->frontPageArticles,'frontPageArticles');
}

When the last line of code is commented (and cache purged), everything is ok (chars like ěščř... are displayed correctly).

ZF 1.8

Comments

please provide a little piece of code to reproduce the problem because there is already a unit test about UTF8 into cache records and there is no problem about it

I close this issue because I think that you have an HTTP header problem or something like that. With default configuration, Zend_Cache_Frontend_Page does not save the "content-type" http header (but there are some options to do that) and IMHO your problem is here.

If I'm wrong, please reopen this issue with a little piece of code to reproduce your UTF8 problem.

Regards

Well, as you can see here: http://frontend.pctuning.cz/ , there isn't a problem with whole page but only with the content touched by Zend_Cache (the main article, which is, I think, clear).

The code:

1) Bootstrap:

$cache = Zend_Cache::factory( 'Core', 'File', array( 'lifetime' => (15*60), 'automatic_serialization' => true, 'caching' => CACHE_ENABLED ), array( 'cache_dir' => '../store/cache/' ) ); Zend_Registry::set('MainCache',$cache);

2) Controller:

private $_cache;

public function init()
{
    $this->_params = $this->getRequest()->getUserParams();
    $this->_cache = Zend_Registry::get('MainCache');
}

public function indexAction()
{

    if (!$this->view->frontPageArticles = $this->_cache->load('frontPageArticles'))
    {
        $content = new CMS_DbTable_Content();
        $this->view->frontPageArticles = $content->getFrontpageContent($this->_params['page']);
        $this->_cache->save($this->view->frontPageArticles,'frontPageArticles');                
    } 
}

3) CMS_DbTable_Content

public function getFrontpageContent($page = 0) {

        $select = $this->select();
        $select->setIntegrityCheck(false);

        $select->from('content')
                ->joinInner(
                    'content_frontpage',
                    'content_frontpage.content_id = content.id',
                    array()
                )
                ->order('content.created DESC')
                ->where('content.state = 1');

                $paginator = new Zend_Paginator(new Zend_Paginator_Adapter_DbTableSelect($select));
                $paginator->setItemCountPerPage(15);
                $paginator->setCurrentPageNumber($page);

        return $paginator;

    }

So as you can see, I do not cache whole page but only the returned paginator object - if I'm right, the query is proccessed after calling getCurrentItems(), so I do not really cache any data from database, so that's more weird that the data I get after calling getCurrentItems are broken.

And I did not forget to call set names utf-8 :-)

I don't know. Your code is too complex. I can't reproduce this on my linux box.

Can you try a unit test : - you save UTF8 chars into a cache record - you read this cache record

then you compare these two strings

I can confirm this issue. If you save a Zend_Paginator object in the cache (I only tested file cache), the result that is loaded from the cache has messed up UTF-8 encoded strings.

 
$frontendOptions = array(
   'caching' => true,
   'lifetime' => 7200, 
   'automatic_serialization' => true
);

$backendOptions = array(
    'cache_dir' => 'cache/' 
);

$cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);

//Zend_Db_Table_Select object
$select = $this->select();

$paginator = Zend_Paginator::factory($select );
$paginator->setItemCountPerPage(10);
$paginator->setCurrentPageNumber(1);

$cache->save($paginator, 'a_cache_id');

$cachedPaginator = $cache->load('a_cache_id');

The UTF-8 chars in $paginator are fine, in $cachedPaginator they are messed up.

I suppose this is a Zend_Paginator or a Zend_Db_Table_Select or a serialize() issue.

Can you try in your configuration to store UTF8 chars (with automatic_serialization = false) and without other objects (only UTF8 chars !) and to retrieve them from cache ?

thanks

after reading http://fr.php.net/unserialize comments about utf8

I think it's a unserialize() issue

please do the little test I propose in my last comment

and do it also with automatic_serialization = true

I did some more testing and it seems to have to do with serialization, probably the Zend_Db_Table_Select and not the Zend_Paginator. I only tested with Zend_Paginator using a Zend_Db_Table_Select though.

This is strange:

Apparently serializing a Zend_Paginator object that includes a result of a Zend_Db_Table_Select breaks the UTF-8.

 
$paginatorObject = serialize($paginatorObject );    
$paginatorObject = unserialize($paginatorObject );

//broken UTF-8
foreach ($paginatorObject as $result) {
    var_dump($result);
}

Now the funny part. If we iterate over the paginator result right before serializing it, the UTF-8 will NOT be broken!

 
//itareate to preserve UTF-8
foreach ($paginatorObject as $result) {
}   

$paginatorObject = serialize($paginatorObject );    
$paginatorObject = unserialize($paginatorObject );

//working UTF-8
foreach ($paginatorObject as $result) {
    var_dump($result);
}

Basically this is my dirty quick fix for now. Right before I save the paginator object in the cache, I iterate over it once.

So, it is not a Zend_Cache issue.

Maybe open a new one for Zend_Paginator ?

Maybe, try with the latest version of PHP before