212 lines
4.9 KiB
Markdown
212 lines
4.9 KiB
Markdown
# PHP 中文字符编码解决方案
|
||
|
||
## 🎯 问题描述
|
||
|
||
在使用 `json_encode()` 处理包含中文字符的数据时,默认会将中文字符转换为 Unicode 编码:
|
||
|
||
```php
|
||
// ❌ 默认行为 - 中文转为Unicode
|
||
$data = ['message' => '请检查计划任务配置'];
|
||
echo json_encode($data);
|
||
// 输出:{"message":"\u8bf7\u68c0\u67e5\u8ba1\u5212\u4efb\u52a1\u914d\u7f6e"}
|
||
```
|
||
|
||
这在日志文件中查看很不方便,影响调试效率。
|
||
|
||
## 🛠️ 解决方案对比
|
||
|
||
### 方案一:`JSON_UNESCAPED_UNICODE` 标志 ⭐⭐⭐⭐⭐⭐
|
||
|
||
```php
|
||
// ✅ 推荐方案 - 保持中文原样
|
||
$data = ['message' => '请检查计划任务配置'];
|
||
echo json_encode($data, JSON_UNESCAPED_UNICODE);
|
||
// 输出:{"message":"请检查计划任务配置"}
|
||
```
|
||
|
||
**优点:**
|
||
- ✅ 中文完全可读
|
||
- ✅ 保持JSON格式
|
||
- ✅ 兼容性好
|
||
- ✅ 性能优秀
|
||
|
||
**使用场景:**
|
||
- 日志记录
|
||
- API响应
|
||
- 配置文件
|
||
- 调试输出
|
||
|
||
### 方案二:`var_export()` 函数 ⭐⭐⭐
|
||
|
||
```php
|
||
// ✅ 完全避免Unicode转义
|
||
$data = ['message' => '请检查计划任务配置'];
|
||
echo var_export($data, true);
|
||
// 输出:array (
|
||
// 'message' => '请检查计划任务配置',
|
||
// )
|
||
```
|
||
|
||
**优点:**
|
||
- ✅ 完全可读
|
||
- ✅ 数组结构清晰
|
||
- ✅ 无需额外参数
|
||
|
||
**缺点:**
|
||
- ❌ 不是标准JSON格式
|
||
- ❌ 输出较冗长
|
||
|
||
**使用场景:**
|
||
- 开发调试
|
||
- 临时日志
|
||
- 数组检查
|
||
|
||
### 方案三:`print_r()` + 捕获输出 ⭐⭐
|
||
|
||
```php
|
||
// ✅ 可读性好的数组输出
|
||
$data = ['message' => '请检查计划任务配置'];
|
||
ob_start();
|
||
print_r($data);
|
||
$result = ob_get_clean();
|
||
```
|
||
|
||
**优点:**
|
||
- ✅ 格式美观
|
||
- ✅ 易于阅读
|
||
|
||
**缺点:**
|
||
- ❌ 需要输出缓冲
|
||
- ❌ 性能较差
|
||
|
||
### 方案四:自定义序列化函数 ⭐⭐⭐
|
||
|
||
```php
|
||
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 类中的实现
|
||
|
||
```php
|
||
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;
|
||
}
|
||
}
|
||
```
|
||
|
||
### 使用示例
|
||
|
||
```php
|
||
// 日志记录 - 使用 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
|
||
// PHP 5.4+ 基本支持
|
||
json_encode($data, JSON_UNESCAPED_UNICODE);
|
||
|
||
// PHP 5.3+ 需要 polyfill
|
||
if (!defined('JSON_UNESCAPED_UNICODE')) {
|
||
define('JSON_UNESCAPED_UNICODE', 256);
|
||
}
|
||
```
|
||
|
||
### 文件编码设置
|
||
```php
|
||
// 确保文件本身是 UTF-8 编码
|
||
header('Content-Type: text/html; charset=utf-8');
|
||
mb_internal_encoding('UTF-8');
|
||
```
|
||
|
||
## 📊 性能对比
|
||
|
||
| 方法 | 执行时间 | 内存使用 | 可读性 | JSON兼容 |
|
||
|------|----------|----------|---------|-----------|
|
||
| `json_encode()` | 快 | 低 | ⭐⭐⭐⭐⭐ | ✅ |
|
||
| `var_export()` | 中 | 中 | ⭐⭐⭐⭐ | ❌ |
|
||
| `print_r()` | 慢 | 高 | ⭐⭐⭐⭐ | ❌ |
|
||
| 自定义序列化 | 慢 | 高 | ⭐⭐ | ❌ |
|
||
|
||
## 🎉 推荐配置
|
||
|
||
### 生产环境(推荐)
|
||
```php
|
||
// 使用 JSON_UNESCAPED_UNICODE 保持中文可读性
|
||
json_encode($data, JSON_UNESCAPED_UNICODE);
|
||
```
|
||
|
||
### 开发环境
|
||
```php
|
||
// 使用格式化JSON增强可读性
|
||
json_encode($data,
|
||
JSON_UNESCAPED_UNICODE |
|
||
JSON_PRETTY_PRINT |
|
||
JSON_UNESCAPED_SLASHES
|
||
);
|
||
```
|
||
|
||
### 调试模式
|
||
```php
|
||
// 使用 var_export 获得最佳可读性
|
||
var_export($data, true);
|
||
```
|
||
|
||
---
|
||
|
||
**总结:** 对于您的需求,使用 `JSON_UNESCAPED_UNICODE` 标志是最佳选择,既保持了JSON格式的标准性,又确保了中文字符的可读性。 |