答案就是yosymfony/toml:PHP无原生TOML支持,该库是唯一活跃维护、兼容v0.4.0的纯PHP实现;需composer require安装,解析返回关联数组,写入须用TomlBuilder手动构建结构,不自动类型转换、不支持点号路径、大小写敏感且严格校验语法。

PHP 读写 TOML 文件必须用 yosymfony/toml,原生不支持;它不自动处理大小写映射、不忽略空值、不支持点号路径取嵌套数组——这些都得手动控制。
安装和基础读取:composer require yosymfony/toml 是唯一可行起点
PHP 没有内置 TOML 支持,yosymfony/toml 是当前唯一活跃维护、兼容 TOML v0.4.0 的纯 PHP 实现。别试图用 file_get_contents + json_decode 硬凑,TOML 不是 JSON。
- 执行
composer require yosymfony/toml,会装入vendor/yosymfony/toml - 读文件直接调
TOML::parseFile("config.toml"),返回关联数组(不是对象),例如$config["database"]["host"] - 如果 TOML 里写了
port = "8080"但 PHP 数组期望整数,不会自动转换——类型严格按字面量解析,"8080"就是字符串 - 注释、空行、缩进全被忽略,不影响解析结果;但语法错误(如漏引号、错用冒号)会抛
TOMLException
写入 TOML:不能直接 dump 数组,得先构造 TomlBuilder 或手动拼表结构
yosymfony/toml 没有类似 Python 的 toml.dump() 一键函数。你不能把普通 PHP 数组丢给它就生成合法 TOML —— 它需要显式构建表结构。
- 推荐方式:用
TomlBuilder逐层添加,例如:$builder->addTable("database")->add("host", "localhost") - 数组字段(如
ports = [8080, 8443])要用TomlArray包裹:$builder->add("ports", new TomlArray([8080, 8443])) - 键名含点号、空格或连字符(如
api.url)会被自动加双引号,不用手逃逸 -
null值不会写入输出 —— TOML 本身无 null 类型,$builder->add("log_path", null)等价于跳过该键
嵌套表和数组表:PHP 数组层级必须与 TOML 语法一一对应
TOML 的 [servers.alpha] 和 [[servers]] 在 PHP 中表现完全不同,混淆会导致数据丢失或解析失败。
立即学习“PHP免费学习笔记(深入)”;
-
[servers.alpha]是一个名为servers.alpha的单层表,对应 PHP 数组键$config["servers.alpha"](注意是字符串键,不是嵌套) -
[[servers]]是“表数组”,必须用 PHP 索引数组表示:$config["servers"] = [ ["name" => "alpha", "ip" => "10.0.0.1"], ["name" => "beta"] ] - 如果 TOML 写了
[[servers.alpha]],这是非法语法(TOML 不允许点号用于数组表名),解析会直接失败 - 动态访问嵌套字段别用点号路径:
$config["servers.alpha.ip"]不存在;必须按实际结构层层进入
容易被忽略的细节:大小写、空格缩进、时区时间全靠 TOML 文件本身守规矩
PHP 层不修正 TOML 语法缺陷,所有校验都在解析时爆发,且错误信息指向行号而非语义。
- TOML 键名默认大小写敏感:
Host和host是两个不同键;yosymfony/toml不做归一化 - 缩进必须用空格,不能用 Tab —— 编辑器若把空格转成 Tab,TOML 解析器会报错,但不提示“用了 Tab”,只报“unexpected token”
- 时间字段如
created_at = 2025-09-27T10:30:00+08:00会被解析为字符串,不是DateTime对象;要转时间需手动new DateTime($config["created_at"]) - 最常踩的坑:在
[database]下误用制表符缩进字段,或在字符串值末尾多加一个冒号(host = "localhost":),都会触发TOMLException



















