最稳妥方式是先用 fopen() 以 'w' 模式打开文件,再用 fwrite() 写入;需检查目录可写、路径绝对化、变量适当转义或序列化,并用返回值判断错误而非 @ 抑制。

用 fopen() 和 fwrite() 写入含变量的文件最稳妥
PHP 中写入变量到新文件,核心是「先打开(或创建)文件,再把变量内容写进去」。fopen() 的 'w' 模式会自动创建文件(若不存在),并清空已有内容;'a' 则追加,但首次运行时也得确保文件可写。别直接用 file_put_contents() 一招鲜——它虽简洁,但错误时不报具体原因,调试困难。
常见错误现象:fopen(): failed to open stream: Permission denied,多因目录无写权限;或路径写成 ./data/ 却没建目录,导致静默失败。
- 务必用
is_writable()检查目标目录是否可写 - 路径建议用
__DIR__ . '/output.txt',避免相对路径歧义 - 写入前对变量做
htmlspecialchars($var, ENT_QUOTES, 'UTF-8')(若含 HTML)或str_replace("\n", "\r\n", $var)(Windows 换行兼容)
file_put_contents() 快速写入但需手动处理失败
它适合脚本工具类场景,一行搞定,但掩盖了底层 fopen 流程。默认使用二进制写入,不自动转义,也不校验目录是否存在。
典型误用:file_put_contents('log.txt', $msg) 在 /var/www/html/ 下跑,结果提示 failed to open stream: No such file or directory——其实是因为上级目录 log/ 不存在,而它不会帮你建。
立即学习“PHP免费学习笔记(深入)”;
- 补救写法:
if (!is_dir($dir = dirname('log/info.txt'))) { mkdir($dir, 0755, true); } - 加错误抑制符
@是掩耳盗铃,应改用返回值判断:$ret = file_put_contents($file, $content); if ($ret === false) { error_log("write failed: $file"); } - 注意:
file_put_contents()返回写入字节数,不是布尔值;空字符串写入成功也返回0,别当成失败
变量含数组或对象时必须序列化
直接 fwrite($fp, $arr) 会输出 Array 字符串,对象同理。要保留结构,得选序列化方式:
- 调试用:
print_r($data, true)或var_export($data, true),生成可读 PHP 代码格式 - 程序间交换:
json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT),注意中文不乱码 - 原样存取:
serialize($data)+unserialize(),但存在反序列化安全风险,别用于不可信数据
示例:$content = " —— 这样生成的文件可被 require 直接加载。
Windows 和 Linux 路径、换行、编码的隐性坑
本地开发(Windows)写完文件,扔到 Linux 服务器上读不出来?大概率是三件事没对齐:路径分隔符、换行符、文件编码。
- 路径统一用
/(PHP 内部自动适配),别拼"C:\\tmp\\" . $name - 写文本文件时,显式换行:
$content = str_replace("\n", PHP_EOL, $content),否则 Windows 写出\r\n,Linux 解析可能错行 - 如果变量含中文,文件头不加 BOM,且保存为 UTF-8 无 BOM;用
mb_convert_encoding($str, 'UTF-8', 'auto')防止来源编码混乱
这些细节不报错,但会让文件在另一环境里“看起来空”“读出来乱码”“require 报语法错误”——问题往往卡在你根本没想到的地方。











