display_errors应该怎么使用,开发环境与生产环境的配置区别
PHP开发过程中,display_errors是一个非常常用的配置项。代码出现语法错误、警告、通知或者异常时,是否直接把错误信息显示给当前请求的用户,很大程度上取决于错误处理和显示配置。
问题在于,适合开发环境的错误显示方式,并不适合直接用于生产服务器。开发者希望看到完整的错误信息,因为这能够快速定位文件、行号和调用链;普通网站用户则不应该看到服务器路径、SQL语句、配置文件位置以及其他内部信息。因此,开发环境和生产环境需要采用不同的错误处理策略。
display_errors解决的是“错误是否显示出来”,而不是“错误是否发生”或者“错误是否记录”。
例如:
display_errors = On
表示满足错误报告条件的错误可以输出到当前响应中。对于Web程序来说,用户可能直接在浏览器页面看到PHP产生的错误信息。
如果设置:
display_errors = Off
则错误不会因为这个配置而直接输出给用户。
但这里有一个非常重要的区别:display_errors = Off并不等于错误自动写入日志。是否记录错误还涉及另一个配置:
log_errors = On
以及:
error_log = /path/to/php-error.log
因此,生产环境通常应该采用“关闭页面显示、开启错误日志”的组合,而不是简单地把所有错误都关闭。
开发环境通常可以使用:
display_errors = On
display_startup_errors = On
error_reporting = E_ALL
这样开发者能够尽可能完整地看到PHP运行期间产生的问题。
其中,error_reporting和display_errors承担的是不同任务。error_reporting决定哪些级别的错误进入错误报告范围,而display_errors决定这些错误是否输出给当前请求。
例如:
error_reporting(E_ALL);
ini_set('display_errors', '1');
这两行代码分别解决不同的问题。第一行让PHP报告所有支持报告的错误类型,第二行尝试让这些错误显示出来。
生产环境则通常应该采用:
display_errors = Off
display_startup_errors = Off
log_errors = On
error_reporting = E_ALL
这里有一个容易被误解的地方。生产环境并不意味着应该把error_reporting降低到只剩E_ERROR | E_WARNING | E_PARSE。
如果服务器关闭了display_errors,那么即使记录E_NOTICE、E_WARNING、E_DEPRECATED等信息,也不会直接显示给网站访客。对生产环境来说,完整记录错误通常比主动忽略问题更有价值。
当然,日志也需要根据项目规模进行管理。如果所有错误都记录下来,日志文件可能迅速增长,因此需要配合日志轮转、保留周期和集中式日志系统进行管理。
error_log的具体路径也不能写成所有服务器都通用的固定值。Linux上的PHP-FPM、Apache模块、Nginx加PHP-FPM、Docker容器等运行方式,日志处理方式都可能不同。
例如某些Linux服务器可以使用:
error_log = /var/log/php_errors.log
但PHP进程必须拥有相应的写入权限,而且系统可能已经将PHP错误交给PHP-FPM、Web服务器或者systemd日志系统处理。直接指定一个不存在或者没有权限写入的目录,可能导致开发者误以为PHP没有产生错误。
对于PHP-FPM环境,实际部署时还应该检查PHP-FPM使用的配置文件,而不能只修改CLI环境中的php.ini。
这是很多PHP开发者遇到“我明明打开display_errors了,为什么网页还是不显示”的原因之一。
命令行执行:
php --ini
可以查看CLI模式使用的配置文件。
而网站通过PHP-FPM运行时,使用的配置可能不同。可以在测试环境建立一个简单的PHP页面,通过phpinfo()或者ini_get()查看当前Web请求实际加载的配置。
例如:
echo ini_get('display_errors');
echo ini_get('log_errors');
echo ini_get('error_reporting');
echo ini_get('error_log');
这样检查到的是当前PHP运行环境中的实际配置,而不是开发者以为自己修改成功的配置。
ini_set()也经常被用于临时调试。例如:
ini_set('display_errors', '1');
error_reporting(E_ALL);
这种方式对于开发环境中的单个脚本非常方便,但不能把它当成所有PHP配置都可以在运行时修改的通用方法。
PHP的配置项具有不同的修改权限级别,有些配置可以在脚本运行过程中修改,有些则受到服务器配置或者PHP运行模式限制。因此,如果ini_set()没有达到预期效果,应该检查该配置项的PHP_INI模式以及当前运行环境。
此外,语法错误和某些启动阶段错误也需要特别注意。display_startup_errors控制的是PHP启动阶段产生的错误显示。开发环境可以暂时打开它,生产环境通常关闭。
例如:
display_startup_errors = Off
如果PHP程序在解析代码之前就发生配置、扩展或者启动相关问题,仅仅依靠脚本内部的ini_set()可能已经来不及修改配置,因为脚本本身还没有正常执行。
这也是为什么服务器级别的PHP配置必须正确设置。
另一个常见误区是把error_reporting(0)当成生产环境的错误处理方案:
error_reporting(0);
这实际上只是降低错误报告范围,可能让大量问题被隐藏。它并不能替代正确的日志系统,也不能解决错误本身。
对于生产系统,更合理的思路是让PHP尽可能记录有价值的错误,同时阻止内部信息进入HTTP响应。
尤其是SaaS、CMS、电商和后台管理系统,错误信息可能包含文件路径、数据库表名、SQL语句、服务器目录结构以及第三方服务调用信息。如果这些内容直接返回给用户,就可能帮助攻击者了解应用内部结构。
例如:
Warning: mysqli_connect(): ...
in /home/example/public_html/includes/db.php on line 27
对于开发者来说,这条信息非常有价值;对于普通访客来说,却完全没有必要看到。
因此生产环境可以向用户返回一个通用错误页面,同时把详细信息写入服务器日志。这样开发人员可以通过日志定位问题,而外部用户只能看到有限的错误提示。
对于使用Laravel等框架的应用,情况又有所不同。框架通常会建立自己的异常处理和日志机制,开发环境可能提供详细异常页面,生产环境则隐藏堆栈信息并将异常写入日志。此时PHP的display_errors仍然存在,但最终呈现给用户的错误页面可能已经由框架接管。
这并不意味着PHP底层配置不重要。错误如果已经通过PHP输出,框架未必能够完全按照预期处理。因此,PHP配置、Web服务器、PHP-FPM以及应用框架的错误处理策略需要保持一致。
Docker环境同样如此。容器中的PHP配置可以通过自定义php.ini、配置文件目录或者镜像构建流程统一管理。关键不是把配置硬编码在某个业务PHP文件里,而是让开发、测试和生产环境拥有明确的配置边界。
开发环境可以追求信息完整:
display_errors = On
display_startup_errors = On
error_reporting = E_ALL
生产环境则强调信息隔离:
display_errors = Off
display_startup_errors = Off
log_errors = On
error_reporting = E_ALL
实际项目还需要根据服务器环境配置日志输出位置,并做好权限控制和日志轮转。
如果生产服务器突然出现PHP页面空白,首先不要急着把display_errors永久打开。更合理的办法是检查PHP错误日志、PHP-FPM日志以及Web服务器日志。如果必须临时调试,也应该尽量缩小影响范围,并在完成排查后恢复生产配置。
对于命令行脚本,调试方式则更加灵活。例如:
php -d display_errors=1 script.php
这种方式只针对当前CLI进程改变配置,不需要修改整个服务器的PHP配置文件。对于Cron任务,也应该重点检查CLI使用的PHP版本、配置文件和错误日志,因为Cron运行环境与Web请求环境可能并不完全相同。
display_errors本身并不是一个安全开关,也不是一个性能优化开关。它解决的是错误信息是否直接进入当前响应的问题。真正完整的PHP错误处理,需要同时考虑错误报告、错误显示、错误日志、异常处理、日志权限以及日志生命周期。
对于开发环境,详细错误信息能够提高排错效率;对于生产环境,错误应该尽可能被记录而不是被隐藏。关闭页面上的错误显示,并不意味着停止记录错误,而是把“开发者需要知道的信息”和“网站访客应该看到的信息”分开。
这也是PHP部署中最重要的原则之一:开发环境应该让问题容易被发现,生产环境应该让问题能够被追踪,同时避免服务器内部信息暴露给外部用户。display_errors只是这套机制中的一个开关,真正可靠的错误处理体系,还需要error_reporting、log_errors、error_log以及应用自身的异常处理机制共同配合。
display_errors 应该怎么使用?开发环境与生产环境的配置区别
喜欢这篇报道?
使用下面的功能,方便以后继续阅读和分享 MNewsTV
关于文章收藏
收藏不需要注册帐号,收藏信息仅保存在当前浏览器中。
删除收藏请进入「我的收藏」进行管理。
分享 Facebook | X | WhatsApp | LinkedIn
捐助(Paypal): https://www.paypal.me/observeccp 订阅中国观察电报 Telegram : https://t.me/s/ObserveCCP