PHP的死亡白屏
现在我开始回到PHP,我开始记住为什么我放弃了。 我现在最讨厌的东西就是我所说的“PHP的死亡白屏”。 当PHP由于语法或其他原因而得到一个致命的错误时,它似乎总是死在没有实际发送任何东西给浏览器的情况下。 我已经将以下内容添加到了.htaccess
,而且似乎大部分时间都在工作,但在这些情况下不起作用。
php_value display_errors 1 php_value display_startup_errors 1 php_value error_reporting 2147483647 # E_ALL
我错过了什么吗? 目前,我觉得我需要刷新每隔几行代码,以免我犯了一个错误,不得不search很多页面,试图找出我犯的一个小错误。
编辑:例如,给出下面的两行代码:
$foo = array(':language' => $languageId; $foo = array(':language' => $languageId);
第一个将展现死亡的白色屏幕(即根本没有任何东西印在浏览器上),而第二个则会愉快地执行。
错误和警告通常出现在....\logs\php_error.log
或....\logs\apache_error.log
具体取决于您的php.ini设置。
也有用的错误往往是针对浏览器,但因为他们不是有效的HTML他们不显示。
因此, "tail -f
”你的日志文件,当你得到一个空白的屏幕使用IE浏览器“查看” – >“源”菜单选项来查看原始输出。
以下代码应显示所有错误:
<?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 ?>
使用此代码生成空白页的唯一方法是在closures处理程序中出现错误时。 我从我自己的cms中复制并粘贴了这个文件,但没有经过testing,但是我确定它能正常工作。
我总是在php脚本的最顶端使用这个语法。
ini_set('error_reporting', E_ALL); ini_set('display_errors', 'On'); //On or Off
这是一个加载与运行时configuration的问题
认识到在编译或parsing步骤中发生语法错误或parsing错误是非常重要的,这意味着在甚至有机会执行任何代码之前,PHP将会保释。 因此,如果您在运行时修改PHP的display_errors
configuration(这包括在代码中使用ini_set
来使用.htaccess(运行时configuration文件)),那么只有默认的加载configuration设置在运行。
如何总是避免WSOD的发展
为了避免WSOD,你要确保你的加载的configuration文件的 display_errors
on和error_reporting
设置为-1
( 这是相当于E_ALL,因为它确保所有的位都打开,不pipe你运行的是哪个版本的PHP )。 不要硬编码E_ALL的常量值,因为该值在不同版本的PHP之间可能会发生变化。
加载的configuration是您的加载的php.ini
文件或您的apache.conf
或httpd.conf
或虚拟主机文件。 这些文件只能在启动阶段读取一次(例如,首次启动apache httpd或php-fpm时),并且只能由运行时configuration更改覆盖。 确保在加载的configuration文件中, display_errors = 1
和error_reporting = -1
可以确保您永远不会看到WSOD,无论在运行时更改之前发生的语法或parsing错误如ini_set('display_errors', 1);
或者error_reporting(E_ALL);
可以发生。
如何find你的(php.ini)加载的configuration文件
要find您加载的configuration文件,只需创build一个只包含以下代码的新PHP文件即可
<?php phpinfo();
然后将浏览器指向那里,查看加载的configuration文件和附加的.ini文件 ,这些文件通常位于phpinfo()
的顶部,并包含所有加载的configuration文件的绝对path。
如果您看到(none)
而不是该文件,这意味着您在configuration文件(php.ini)path中没有php.ini 。 所以你可以从这里下载与PHP捆绑在一起的股票php.ini ,并将其作为php.ini复制到你的configuration文件path,然后确保你的php用户有足够的权限来读取该文件。 您需要重新启动httpd或php-fpm才能加载。请记住,这是PHP源代码捆绑的开发 php.ini文件。 所以请不要在生产中使用它!
只是不要在生产中这样做
这确实是避免开发WSOD的最好方法。 任何人build议你把ini_set('display_errors', 1);
或者error_reporting(E_ALL);
在您的PHP脚本的顶部或使用.htaccess(就像您在此处所做的那样),如果加载的configuration文件已closuresdisplay_errors
,则不会帮助您避免发生语法或语法分析错误(如您的情况)。
许多人(和PHP的股票安装)将使用默认情况下closuresdisplay_errors
的生产ini文件,这通常会导致您在这里遇到的同样的挫折感。 由于PHP在启动时已经closures了,所以遇到语法或parsing错误,并且没有任何输出。 你期望你的ini_set('display_errors',1);
在你的PHP脚本的顶部应该避免这种情况,但是如果PHP不能parsing你的代码,那么它将永远不会到达运行时。
不知道,如果它会帮助,但这是我的PHP项目的标准configuration文件的一部分。 即使在我自己的服务器上,我也不会太依赖apache的configuration。
我从来没有消失的错误问题,所以也许这里的东西会给你一个想法。
**编辑显示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>"); }
可以注册一个钩子以使最后的错误或警告可见。
function shutdown(){ var_dump(error_get_last()); } register_shutdown_function('shutdown');
将此代码添加到您的开始index.php将帮助您debugging问题。
打开你的php.ini,确保它设置为:
display_errors = On
重启你的服务器。
尝试设置您的实际PHP文件中的错误报告级别。 或者像其他人所build议的那样,检查你的服务器设置 – 可能是php.ini中的某些内容,或者对你的主机有一些限制。 不要只依靠.htaccess。 另外,在排除故障时,print_r您可能会觉得可疑的任何variables。
你确定PHP实际上是从.htaccess中获取' display_errors
'设置吗? 检查phpinfo()
函数的输出以确保。
另外,你应该检查以确保你没有使用' @
',如果你已经使用'@include …'或者'@some_function(…)',它可能会使你的错误变得沉默跟踪。
一些应用程序自己处理这些指令,通过调用如下所示:
error_reporting(E_ALL & ~E_DEPRECATED); or error_reporting(0);
因此覆盖你的.htaccess设置。
使用@inexistent_function_call();
在你的代码将导致英特尔悄悄死亡和中止脚本parsing。 你应该检查无效的函数,并尽量不要使用错误抑制运算符(@ char)
当fastcgi_params
或fastcgi.conf
configuration文件未正确包含在服务器configuration中时,我也看到了这样的错误。 所以对我的修复是一个愚蠢的:
include /etc/nginx/fastcgi_params;
花了我一个小时才发现…
您也可以在terminal(命令行)中运行文件,如下所示: php -f filename.php
。
这将运行你的代码,并给你相同的输出,以防在error.log
看到任何错误。 它提到了错误和行号。
对于那些使用nginx,甚至有一个白色屏幕的文件与<?php echo 123;
。 在我的情况下,我没有在nginxconfiguration文件中的PHP这个必需的选项:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
此选项不在fastcgi_params文件中,所以PHP不起作用,日志中没有任何错误。
如果错误是在PHP代码中,则可以在代码中使用error_reporting()函数将所有报告设置为。
但是,这不处理PHP崩溃的情况。 有关信息仅在服务器日志中可用。 也许您无法访问这些内容,但许多与我合作的托pipe提供商都有一些方法可以让您访问它。 例如,我最喜欢的方法是在.php所在的当前目录中创builderror_log文件。 尝试search那里或与您的托pipe服务提供商有关这个。