我经常会尝试运行PHP脚本,然后得到一个空白屏幕。没有错误信息;只有一个空屏幕。原因可能是一个简单的语法错误(错误的括号,缺少分号),或者函数调用失败,或者完全是其他原因。

很难找出哪里出了问题。我最终注释掉了代码,到处输入“echo”语句,等等,试图缩小问题的范围。但肯定有更好的办法,对吧?

是否有一种方法可以让PHP像Java那样产生有用的错误消息?


当前回答

可以通过注册钩子来显示最后一个错误或警告。

function shutdown(){
  var_dump(error_get_last());
}

register_shutdown_function('shutdown');

将此代码添加到index.php的开头将有助于调试问题。

其他回答

对于那些使用nginx并且即使文件<?PHP echo 123;在我的情况下,我在nginx配置文件中没有这个必要的PHP选项:

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

fastcgi_params文件中没有这个选项,所以PHP不起作用,日志中也没有任何错误。

PHP配置

php.ini中的2个条目指示错误的输出:

display_errors error_reporting

在生产中,display_errors通常设置为Off(这是一件好事,因为在生产站点中错误显示通常是不可取的!)

但是,在开发中,应该将其设置为On,以便显示错误。检查!

error_reporting(从PHP 5.3开始)默认设置为E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED(意思是,除了通知、严格标准和弃用通知之外的所有内容都会显示)。当不确定时,将其设置为E_ALL以显示所有错误。检查!

哇哇!没有检查!我不能改变我的php.ini!

真遗憾。通常共享主机不允许更改它们的php.ini文件,因此,遗憾的是,这个选项是不可用的。但是不要害怕!我们还有其他选择!

运行时配置

在所需的脚本中,我们可以在运行时更改php.ini条目!这意味着,它将在脚本运行时运行!甜蜜的!

error_reporting(E_ALL);
ini_set("display_errors", "On");

这两行代码与上面修改php.ini条目的效果相同!太棒了!

我仍然得到一个空白页/500错误!

这意味着脚本甚至还没有运行!这通常发生在语法错误的时候!

由于语法错误,脚本甚至无法进入运行时。它在编译时失败,这意味着它将使用php.ini中的值,如果没有更改,可能不允许显示错误。

错误日志

此外,PHP在默认情况下会记录错误。在共享主机中,它可能位于专用文件夹中,也可能位于与该脚本相同的文件夹中。

如果您可以访问php.ini,您可以在error_log条目下找到它。

可以通过注册钩子来显示最后一个错误或警告。

function shutdown(){
  var_dump(error_get_last());
}

register_shutdown_function('shutdown');

将此代码添加到index.php的开头将有助于调试问题。

你也可以像这样在终端(命令行)运行文件:

这将运行您的代码,并为您提供与在error.log中看到的任何错误相同的输出。它提到了错误和行号。

这是一个加载配置与运行时配置的问题

重要的是要认识到在编译或解析步骤中会发生语法错误或解析错误,这意味着PHP甚至在有机会执行任何代码之前就会退出。因此,如果你在运行时修改PHP的display_errors配置(这包括在代码中使用ini_set到使用.htaccess,这是一个运行时配置文件),那么只有默认加载的配置设置在起作用。

如何在开发中始终避免WSOD

为了避免WSOD,您需要确保加载的配置文件具有display_errors,并将error_reporting设置为-1(这相当于E_ALL,因为它确保无论您运行的是哪个版本的PHP,所有位都是打开的)。不要硬编码E_ALL的常量值,因为该值在不同版本的PHP之间可能会发生变化。

Loaded configuration is either your loaded php.ini file or your apache.conf or httpd.conf or virtualhost file. Those files are only read once during the startup stage (when you first start apache httpd or php-fpm, for example) and only overridden by runtime configuration changes. Making sure that display_errors = 1 and error_reporting = -1 in your loaded configuration file ensures that you will never see a WSOD regardless of syntax or parse error that occur before a runtime change like ini_set('display_errors', 1); or error_reporting(E_ALL); can take place.

如何找到你(php.ini)加载的配置文件

要定位您加载的配置文件,只需用以下代码创建一个新的PHP文件…

<?php
phpinfo();

然后将浏览器指向那里,查看已加载配置文件和已解析的附加.ini文件,它们通常位于phpinfo()的顶部,并将包括所有已加载配置文件的绝对路径。

如果你看到(none)而不是文件,这意味着你在配置文件(php.ini)路径中没有php.ini。因此,您可以从这里下载与PHP捆绑的库存PHP .ini,并将其复制到您的配置文件路径作为PHP .ini,然后确保您的PHP用户有足够的权限从该文件读取。您需要重新启动httpd或php-fpm来加载它。记住,这是PHP源代码附带的开发PHP .ini文件。所以请不要在生产中使用它!


只是不要在生产中这样做

这确实是在开发过程中避免WSOD的最佳方法。有人建议你把ini_set('display_errors', 1);或error_reporting (E_ALL);在你的PHP脚本顶部或使用.htaccess,就像你在这里所做的,不会帮助你避免WSOD当语法或解析错误发生时(就像你在这里的情况),如果你加载的配置文件已经display_errors关闭。

Many people (and stock installations of PHP) will use a production-ini file that has display_errors turned off by default, which typically results in this same frustration you've experienced here. Because PHP already has it turned off when it starts up, then encounters a syntax or parse error, and bails with nothing to output. You expect that your ini_set('display_errors',1); at the top of your PHP script should have avoided that, but it won't matter if PHP can't parse your code because it will never have reached the runtime.