file_put_contents追加内容必须显式使用FILE_APPEND标志,否则默认覆盖;需手动添加换行符、检查返回值,避免混用FILE_USE_INCLUDE_PATH,高并发场景建议改用fopen+flock。

file_put_contents 追加内容要用 FILE_APPEND 标志
直接调用 file_put_contents 默认是覆盖写入,想追加必须显式传入 FILE_APPEND 标志。它不是靠参数顺序或默认行为生效,漏掉这个标志就白写了。
-
FILE_APPEND是唯一可靠的追加方式,不依赖文件指针位置或打开模式 - 如果同时需要创建目录(比如日志路径不存在),得额外用
mkdir或stream_context_create配合recursive选项,FILE_APPEND本身不处理路径创建 - 追加时不会自动加换行符——如果每次写一行,记得在数据末尾手动加
\n
常见错误:误用 FILE_USE_INCLUDE_PATH 或忽略返回值
有人把 FILE_APPEND 和 FILE_USE_INCLUDE_PATH 混在一起传,结果 PHP 找不到文件还报错;也有人没检查 file_put_contents 返回值,写失败了却以为成功了。
- 错误写法:
file_put_contents('log.txt', $msg, FILE_APPEND | FILE_USE_INCLUDE_PATH)——FILE_USE_INCLUDE_PATH会让 PHP 去include_path里找文件,不是当前目录 - 正确写法:
file_put_contents('log.txt', $msg . "\n", FILE_APPEND) - 建议判断返回值:
if (file_put_contents('log.txt', $msg . "\n", FILE_APPEND) === false) { /* 写入失败 */ }
并发写入时可能丢数据,别直接裸用
多个请求同时追加到同一个文件,FILE_APPEND 虽然底层调用 open(..., O_APPEND) 保证原子性,但 PHP 层的字符串拼接、编码转换等前置操作不在原子范围内。更关键的是,Linux 下 O_APPEND 只保证单次 write() 原子,而 PHP 的 file_put_contents 在大内容或开启 mbstring 时可能拆成多次写入。
- 简单日志场景够用,但高并发或要求强一致性的场景,建议改用
fopen+flock+fwrite - 如果坚持用
file_put_contents,确保内容短小、无编码转换,且不要在循环里高频调用 - 注意 umask 影响:如果文件不存在,新创建的文件权限受当前
umask控制,可能比预期更严格
Windows 下换行符和编码要特别留意
Windows 默认用 \r\n,而 PHP 脚本若在 Linux 编写、部署到 Windows,又用了 mb_convert_encoding 或输出缓冲,容易导致追加内容乱码或换行错位。
立即学习“PHP免费学习笔记(深入)”;
- 写文本日志时,统一用
\n,让终端/编辑器自己适配显示(现代工具都支持) - 避免混用
file_put_contents和fwrite操作同一文件——前者会重置文件指针,后者依赖当前位置,冲突难排查 - 如果内容含中文,确认脚本文件编码是 UTF-8 无 BOM,且没被
iconv或mb_internal_encoding意外转码
追加看着简单,但跨平台、并发、编码这三块最容易出 silent bug,尤其是线上日志突然断掉或者内容粘连的时候,往往就卡在这几个细节上。



















