php.ini 配置
php.ini 是 PHP 的核心配置文件,几乎控制着 PHP 运行的所有行为。从内存限制、上传大小到错误显示方式、扩展加载,每一项都直接影响着你的 PHP 应用的运行效果和安全性。本节将全面介绍 php.ini 的查找方法、核心配置项详解、配置分区机制,以及不同环境下的配置建议。
前置知识
在阅读本节之前,你需要了解:
- PHP 的运行模式(CLI / Web / FPM,参见 CLI 命令行模式 和 Web 模式(CGI/FPM))
- 基本的命令行操作
- Web 服务器(Nginx/Apache)的基本概念
php.ini 文件查找
使用 php -i 命令查找
bash
# 查找当前加载的 php.ini 文件位置
php -i | grep "Loaded Configuration File"
# 输出示例:
# Loaded Configuration File => /etc/php/8.3/cli/php.ini
# 查找所有扫描的配置文件目录
php -i | grep "Scan for additional .ini files"
# 输出示例:
# Scan this dir for additional .ini files => /etc/php/8.3/cli/conf.d
# Additional .ini files parsed => /etc/php/8.3/cli/conf.d/10-opcache.ini,
# /etc/php/8.3/cli/conf.d/10-pdo.ini, /etc/php/8.3/cli/conf.d/20-calendar.ini,
# ...使用 php --ini 快捷命令
bash
# PHP 提供了更简洁的方式查看配置文件位置
php --ini
# 输出示例:
# Configuration File (php.ini) Path: /etc/php/8.3/cli
# Loaded Configuration File: /etc/php/8.3/cli/php.ini
# Scan for additional .ini files in: /etc/php/8.3/cli/conf.d
# Additional .ini files: /etc/php/8.3/cli/conf.d/10-opcache.ini,
# /etc/php/8.3/cli/conf.d/10-pdo.ini,
# ...不同 SAPI 的 php.ini 位置
PHP 为不同的 SAPI 可以使用不同的 php.ini 文件:
/etc/php/8.3/
├── cli/
│ ├── php.ini ← CLI 模式使用的配置
│ └── conf.d/ ← CLI 扩展配置
├── fpm/
│ ├── php.ini ← PHP-FPM 模式使用的配置
│ └── conf.d/ ← FPM 扩展配置
├── apache2/
│ ├── php.ini ← Apache mod_php 使用的配置
│ └── conf.d/ ← Apache 扩展配置
└── mods-available/ ← 扩展模块文件建议分别配置
强烈建议为 CLI 和 FPM 分别配置 php.ini。例如:
- CLI 可以设置
memory_limit = -1(无限制) - FPM 应设置合理的
memory_limit = 256M - CLI 可以开启
display_errors = On - FPM 应关闭
display_errors = Off
核心配置项详解
资源限制配置
memory_limit
ini
; 脚本可使用的最大内存量
; 格式:数字 + 单位(K/M/G),-1 表示无限制
; 默认值:128M
memory_limit = 128M
; 常见设置:
; memory_limit = 256M — 一般 Web 应用
; memory_limit = 512M — 处理大量数据的应用
; memory_limit = 1G — 图片/视频处理
; memory_limit = -1 — CLI 模式(无限制)php
<?php
declare(strict_types=1);
// 查看当前内存限制
echo "memory_limit: " . ini_get('memory_limit') . "\n";
// 查看当前脚本内存使用情况
echo "已使用: " . round(memory_get_usage(true) / 1024 / 1024, 2) . " MB\n";
echo "峰值: " . round(memory_get_peak_usage(true) / 1024 / 1024, 2) . " MB\n";
// 当内存不足时会触发 Fatal Error
// Allowed memory size of 134217728 bytes exhaustedmax_execution_time
ini
; 脚本最大执行时间(秒)
; 0 表示无限制
; 默认值:30
; 注意:此配置在 CLI 模式下默认无效(默认为 0)
max_execution_time = 30
; 对于耗时的操作可以临时增加
; 建议使用队列处理耗时任务php
<?php
declare(strict_types=1);
// 查看最大执行时间
echo "max_execution_time: " . ini_get('max_execution_time') . "\n";
// 运行时临时修改(不能超过 php.ini 中的设置上限)
set_time_limit(60); // 设置为 60 秒
set_time_limit(0); // 无限制(需要确认安全)
// 对于需要长时间运行的操作,推荐使用队列
// $job = dispatch(new ProcessLargeFile($filePath));max_input_time
ini
; PHP 解析输入数据(POST/GET/文件上传)的最大时间(秒)
; 默认值:-1(使用 max_execution_time 的值)
; 如果表单提交或文件上传较大,可以适当增加
max_input_time = 60文件上传配置
upload_max_filesize
ini
; 单个上传文件的最大允许大小
; 必须小于等于 post_max_size
; 默认值:2M
upload_max_filesize = 20Mpost_max_size
ini
; POST 请求体的最大大小(包括所有表单数据和上传文件)
; 必须大于等于 upload_max_filesize
; 如果同时上传多个文件,需要根据文件数量调整
; 默认值:8M
post_max_size = 25M
; 计算公式:
; post_max_size >= upload_max_filesize * 最大同时上传文件数 + 表单数据大小upload 相关配置
ini
; 最大上传文件数(PHP 8.2+ 废弃,使用 upload_max_filesize 和 post_max_size 控制)
; max_file_uploads = 20
; 文件上传的临时目录
; 默认使用系统临时目录
upload_tmp_dir = /tmp
; 是否启用 HTTP 文件上传
; 默认值:On
file_uploads = On
; 上传文件的最大大小(0 表示无限制,PHP 8.2+)
; max_file_uploads = 20文件上传配置关系
upload_max_filesize、post_max_size、memory_limit 三者必须协调:
memory_limit >= post_max_size + 脚本运行所需内存
post_max_size >= upload_max_filesize * 文件数量 + POST 数据大小
upload_max_filesize >= 实际需要上传的文件大小常见错误配置导致的问题:
upload_max_filesize = 20M但post_max_size = 8M→ 上传超过 8M 的文件时 POST 为空post_max_size = 25M但memory_limit = 128M→ 多个并发上传可能导致内存溢出
错误处理配置
display_errors
ini
; 是否将错误信息输出到屏幕(HTML 输出)
; 生产环境必须设为 Off
; 默认值:On
display_errors = Off ; 生产环境
; display_errors = On ; 开发环境error_reporting
ini
; 控制报告哪些级别的错误
; 默认值:E_ALL & ~E_DEPRECATED & ~E_STRICT
; 推荐生产环境设置:
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE
; 推荐开发环境设置:
; error_reporting = E_ALL
; 可用的错误级别:
; E_ERROR — 致命运行时错误
; E_WARNING — 运行时警告
; E_PARSE — 编译时解析错误
; E_NOTICE — 运行时通知
; E_CORE_ERROR — PHP 启动时的致命错误
; E_CORE_WARNING — PHP 启动时的警告
; E_COMPILE_ERROR — 编译时的致命错误
; E_COMPILE_WARNING — 编译时的警告
; E_USER_ERROR — 用户触发的错误
; E_USER_WARNING — 用户触发的警告
; E_USER_NOTICE — 用户触发的通知
; E_DEPRECATED — 弃用警告
; E_STRICT — 兼容性建议
; E_RECOVERABLE_ERROR — 可恢复的致命错误
; E_ALL — 所有错误(不包括 E_STRICT)php
<?php
declare(strict_types=1);
// 运行时修改错误报告级别
error_reporting(E_ALL);
// 触发不同级别的错误示例
trigger_error("这是一个 Notice", E_USER_NOTICE);
trigger_error("这是一个 Warning", E_USER_WARNING);
trigger_error("这是一个 Error", E_USER_ERROR);log_errors
ini
; 是否将错误信息记录到日志文件
; 生产环境必须开启
; 默认值:On
log_errors = On
; 错误日志文件路径
error_log = /var/log/php/error.log
; 注意:在 CLI 模式下,如果 error_log 为空,错误会输出到 STDERR
; CLI 模式下可以指定:
; error_log = /var/log/php/cli-error.logerror_log
ini
; 错误日志文件路径
; 可以是文件路径或 syslog
error_log = /var/log/php/error.log
; 使用系统日志(syslog)
; error_log = syslog
; 如果设置为空字符串,错误输出到 SAPI 标准错误输出
; error_log =php
<?php
declare(strict_types=1);
// 使用 error_log() 函数记录日志
error_log("这是一条普通日志");
error_log("这是一条警告日志", 3, "/var/log/php/app.log");
// 记录数组或对象
error_log("调试信息: " . print_r($_SERVER, true));日期时区配置
date.timezone
ini
; 设置默认时区
; 默认为空(PHP 会根据系统设置猜测,但会产生警告)
; 必须明确设置
; 常见值:
date.timezone = Asia/Shanghai ; 中国(东八区)
; date.timezone = Asia/Tokyo ; 日本
; date.timezone = America/New_York ; 纽约
; date.timezone = UTC ; 协调世界时
; date.timezone = Europe/London ; 伦敦
; 查看所有支持的时区列表
; php -r 'print_r(timezone_identifiers_list());'php
<?php
declare(strict_types=1);
// 查看当前时区
echo "时区: " . date_default_timezone_get() . "\n";
// 运行时修改时区
date_default_timezone_set('Asia/Shanghai');
echo "当前时间: " . date('Y-m-d H:i:s') . "\n";
echo "时间戳: " . time() . "\n";时区警告
如果 date.timezone 未设置,PHP 在使用日期函数时会抛出警告:
Warning: date(): It is not safe to rely on the system's timezone settings.
You are required to use the date.timezone setting or the date_default_timezone_set() function.session 配置
ini
; Session 存储处理器
session.save_handler = files
; Session 文件保存路径
session.save_path = "/var/lib/php/sessions"
; Session 名称(Cookie 名称)
session.name = PHPSESSID
; Session 在 Cookie 中的生命周期(秒),0 表示浏览器关闭即失效
session.cookie_lifetime = 0
; Session 服务端文件的生命周期(秒)
session.gc_maxlifetime = 1440 ; 24 分钟
; Session 使用严格模式(PHP 7.1+)
session.use_strict_mode = 1
; 仅通过 Cookie 传递 Session ID(防止 Session 固定攻击)
session.use_only_cookies = 1
; Cookie 中的 Session ID 仅通过 HTTP 访问(防止 JS 窃取)
session.cookie_httponly = 1
; Cookie 中的 Session ID 仅通过 HTTPS 传输(PHP 7.1+)
; session.cookie_secure = 1 ; HTTPS 环境开启
session.cookie_secure = 0 ; HTTP 环境关闭
; Cookie 的 SameSite 属性(PHP 7.3+)
session.cookie_samesite = Lax ; Strict / Lax / None
; Session 自动启动(建议关闭,手动控制)
session.auto_start = 0OPcache 配置
ini
[OPcache]
; 是否启用 OPcache(强烈建议开启)
; CLI 模式默认关闭,FPM 模式默认开启
opcache.enable = 1
opcache.enable_cli = 1
; OPcache 共享内存大小(MB)
; 生产环境建议 128M+
opcache.memory_consumption = 128
; 存储缓存的内部字符串数量
opcache.interned_strings_buffer = 16
; 最大缓存文件数
opcache.max_accelerated_files = 20000
; 检查脚本时间戳的频率(秒)
; 0 表示不检查(生产环境推荐,性能最佳)
; 1 表示每次请求都检查(开发环境推荐)
opcache.revalidate_freq = 0
; 开发环境下关闭 OPcache(确保代码变更即时生效)
; opcache.enable = 0
; 开启 JIT(PHP 8.0+)
; opcache.jit = 1205
; opcache.jit_buffer_size = 64M配置分区(PHP_INI_*)
PHP 配置项按可修改范围分为四个级别,这决定了配置项可以在哪些层面被修改:
分区级别说明
| 级别 | 常量名 | 说明 |
|---|---|---|
| ALL | PHP_INI_ALL | 可在所有地方修改(php.ini、.htaccess、ini_set、.user.ini) |
| PERDIR | PHP_INI_PERDIR | 可在 php.ini、.htaccess、.user.ini 中修改,不可用 ini_set |
| SYSTEM | PHP_INI_SYSTEM | 只能在 php.ini 或 httpd.conf 中修改 |
| MODAL | PHP_INI_MODAL | 仅在 php.ini 中可设置(通常为只读信息) |
常见配置项的分区
php
<?php
declare(strict_types=1);
/**
* 各配置项所属分区一览
*/
$configScopes = [
// PHP_INI_ALL — 可用 ini_set() 修改
'display_errors' => 'ALL',
'error_reporting' => 'ALL',
'error_log' => 'ALL',
'date.timezone' => 'ALL',
'memory_limit' => 'ALL',
'max_execution_time' => 'ALL',
'include_path' => 'ALL',
'auto_prepend_file' => 'ALL',
'auto_append_file' => 'ALL',
'default_socket_timeout'=> 'ALL',
'upload_max_filesize' => 'ALL',
// PHP_INI_PERDIR — 不可用 ini_set() 修改
'upload_max_filesize' => 'PERDIR',
'post_max_size' => 'PERDIR',
'file_uploads' => 'PERDIR',
'max_input_time' => 'PERDIR',
'max_input_vars' => 'PERDIR',
'session.save_path' => 'PERDIR',
'session.name' => 'PERDIR',
'session.cookie_lifetime' => 'PERDIR',
'session.cookie_httponly' => 'PERDIR',
'session.cookie_secure' => 'PERDIR',
'session.use_strict_mode' => 'PERDIR',
'mbstring.func_overload' => 'PERDIR',
// PHP_INI_SYSTEM — 只能在 php.ini 中设置
'disable_functions' => 'SYSTEM',
'disable_classes' => 'SYSTEM',
'open_basedir' => 'SYSTEM',
'extension_dir' => 'SYSTEM',
'zend_extension' => 'SYSTEM',
'opcache.enable' => 'SYSTEM',
'opcache.enable_cli' => 'SYSTEM',
'opcache.memory_consumption' => 'SYSTEM',
];
// 使用 ini_get_all() 查看配置项的访问级别
$allConfigs = ini_get_all();
// 查找特定配置项的访问级别
$memoryLimitScope = $allConfigs['memory_limit']['access'] ?? 'unknown';
echo "memory_limit access level: {$memoryLimitScope}\n";
// 输出: memory_limit access level: 7
// PHP_INI_ALL=7, PHP_INI_USER=1, PHP_INI_PERDIR=2, PHP_INI_SYSTEM=4检查配置项是否可修改
php
<?php
declare(strict_types=1);
/**
* 检查某个 ini 配置项是否可以通过 ini_set() 修改
*/
function isIniSettable(string $configName): bool
{
// PHP_INI_USER = 1
// PHP_INI_PERDIR = 2
// PHP_INI_SYSTEM = 4
// PHP_INI_ALL = 7 (USER | PERDIR)
$scope = ini_get_all($configName, false)[$configName]['access'] ?? 0;
// 只有 USER 标记(bit 0)的配置才可用 ini_set() 修改
return ($scope & 1) === 1;
}
// 测试
$testConfigs = [
'display_errors', // ALL → 可修改
'memory_limit', // ALL → 可修改
'upload_max_filesize', // PERDIR → 不可修改
'post_max_size', // PERDIR → 不可修改
'open_basedir', // SYSTEM → 不可修改
'disable_functions', // SYSTEM → 不可修改
];
foreach ($testConfigs as $name) {
$result = isIniSettable($name) ? '可修改' : '不可修改';
echo "ini_set('{$name}'): {$result}\n";
}实战示例:生产环境 php.ini 模板
ini
; ================================
; PHP 8.3 生产环境 php.ini 配置模板
; ================================
[PHP]
; ========== 资源限制 ==========
memory_limit = 256M
max_execution_time = 30
max_input_time = 60
max_input_vars = 3000
; ========== 错误处理 ==========
display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE
log_errors = On
error_log = /var/log/php/error.log
html_errors = Off
; ========== 文件上传 ==========
file_uploads = On
upload_max_filesize = 20M
post_max_size = 25M
upload_tmp_dir = /tmp
max_file_uploads = 20
; ========== 日期时区 ==========
date.timezone = Asia/Shanghai
; ========== Session ==========
session.save_handler = files
session.save_path = "/var/lib/php/sessions"
session.use_strict_mode = 1
session.use_only_cookies = 1
session.cookie_httponly = 1
session.cookie_secure = 1
session.cookie_samesite = Lax
session.gc_maxlifetime = 1440
session.auto_start = 0
; ========== 安全 ==========
; 限制 PHP 可访问的目录
open_basedir = /var/www/html:/tmp:/usr/share/php:/var/lib/php/sessions
; 禁用危险函数
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,
curl_multi_exec,parse_ini_file,show_source
disable_classes =
; 隐藏 PHP 版本信息
expose_php = Off
; 防止 HTTP 请求体过大攻击
max_input_nesting_level = 64
; 防止包含远程文件
allow_url_include = Off
allow_url_fopen = On
; 防止 CGI 注入
cgi.fix_pathinfo = 0
[Date]
date.timezone = Asia/Shanghai
[Session]
session.save_handler = files
session.save_path = "/var/lib/php/sessions"
session.use_strict_mode = 1
[OPcache]
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.revalidate_freq = 0
opcache.validate_timestamps = 0
opcache.save_comments = 1
opcache.jit = 1205
opcache.jit_buffer_size = 64M
[mbstring]
mbstring.internal_encoding = UTF-8
mbstring.http_input = UTF-8
mbstring.http_output = UTF-8
[curl]
; 限制 cURL 重定向次数,防止 SSRF 攻击
curl.max_redirs = 5注意事项
1. 配置生效顺序
PHP 配置可能被多个层面覆盖,了解优先级非常重要:
php.ini < 扩展 .ini < .user.ini < httpd.conf < .htaccess < ini_set() < 脚本内设置
↑ ↑
低优先级 高优先级但注意:PHP_INI_SYSTEM 级别的配置只能在 php.ini 中设置,后续层面无法覆盖。
2. 修改配置后重启
修改 php.ini 后,需要根据 SAPI 类型重启对应的服务:
bash
# CLI:无需重启,下次执行新脚本时生效
# PHP-FPM:优雅重载
sudo systemctl reload php8.3-fpm
# 或
sudo service php8.3-fpm reload
# Apache mod_php:重启 Apache
sudo systemctl restart apache2
# 或
sudo systemctl restart httpd3. 查看最终生效的配置值
bash
# 使用 php -i 查看所有配置
php -i | grep memory_limit
# 使用 ini_get() 在脚本中查看
php -r 'echo ini_get("memory_limit");'
# 创建 phpinfo.php 在 Web 环境查看
# phpinfo.php
# <?php phpinfo();phpinfo() 安全
phpinfo() 会暴露所有 PHP 配置信息,包括服务器路径、模块版本等敏感信息。生产环境务必删除或限制访问 phpinfo.php。
最佳实践
1. 分环境管理 php.ini
# 使用分离的 php.ini 文件
/etc/php/8.3/
├── fpm/
│ ├── php.ini ← 生产配置(关闭 display_errors 等)
│ ├── php.ini.development ← 开发配置(开启 display_errors 等)
│ └── php.ini.production ← 生产配置的备份
├── cli/
│ ├── php.ini ← CLI 专用配置
│ └── conf.d/切换环境时使用软链接:
bash
# 开发环境
sudo ln -sf /etc/php/8.3/fpm/php.ini.development /etc/php/8.3/fpm/php.ini
sudo systemctl reload php8.3-fpm
# 生产环境
sudo ln -sf /etc/php/8.3/fpm/php.ini.production /etc/php/8.3/fpm/php.ini
sudo systemctl reload php8.3-fpm2. 配置验证
php
<?php
declare(strict_types=1);
/**
* PHP 配置检查工具
* 用于检查关键配置项是否符合生产环境要求
*/
function checkPhpConfig(): array
{
$checks = [
[
'name' => 'display_errors',
'expected' => '0',
'operator' => '==',
'severity' => 'critical',
],
[
'name' => 'expose_php',
'expected' => '',
'operator' => '==',
'severity' => 'warning',
],
[
'name' => 'allow_url_include',
'expected' => '0',
'operator' => '==',
'severity' => 'critical',
],
[
'name' => 'memory_limit',
'expected' => '128M',
'operator' => '>=',
'severity' => 'info',
],
[
'name' => 'date.timezone',
'expected' => 'Asia/Shanghai',
'operator' => '==',
'severity' => 'warning',
],
[
'name' => 'opcache.enable',
'expected' => '1',
'operator' => '==',
'severity' => 'warning',
],
];
$results = [];
foreach ($checks as $check) {
$actual = ini_get($check['name']);
$passed = match ($check['operator']) {
'==' => $actual == $check['expected'],
'>=' => version_compare($actual, $check['expected'], '>='),
default => false,
};
$results[] = [
'name' => $check['name'],
'actual' => $actual,
'expected' => $check['expected'],
'operator' => $check['operator'],
'passed' => $passed,
'severity' => $check['severity'],
];
}
return $results;
}
// 执行检查并输出报告
$report = checkPhpConfig();
foreach ($report as $item) {
$status = $item['passed'] ? '[PASS]' : '[FAIL]';
echo "{$status} {$item['name']}: actual={$item['actual']} expected={$item['operator']}{$item['expected']}\n";
}3. 不要在 php.ini 中硬编码路径
ini
; 推荐:使用相对路径或变量
upload_tmp_dir = /tmp
; 避免:硬编码特定项目路径
; upload_tmp_dir = /home/user/project/tmp
; 项目特定的配置应在 PHP-FPM pool 配置或 .user.ini 中设置下一节
你已经掌握了 php.ini 核心配置项的用法和分区机制,接下来将学习运行时配置(ini_set()),了解如何在 PHP 脚本中动态修改配置。