
本文详解 php 中将关联数组以 utf-8 兼容的 json 格式写入日志文件的方法,指出直接 fwrite 数组导致失败的根本原因,并提供安全、可读、可解析的日志记录实践方案。
本文详解 php 中将关联数组以 utf-8 兼容的 json 格式写入日志文件的方法,指出直接 fwrite 数组导致失败的根本原因,并提供安全、可读、可解析的日志记录实践方案。
在您提供的 class.log.php 中,核心问题在于:PHP 的 fwrite() 函数无法直接写入数组变量。当您执行 fwrite($ofile, $data) 时,PHP 会尝试将数组隐式转换为字符串(结果为 "Array" 字面量),而非其实际内容——这导致日志文件中仅记录无意义的 "Array",而非期望的结构化 JSON 数据。
要正确写入 JSON,必须显式调用 json_encode() 将数组序列化为合法 JSON 字符串。同时,为保障中文等 Unicode 字符正常显示(避免乱码),应启用 JSON_UNESCAPED_UNICODE 选项。以下是修正后的关键代码段:
public function add($uID, $pID, $text)
{
$date = date("d.m.Y H:i:s"); // 合并日期与时间,更简洁
$data = [
"Date" => $date,
"UserID" => $uID,
"ProductID" => $pID,
"Text" => $text
];
$folder = "../log/";
$logFileName = $folder . date("d-m-Y") . ".log";
// 确保目录存在(含递归创建,更健壮)
if (!is_dir($folder)) {
mkdir($folder, 0755, true);
}
// 写入 BOM 仅对 UTF-8 编码文本文件必要(如需兼容某些编辑器),但非强制
if (!file_exists($logFileName)) {
file_put_contents($logFileName, "\xEF\xBB\xBF", FILE_APPEND | LOCK_EX);
}
// 关键修复:json_encode + 错误检查
$jsonLine = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if ($jsonLine === false) {
error_log("JSON encode failed: " . json_last_error_msg());
return;
}
// 使用 file_put_contents 替代 fopen/fwrite,更简洁且自动处理锁
file_put_contents($logFileName, $jsonLine . PHP_EOL, FILE_APPEND | LOCK_EX);
}注意事项与最佳实践:
- ✅ 始终检查 json_encode() 返回值:若输入含不可序列化类型(如资源、闭包),会返回 false,需捕获并记录错误;
- ✅ 使用 FILE_APPEND | LOCK_EX:确保多进程写入时的日志行原子性,避免内容错乱;
- ✅ 追加换行符 PHP_EOL:使每条 JSON 记录独占一行,便于后续用 file() 或流式解析;
- ⚠️ BOM(\xEF\xBB\xBF)慎用:现代 JSON 解析器通常无需 BOM,反而可能引发解析异常,建议仅在明确需要时添加;
- ? 权限与路径安全:确保 ../log/ 目录可被 Web 服务器进程写入,且不在 Web 可访问路径下(防止日志被直接下载)。
通过以上改进,您的日志文件将生成标准、可读、可解析的 JSON 行格式(JSON Lines),例如:
立即学习“PHP免费学习笔记(深入)”;
{"Date":"12.04.2024 15:30:22","UserID":"41","ProductID":"16","Text":"Product Added"}这不仅解决了当前问题,也为日志的自动化分析、ELK 集成或跨语言处理奠定了坚实基础。



















