配置文件

配置文件(php.ini)在 PHP 启动时被读取。对于服务器模块版本的 PHP,仅在 web 服务器启动时读取一次。对于 CGICLI 版本,每次调用都会读取。

php.ini 的搜索路径如下(按顺序):

  • SAPI 模块所指定的位置(Apache 2 中的 PHPIniDir 指令,CGI 和 CLI 中的 -c 命令行选项)。
  • PHPRC 环境变量。
  • 可以为不同版本的 PHP 指定不同的 php.ini 文件位置。注册表目录所在的位置取决于你的系统是 32 位还是 64 位。32-bit 的 PHP 运行在 32-bit 的系统或 64-bit 的 PHP 运行在 64-bit 系统时使用 [(HKEY_LOCAL_MACHINE\SOFTWARE\PHP] 32-bit 的 PHP 运行在 64-bit 的系统上时,则使用 [HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\PHP]] 替代。 系统版本跟 PHP 版本架构一致时,会按以下顺序依次进行检查: [HKEY_LOCAL_MACHINE\SOFTWARE\PHP\x.y.z][HKEY_LOCAL_MACHINE\SOFTWARE\PHP\x.y][HKEY_LOCAL_MACHINE\SOFTWARE\PHP\x],其中的 x,y 和 z 指的是 PHP 主版本号,次版本号和发行批次。 对于 32 bit 版本的 PHP 运行在 64 bit 系统上的情况,则会按以下顺序依次进行检查: [HKEY_LOCAL_MACHINE\SOFTWARE\WOW6421Node\PHP\x.y.z][HKEY_LOCAL_MACHINE\SOFTWARE\WOW6421Node\PHP\x.y][HKEY_LOCAL_MACHINE\SOFTWARE\WOW6421Node\PHP\x],其中的 x,y 和 z 指的是 PHP 主版本号,次版本号和发行批次。如果在其中任何目录下的 IniFilePath 有键值,则第一个值将被用作 php.ini 的位置(仅适用于 Windows)。
  • [HKEY_LOCAL_MACHINE\SOFTWARE\PHP]IniFilePath 的值(Windows 注册表位置)。
  • 当前工作目录(对于 CLI)。
  • web 服务器目录(对于 SAPI 模块)或 PHP 所在目录(Windows 下其它情况)。
  • Windows 目录(C:\windowsC:\winnt),或 --with-config-file-path 编译时选项指定的位置。

如果存在 php-SAPI.ini(SAPI 是当前所用的 SAPI 名称,因此实际文件名为 php-cli.iniphp-apache.ini 等),则会用它替代 php.ini。SAPI 的名称可以用 php_sapi_name() 来测定。

注意:

Apache web 服务器在启动时会把目录转到根目录,这将导致 PHP 尝试在根目录下读取 php.ini,如果存在的话。

php.ini 中可以使用环境变量,如下示例:

示例 #1 php.ini 中的环境变量

; PHP_MEMORY_LIMIT 来自于环境变量的值
memory_limit = ${PHP_MEMORY_LIMIT}

由扩展库处理的 php.ini 指令,其文档分别在各扩展库的页面。内核配置选项见附录。不过也许不是所有的 PHP 指令都在手册中有文档说明。要得到自己的 PHP 版本中的配置指令完整列表,请阅读 php.ini 文件,其中都有注释。此外,也许从 Git 得到的» 最新版 php.ini 也有帮助。

示例 #2 php.ini 例子

; any text on a line after an unquoted semicolon (;) is ignored
[php] ; section markers (text within square brackets) are also ignored
; Boolean values can be set to either:
;    true, on, yes
; or false, off, no, none
register_globals = off
track_errors = yes

; you can enclose strings in double-quotes
include_path = ".:/usr/local/lib/php"

; backslashes are treated the same as any other character
include_path = ".;c:\php\lib"

在 .ini 文件内可能会引用已存在的 .ini 变量。例如:open_basedir = ${open_basedir} ":/new/dir"

扫描路径配置

可以通过配置,让 PHP 在读完 php.ini 后,扫描指定路径中的附加 .ini 配置文件。编译时通过 --with-config-file-scan-dir 参数来指定要扫描的目录。扫描路径也可以通过环境变量 PHP_INI_SCAN_DIR 来设置。

