Zend_Cache:加载缓存数据后,字符编码好像乱了

第一;在我的开发服务器(本地主机;OSX 上的默认 XAMPP)上一切正常,但当我将完全相同的代码(和数据)部署到临时服务器(在 Redhat 上托管 Apache2)时,它会中断.

First; On my development server (localhost; default XAMPP on OSX) everything works fine, though when I deploy the exact same code (and data) to the staging server (managed Apache2 on Redhat) it breaks.

我正在使用 Zend_Cache 使用文件后端和自动序列化缓存一些数据.原始数据中使用的特殊字符显示正常,但当它们从缓存中加载时,它们都是乱码.

I'm caching some data using Zend_Cache using the File backend and auto-serialization. Special characters used in the original data display fine, though when they are loaded from cache they're all garbled up.

有人知道吗?

附注.我正在寻找一种方法来了解临时服务器上可能出现的错误",而不是只是一种解决方法.什么可能会搞砸?

PS. Instead of just a workaround, I'm looking for a way to understand what might go "wrong" on the staging server. What could possibly mess this up?

更新我缓存的数据是 UTF-8 编码的.

UPDATE The data I'm caching is UTF-8 encoded.

更新在查看原始缓存文件(序列化数组的)时,我看到了一个很大的不同;当暂存服务器上缓存的(相同)数据确实显示换行符时,我的本地主机上缓存的数据不显示换行符.

UPDATE When looking at the raw cache files (of a serialized array) there i See one big difference; The data cached on my localhost shows no newlines when the (identical) data cached on the staging server does show newlines.

更新本地服务器运行 PHP 5.3,临时服务器运行 PHP 5.2.10

UPDATE Local server runs PHP 5.3, staging server runs PHP 5.2.10

更新在 Zend FW 1.10.8 上运行

UPDATE Running on Zend FW 1.10.8

推荐答案

我和你的情况几乎一模一样,

I have almost identical state like you ,

开发机器windows + php 5.3

development machine is windows + php 5.3

开发机为Linux + php 5.2.14

development machine is Linux + php 5.2.14

ZF 版本是 1.10

ZF version is 1.10

我唯一的区别是:我曾经在引导类中添加 mb_internal_encoding("UTF-8");

the only difference i had is : i used to add mb_internal_encoding("UTF-8"); in the bootstrap class

仅供参考,我曾经从数据库中缓存所有编码的 UTF8 文本(阿拉伯语)当我打开文件时,我看到了预期的阿拉伯语文本.

FYI , I used to cache text (arabic language ) from database all encoded UTF8 when i open the file i see the arabic text as expected .

更新:1- 这是我完整的 initCache 函数,只是为了清楚起见

UPDATE : 1- here is my complete initCache function just to make it clear

public function _initCache() {
        mb_internal_encoding("UTF-8");
        $frontendOptions = array(
            'automatic_serialization' => TRUE,
            'lifetime' => 86400
        );
        $backendOptions = array(
            'cache_dir' => APPLICATION_PATH . "/configs/cache/",
                ///'cache_dir' => sys_get_temp_dir(),
        );
        $cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);
        Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
        Zend_Registry::set("cache", $cache);
    }

说明:1-任何早于 PHP 6 的 php 版本都没有对 UTF-8 的本机支持,https://stackoverflow.com/questions/716703/what-is-coming-in-php-6

Explanation : 1-Any php version earlier than PHP 6 doesn't have native support for UTF-8 , https://stackoverflow.com/questions/716703/what-is-coming-in-php-6

2-使 php 5.3 或 5.2 使用 ICONV 处理 UTF8或 MB_STRING

2-making php 5.3 or 5.2 deal with UTF8 by using ICONV or MB_STRING

只需使用 var_dump(mb_internal_encoding());

你可以在内部使用 ISO-8859-1 告诉 php,

you can tell that php using ISO-8859-1 internally ,

你可以通过var_dump(mb_internal_encoding("UTF-8"));

它会输出真(它成功覆盖内部编码)

it would output true (it success to override the internal encoding )

老实说,我不知道是否有更好的解决方案或如何不好是吗??,

to be honest i don't know if there is better solution or how bad it is ?? ,

如果你有更好的我会很乐意采用它:)

if you had any better i would be happy to adopt it :)

更新 2如果您不想使用该功能,打开这个文件 "Zend/Cache/Backend/File.php" 并转到第 976 行改变这个:

UPDATE 2 in case you don't want to use that function , open this file "Zend/Cache/Backend/File.php" and go to the line 976 change this :

protected function _filePutContents($file, $string)
{

    $result = false;
    $f = @fopen($file, 'ab+');
    if ($f) {
        if ($this->_options['file_locking']) @flock($f, LOCK_EX);
        fseek($f, 0);
        ftruncate($f, 0);
        $tmp = @fwrite($f, $string);
        if (!($tmp === FALSE)) {
            $result = true;
        }
        @fclose($f);
    }
    @chmod($file, $this->_options['cache_file_umask']);
    return $result;
}

成为这样:

protected function _filePutContents($file, $string)
{
    $string = mb_convert_encoding($string   , "UTF-8" , "ISO-8859-1"); // i didn't test it , use it at your own risk and i'd rather stick with the first solution 
    $result = false;
    $f = @fopen($file, 'ab+');
    if ($f) {
        if ($this->_options['file_locking']) @flock($f, LOCK_EX);
        fseek($f, 0);
        ftruncate($f, 0);
        $tmp = @fwrite($f, $string);
        if (!($tmp === FALSE)) {
            $result = true;
        }
        @fclose($f);
    }
    @chmod($file, $this->_options['cache_file_umask']);
    return $result;
}

我没有手动测试,但它应该按预期工作

i didn't test manually but it should work as expected

很高兴它有所帮助!

相关文章