parse_ini_file()默认返回一维数组,节内键名扁平化易覆盖;必须传true才返回二维数组保留节结构,且需校验文件存在性、权限及布尔值写回还原,写入须手动拼接并加锁防并发。

parse_ini_file() 读取时必须传 true 才能拿到节结构
默认调用 parse_ini_file('config.ini') 返回一维数组,所有键扁平化,[database] 节里的 host 和 [cache] 节里的 host 会互相覆盖。要保留节层级,第二个参数必须显式设为 true:parse_ini_file('config.ini', true)。否则你拿到的数组根本看不出配置归属哪个节。
常见错误现象:修改了 config.ini 加了新节,但 PHP 代码里访问 $cfg['database']['host'] 报 Notice: Undefined index——八成是漏传 true。
额外注意点:
-
parse_ini_file()在文件不存在或不可读时直接返回false,不是空数组,务必先用file_exists()和is_readable()检查 - 布尔值如
debug = on会被转成true,但写回时若不还原为字符串"on",下次读就永远是布尔型了 - 注释和空行被自动忽略,别指望靠它存文档说明
写入 INI 文件没有内置函数,必须手动拼接字符串
PHP 只提供读,不提供写。想保存修改,得自己把数组转成标准 INI 格式再 fopen() 写入。核心逻辑是:遍历外层数组(节名),对每个节再遍历内层键值对,按 key = "value" 拼接,节头用 [section] 包裹。
立即学习“PHP免费学习笔记(深入)”;
容易踩的坑:
- 值含等号、引号、换行时必须加双引号并转义,否则解析失败;简单做法是统一用
sprintf('"%s"', addslashes($value)) - 数组型值(如
allowed_hosts[] = "127.0.0.1")需识别is_array()并用[]语法,否则写成allowed_hosts = "Array" - 写入前没检查目录可写权限,
fopen($path, 'w')失败返回false,但错误被静默吞掉 - 没做
file_put_contents($path, $content, LOCK_EX)加锁,高并发写可能损坏文件
INI_SCANNER_TYPED 能自动转类型,但兼容性有风险
第三个参数传 INI_SCANNER_TYPED 后,port = 3306 解析为整数 3306,debug = off 解析为布尔 false。看起来省事,但要注意:
- PHP 5.6+ 才支持该常量,低版本直接报
undefined constant - 值为
0、1、yes、no等会被强转,但parse_ini_file()不保证所有“真值”都统一处理,比如enabled = 1是整数,enabled = true是布尔,混用易引发类型判断 bug - 写回时若没按原始字符串还原(比如把
false写成off),下次读又变布尔,形成恶性循环
敏感配置别放 INI 文件,尤其不能放 Web 可访问路径
INI 文件本身不执行代码,但若放在 public/ 或 www/ 目录下,用户直接请求 http://yoursite.com/config.ini 就能下载全部内容——数据库密码、API 密钥全裸奔。
安全底线:
- INI 文件必须放在 Web 根目录之外,比如
/var/www/app/config/,而非/var/www/html/config/ - Apache/Nginx 配置里显式禁止 .ini 后缀访问:
location ~ \.ini$ { deny all; } - 别用
parse_ini_file()直接读取用户上传的 INI,没做白名单校验极易导致路径遍历(如传../../etc/passwd)
addslashes()、is_writable()、flock() 这些胶水逻辑——PHP 原生只给一半梯子,剩下得自己焊。



