通过在扫描路径配置中加入特定系统的目录分隔符(Windows、NetWare 和 RISC OS 下是 ;;其它操作系统下是 :;该值可以通过 PHP 常量 PATH_SEPARATOR 获取),还可以设置多个扫描路径。如果 PHP_INI_SCAN_DIR 为空,PHP 一样会扫描在编译时指定的 --with-config-file-scan-dir 此路径。

对于每个目录而言,PHP 会以首字符顺序为优先级,扫描该目录下所有的 .ini 结尾的配置文件。所有被截入的配置文件,可以通过 php_ini_scanned_files() 函数来获取列表,也可以通过 PHP 命令行加入 --ini 参数来查看。

以下假设 PHP 配置为 --with-config-file-scan-dir=/etc/php.d
并且目录分隔符为 :

$ php
  PHP 会加载 /etc/php.d/*.ini 全部配置文件。

$ PHP_INI_SCAN_DIR=/usr/local/etc/php.d php
  PHP 会加载 /usr/local/etc/php.d/*.ini 全部配置文件。

$ PHP_INI_SCAN_DIR=:/usr/local/etc/php.d php
  PHP 会加载 /etc/php.d/*.ini 下的全部配置文件,然后加载
  /usr/local/etc/php.d/*.ini 下的全部配置文件。

$ PHP_INI_SCAN_DIR=/usr/local/etc/php.d: php
  PHP 会加载 /usr/local/etc/php.d/*.ini 下的全部配置文件,然后加载
  /etc/php.d/*.ini 下的全部配置文件。
添加备注

用户贡献的备注 4 notes

up
26
weili
3 years ago
For someone who's also wondering.

PHP can work even if there is no configuration file(php.ini) loaded,
it will simply applies the default values to directives.
up
2
Pictor13
11 months ago
Notice that `error_reporting` CANNOT be interpolated with an environment variable (e.g. `error_reporting = ${PHP_ERROR_REPORTING}`).

`error_reporting` is treated differently than other directives:
if assigned an environment variable, this will be silently ignored and replaced with value `0` (aka no-reporting).

I couldn't find documentation about it.
Is maybe an info that should be added in https://github.com/php/php-src/blob/8f5156fcba9906664ecd97e4c279ee980e522121/php.ini-production#L451-L500 ?

I am not aware if this specific behavior affects only `error_reporting` or also other directive.
up
-1
michael at maildrop dot cc
3 months ago
I'm not sure why the comment saying you can use constants is downvoted so much. This is amazing news and just what I was looking for.

Having a configuration like:
php_admin_value[error_log] = "/logfolder/php-fpm-"PHP_VERSION".$pool.log"

will nicely log to /logfolder/php-fpm-8.3.10.mypool.log , which is really useful if you have multiple versions of PHP running and want to keep your log files separate and not have to fiddle with the configuration each time you update. A list of the pre-defined constants is here ( https://www.php.net/manual/en/reserved.constants.php#reserved.constants.core ) The PHP_*_VERSION, PHP_VERSION, PHP_OS_FAMILY, and maybe PHP_SAPI are useful in this case.
up
-5
atv dot seth at gmail dot com
11 months ago
For anyone who wants to ignore any directory entirely

On a linux Redhat distro (this was on EL9):

; if using php-fpm, put this file in place"
/etc/systemd/system/php-fpm.service.d/override.conf
[Service]
Environment="PHP_INI_SCAN_DIR="

; do a systemd config reload:
systemctl daemon-reload

; if you want to make sure php on the cli fails if it's not passing 'PHP_INI_SCAN_DIR= php' (this should also affect both linux normal+system users?) then drop this file in place:
cat /etc/php.d/00-dont-use-phpd.ini
auto_prepend_file=MISSING_ENV__PHP_INI_SCAN_DIR__SEE_ETC_PHPD_00_DONT_USE_PHPD_INI
; don't allow php.d directory to load in files
; you must pass 'PHP_INI_SCAN_DIR= ' before your php command on the cli
; reference:
; https://www.php.net/manual/en/configuration.file.php#configuration.file.scan
To Top