PHP的死亡白屏

时间:2009-09-25 03:36:14

标签: php error-handling error-reporting wsod

现在我开始回到PHP,我开始记得为什么我放弃了它。目前我盘子里最烦人的事情就是我所说的“PHP的死亡白屏”。当PHP由于语法或其他原因而出现致命错误时,似乎总是在没有实际向浏览器发送任何内容的情况下死亡。我已将以下内容添加到我的.htaccess中,并且它似乎在大多数情况下都有效,但在这些情况下它不起作用。

php_value display_errors 1
php_value display_startup_errors 1
php_value error_reporting 2147483647 # E_ALL

我错过了什么吗?目前我觉得我需要刷新我编写的每几行代码,以免我犯了一个错误并且必须搜索许多页面,试图找出我犯的一个小错误......

编辑:例如,给出以下两行代码:

$foo = array(':language' => $languageId;
$foo = array(':language' => $languageId);

第一个将显示死亡的白色屏幕(即,没有任何内容打印到浏览器),而第二个将显示为愉快。

15 个答案:

答案 0 :(得分:167)

以下代码应显示所有错误:

<?php

// ----------------------------------------------------------------------------------------------------
// - Display Errors
// ----------------------------------------------------------------------------------------------------
ini_set('display_errors', 'On');
ini_set('html_errors', 0);

// ----------------------------------------------------------------------------------------------------
// - Error Reporting
// ----------------------------------------------------------------------------------------------------
error_reporting(-1);

// ----------------------------------------------------------------------------------------------------
// - Shutdown Handler
// ----------------------------------------------------------------------------------------------------
function ShutdownHandler()
{
    if(@is_array($error = @error_get_last()))
    {
        return(@call_user_func_array('ErrorHandler', $error));
    };

    return(TRUE);
};

register_shutdown_function('ShutdownHandler');

// ----------------------------------------------------------------------------------------------------
// - Error Handler
// ----------------------------------------------------------------------------------------------------
function ErrorHandler($type, $message, $file, $line)
{
    $_ERRORS = Array(
        0x0001 => 'E_ERROR',
        0x0002 => 'E_WARNING',
        0x0004 => 'E_PARSE',
        0x0008 => 'E_NOTICE',
        0x0010 => 'E_CORE_ERROR',
        0x0020 => 'E_CORE_WARNING',
        0x0040 => 'E_COMPILE_ERROR',
        0x0080 => 'E_COMPILE_WARNING',
        0x0100 => 'E_USER_ERROR',
        0x0200 => 'E_USER_WARNING',
        0x0400 => 'E_USER_NOTICE',
        0x0800 => 'E_STRICT',
        0x1000 => 'E_RECOVERABLE_ERROR',
        0x2000 => 'E_DEPRECATED',
        0x4000 => 'E_USER_DEPRECATED'
    );

    if(!@is_string($name = @array_search($type, @array_flip($_ERRORS))))
    {
        $name = 'E_UNKNOWN';
    };

    return(print(@sprintf("%s Error in file \xBB%s\xAB at line %d: %s\n", $name, @basename($file), $line, $message)));
};

$old_error_handler = set_error_handler("ErrorHandler");

// other php code

?>

使用此代码生成空白页的唯一方法是在关闭处理程序中出现错误。我在没有测试的情况下从我自己的cms复制并粘贴了它,但我确信它有效。

答案 1 :(得分:57)

错误和警告通常会出现在....\logs\php_error.log....\logs\apache_error.log中,具体取决于您的php.ini设置。

同样有用的错误通常是针对浏览器的,但由于它们不是有效的html,因此不会显示。

所以"tail -f“你的日志文件,当你得到一个空白的屏幕时,使用IE”查看“ - &gt;”源“菜单选项来查看原始输出。

答案 2 :(得分:30)

我总是在php脚本的顶部使用这种语法。

ini_set('error_reporting', E_ALL);
ini_set('display_errors', 'On');  //On or Off

答案 3 :(得分:23)

可以注册一个钩子,使上一个错误或警告可见。

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

register_shutdown_function('shutdown');

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

答案 4 :(得分:18)

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

认识到在编译解析步骤期间发生语法错误或解析错误很重要,这意味着PHP将在它之前保释#39 ;甚至有机会执行你的任何代码。因此,如果您在运行时修改PHP display_errors配置,(这包括在代码中使用ini_set到使用.htaccess(运行时配置文件)),那么只有默认<正在使用strong>加载的配置设置。

如何始终避免开发中的WSOD

要避免使用WSOD,您需要确保已加载的配置文件已启用display_errors并且error_reporting设置为-1这是等效的E_ALL因为它确保所有位都打开,无论您运行的是哪个版本的PHP 。不要对E_ALL的常量值进行硬编码,因为该值可能会在不同版本的PHP之间发生变化。

加载的配置是加载的php.ini文件或apache.confhttpd.conf或虚拟主机文件。这些文件只在启动阶段(例如,当您第一次启动apache httpd或php-fpm时)读取一次,并且仅被运行时配置更改覆盖。确保加载的配置文件中的display_errors = 1error_reporting = -1确保您永远不会看到 WSOD ,无论在运行时更改之前发生的语法或解析错误如{{1}或ini_set('display_errors', 1);可以发生。

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

要找到已加载的配置文件,只需创建一个只包含以下代码的新PHP文件...

error_reporting(E_ALL);

然后将浏览器指向该位置并查看已加载的配置文件已解析的其他.ini文件,这些文件通常位于<?php phpinfo(); 的顶部,并且包括所有已加载配置文件的绝对路径。

如果您看到phpinfo()而不是文件,则表示您在配置文件(php.ini)路径中没有php.ini。所以你可以download the stock php.ini bundled with PHP from here并将其作为php.ini复制到你的配置文件路径,然后确保你的php用户有足够的权限从该文件中读取。您需要重新启动httpd或php-fpm才能加载它。请记住,这是与PHP源捆绑在一起的 development php.ini文件。所以请不要在生产中使用它!

在生产中不要这样做

这确实是避免WSOD开发的最佳方法。任何人建议您将(none)ini_set('display_errors', 1);置于PHP脚本的顶部或使用.htaccess,就像您在此处所做的那样,并不会帮助您在发生语法或解析错误时避免使用WSOD(如在这种情况下,如果您加载的配置文件已关闭error_reporting(E_ALL);

许多人(以及PHP的库存安装)将使用默认关闭display_errors的production-ini文件,这通常会导致您在此遇到的同样挫败感。因为PHP在启动时已经关闭了它,然后遇到语法或解析错误,并且没有任何输出就会失败。您希望PHP脚本顶部的display_errors应该避免这种情况,但如果PHP无法解析您的代码,那将无关紧要,因为它永远不会到达运行时。

答案 5 :(得分:15)

Dunno,如果它会有所帮助,但这里有一个我的标准配置文件的PHP项目。即使在我自己的服务器上,我也不会太依赖apache配置。

我从来没有消失的错误问题,所以这里的某些内容可能会给你一个想法。

已修改为显示APPLICATON_LIVE

/*
APPLICATION_LIVE will be used in process to tell if we are in a development or production environment.  It's generally set as early as possible (often the first code to run), before any config, url routing, etc.
*/

if ( preg_match( "%^(www.)?livedomain.com$%", $_SERVER["HTTP_HOST"]) ) {
    define('APPLICATION_LIVE', true);
} elseif ( preg_match( "%^(www.)?devdomain.net$%", $_SERVER["HTTP_HOST"]) ) {
    define('APPLICATION_LIVE', false);
} else {
    die("INVALID HOST REQUEST (".$_SERVER["HTTP_HOST"].")");
    // Log or take other appropriate action.
}


/*
--------------------------------------------------------------------
DEFAULT ERROR HANDLING
--------------------------------------------------------------------
Default error logging.  Some of these may be changed later based on APPLICATION_LIVE.
*/
error_reporting(E_ALL & ~E_STRICT);
ini_set ( "display_errors", "0");
ini_set ( "display_startup_errors", "0");
ini_set ( "log_errors", 1);
ini_set ( "log_errors_max_len", 0);
ini_set ( "error_log", APPLICATION_ROOT."logs/php_error_log.txt");
ini_set ( "display_errors", "0");
ini_set ( "display_startup_errors", "0");

if ( ! APPLICATION_LIVE ) {
    // A few changes to error handling for development.
    // We will want errors to be visible during development.
    ini_set ( "display_errors", "1");
    ini_set ( "display_startup_errors", "1");
    ini_set ( "html_errors", "1");
    ini_set ( "docref_root", "http://www.php.net/");
    ini_set ( "error_prepend_string", "<div style='color:red; font-family:verdana; border:1px solid red; padding:5px;'>");
    ini_set ( "error_append_string", "</div>");
}

答案 6 :(得分:6)

打开你的php.ini, 确保它设置为:

display_errors = On

重新启动服务器。

答案 7 :(得分:2)

尝试在实际的php文件中设置错误报告级别。或者,正如其他人所建议的那样,检查您的服务器设置 - 它可能是php.ini中的内容,或者对您的主机有一些限制。不要只依靠.htaccess。此外,在进行故障排除时,print_r您可能认为可疑的任何变量。

答案 8 :(得分:2)

你确定PHP实际上正在从.htaccess中获取'display_errors'设置吗?检查phpinfo()函数的输出以确保。

此外,您应该检查以确保没有使用“@”,如果您使用了“@include ...”或“@some_function(...),它可能会使您的错误失效)',在堆栈跟踪的某处。

答案 9 :(得分:2)

对于那些使用nginx并且即使对于fs的文件也有白屏的人。在我的情况下,我在nginx配置文件中没有这个必需的PHP选项:

<?php echo 123;

此选项不在fastcgi_params文件中,因此PHP无效并且日志中没有任何错误。

答案 10 :(得分:1)

某些应用程序本身通过调用以下内容来处理这些指令:

error_reporting(E_ALL & ~E_DEPRECATED); or error_reporting(0);

从而覆盖你的.htaccess设置。

答案 11 :(得分:1)

在代码中使用@inexistent_function_call();会导致解释器悄然死亡并中止脚本解析。您应该检查无效函数并尽量不使用错误抑制运算符(@ char)

答案 12 :(得分:1)

fastcgi_paramsfastcgi.conf配置文件没有正确包含在服务器配置中时,我也看到了这样的错误。所以对我的修复很愚蠢:

include /etc/nginx/fastcgi_params;

花了我小时来找出...

答案 13 :(得分:1)

您也可以在终端(命令行)中运行该文件,如下所示:php -f filename.php

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

答案 14 :(得分:-1)

如果错误在PHP代码中,您可以在代码中使用error_reporting()函数来设置所有报告。

但是,这不能处理PHP崩溃时的情况。有关它的信息仅在服务器日志中可用。也许您无法访问这些,但我与之合作的许多托管服务提供商都有一些方法可以让您访问它。例如,我最喜欢的方法是在.php所在的当前目录中创建error_log文件。尝试在那里搜索或与您的托管服务提供商联系。