编程

PHP 8.3: PHP INI 环境变量语法支持回退值

1015 2023-11-01 00:36:00

PHP 支持使用 PHP 的字符串插值语法将 PHP INI 值替换为环境变量。如果指定的环境变量不可用,INI 解析器会使用空字符串。在 PHP 8.3 中,该语法扩展到支持环境变量未设置时声明回退值。

session.name = ${SESSION_NAME}
sendmail_from = "${MAIL_FROM_USER}@${MAIL_FROM_DOMAIN}"
ini_get('session.name');
ini_get('sendmail_from');

所有的 PHP 版本都支持上述语法,用以在 PHP INI 文件中使用环境变量。在此例中,session.name INI 值会被设置为 SESSION_NAME 环境变量(如果设置了该环境变量),否则为空字符串。sendmail_from 值使用字符串插值,PHP 替换可用的环境变量以及在中间的 @ 字符。

当没有环境变量时,PHP 在启动或者解析时不会发出任何警告,而且总是使用空字符串对其进行替换。

PHP 8.3扩展了对 INI 环境变量替换的支持,支持其声明回退值。

在 PHP 8.3 以后,可以可选地使用 :- 符号,在其后紧跟着回退值来声明回退值。上述代码中的 INI 值声明现在可以使用回退值进行设置:

session.name = ${SESSION_NAME:-Foo}
sendmail_from = "${MAIL_FROM_USER:-info}@${MAIL_FROM_DOMAIN:-example.com}"
ini_get('session.name');
ini_get('sendmail_from');

PHP 8.3 通过在 :- 符号后指定回退值来支持解析。

例如,如果设置了 SESSION_NAME 环境变量, 那么 session.name 的值将是该环境变量的值,否则它现在将使用 Foo 值。

如果 MAIL_FROM_USERMAIL_FROM_DOMAIN 环境变量都未设置,sendmail_from 值也将回落到 info@example.com。如果其中任何一个可用,则将使用环境变量。

支持的功能

所有返回、设置和解析 INI 值的 PHP 函数都支持回退值语法。这包括:

  • ini_get()
  • ini_get_all()
  • ini_set()
  • get_cfg_var()
  • parse_ini_string()
  • parse_ini_file()

递归替换

环境变量回退语法也支持将环境变量作为回退值,这反过来也可以支持其他回退变量。

session.name = ${SESSION_NAME:-${APP_NAME:-Login}}

在这个声明中,如果 SESSIOON_NAME 环境变量可用,PHP 会使用该环境变量。否则,如果 APP_NAME 可用,PHP 会尝试使用它。最后,再使用 Login 作为回退值。

PHP 常量作为回退值

对于支持在运行时修改 PHP INI 值的情况,INI 语法也支持使用 PHP 常量作为回退值:

define('APP_NAME', "MyApp");
parse_ini_string('name = ${SESSION_NAME:-APP_NAME}');
[
    "name" => "MyApp",
]

类型强制

PHP 试图强制回退值也遵循与标准字符串字面量配置值相同的规则。

true_true = true
true_fallabck = ${FOOBAR:-true}

解析时,上面的值都会被强制转换成 “1”

false_false = false
false_fallabck = ${FOOBAR:-false}

解析时,上面所有的值都会强制转换成 ""(而非 "0")。

null 常量和不存在的环境变量使用空字符串("")替代

安全考虑

即使是此更新之前,解析用户提供的任意 INI 值,必须验证使其不包含不应向用户公开的环境值。

此更新后,该语法也获取了 PHP 常量支持,因此也必须将其认证考虑在内。

解析用户提供的 INI 字符串和文件时的安全考虑

默认情况下,parse_ini_fileparse_ini_string 函数会处理环境变量和 PHP 常量。在解析 INI 值时,总是使用 INI_SCANNER_RAW 标志以确保 PHP 的环境变量和常量替换是禁用的。

向后兼容性影响

新语法不能向后移植到旧的 PHP 版本。但是,用户端 INI 解析器可以通过使用 ${FOO:-BAR} 语法正确地插值来模仿这种行为。

尝试分析使用此新语法的 INI 字符串和文件不会引发任何异常或发出错误。它们将被一个空字符串无声地替换,就好像名为 FOO:-BAR 的环境变量不存在一样。