Files
shop-platform/docs/CHINESE_ENCODING_SOLUTIONS.md

4.9 KiB
Raw Permalink Blame History

PHP 中文字符编码解决方案

🎯 问题描述

在使用 json_encode() 处理包含中文字符的数据时,默认会将中文字符转换为 Unicode 编码:

// ❌ 默认行为 - 中文转为Unicode
$data = ['message' => '请检查计划任务配置'];
echo json_encode($data);
// 输出:{"message":"\u8bf7\u68c0\u67e5\u8ba1\u5212\u4efb\u52a1\u914d\u7f6e"}

这在日志文件中查看很不方便,影响调试效率。

🛠️ 解决方案对比

方案一:JSON_UNESCAPED_UNICODE 标志

// ✅ 推荐方案 - 保持中文原样
$data = ['message' => '请检查计划任务配置'];
echo json_encode($data, JSON_UNESCAPED_UNICODE);
// 输出:{"message":"请检查计划任务配置"}

优点:

  • 中文完全可读
  • 保持JSON格式
  • 兼容性好
  • 性能优秀

使用场景:

  • 日志记录
  • API响应
  • 配置文件
  • 调试输出

方案二:var_export() 函数

// ✅ 完全避免Unicode转义
$data = ['message' => '请检查计划任务配置'];
echo var_export($data, true);
// 输出array (
//   'message' => '请检查计划任务配置',
// )

优点:

  • 完全可读
  • 数组结构清晰
  • 无需额外参数

缺点:

  • 不是标准JSON格式
  • 输出较冗长

使用场景:

  • 开发调试
  • 临时日志
  • 数组检查

方案三:print_r() + 捕获输出

// ✅ 可读性好的数组输出
$data = ['message' => '请检查计划任务配置'];
ob_start();
print_r($data);
$result = ob_get_clean();

优点:

  • 格式美观
  • 易于阅读

缺点:

  • 需要输出缓冲
  • 性能较差

方案四:自定义序列化函数

function serializeArray($data) {
    if (!is_array($data)) return $data;
    
    $result = [];
    foreach ($data as $key => $value) {
        if (is_array($value)) {
            $result[$key] = serializeArray($value);
        } else {
            $result[$key] = $value;
        }
    }
    
    return $result;
}

🎯 最佳实践组合

在 Cron 类中的实现

class Cron extends BaseModel
{
    /**
     * 格式化数据为日志友好的字符串(保持中文可读性)
     */
    private static function formatForLog($data): string
    {
        if (is_array($data) || is_object($data)) {
            // JSON_UNESCAPED_UNICODE 保持中文可读性
            // JSON_PRETTY_PRINT 增加格式化
            // JSON_UNESCAPED_SLASHES 避免斜杠转义
            return json_encode($data, 
                JSON_UNESCAPED_UNICODE | 
                JSON_PRETTY_PRINT | 
                JSON_UNESCAPED_SLASHES
            );
        }
        
        return (string) $data;
    }

    /**
     * 完全避免Unicode转义的格式化
     */
    private static function exportForLog($data): string
    {
        if (is_array($data) || is_object($data)) {
            return var_export($data, true);
        }
        
        return (string) $data;
    }
}

使用示例

// 日志记录 - 使用 formatForLog
$detail = [
    'error' => $error,
    'remark' => $remark,
    'suggestion' => ScheduleDict::getSuggestion($cronType)
];
log_write('异常信息:' . self::formatForLog($detail), 'warning');

// 调试输出 - 使用 exportForLog  
$debugData = ['config' => $config, 'status' => $status];
echo self::exportForLog($debugData);

🔧 环境配置

确保 PHP 版本支持

// PHP 5.4+ 基本支持
json_encode($data, JSON_UNESCAPED_UNICODE);

// PHP 5.3+ 需要 polyfill
if (!defined('JSON_UNESCAPED_UNICODE')) {
    define('JSON_UNESCAPED_UNICODE', 256);
}

文件编码设置

// 确保文件本身是 UTF-8 编码
header('Content-Type: text/html; charset=utf-8');
mb_internal_encoding('UTF-8');

📊 性能对比

方法 执行时间 内存使用 可读性 JSON兼容
json_encode()
var_export()
print_r()
自定义序列化

🎉 推荐配置

生产环境(推荐)

// 使用 JSON_UNESCAPED_UNICODE 保持中文可读性
json_encode($data, JSON_UNESCAPED_UNICODE);

开发环境

// 使用格式化JSON增强可读性
json_encode($data, 
    JSON_UNESCAPED_UNICODE | 
    JSON_PRETTY_PRINT | 
    JSON_UNESCAPED_SLASHES
);

调试模式

// 使用 var_export 获得最佳可读性
var_export($data, true);

总结: 对于您的需求,使用 JSON_UNESCAPED_UNICODE 标志是最佳选择既保持了JSON格式的标准性又确保了中文字符的可读性。