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

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

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


当前回答

您可以在要调试的文件中包含以下行:

error_reporting(E_ALL);
ini_set('display_errors', '1');

这将覆盖PHP .ini中的默认设置,这只会使PHP向日志报告错误。

其他回答

如果你是一个ubuntu用户,那么在你的终端上运行这个命令

sudo tail -50f /var/log/apache2/error.log

它将显示最近的50个错误。 apache2有一个错误文件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.

PHP错误处理

有时,您的应用程序不会按预期的方式运行,从而导致错误。有许多原因可能导致错误,例如:

The Web server might run out of disk space A user might have entered an invalid value in a form field The file or database record that you were trying to access may not exist The application might not have permission to write to a file on the disk A service that the application needs to access might be temporarily unavailable These types of errors are known as run-time errors, because they occur at the time the script runs. They are distinct from syntax errors that need to be fixed before the script will run.

专业的应用程序必须能够优雅地处理此类运行时错误。通常,这意味着要更清楚、更准确地告知用户问题。

理解错误级别

通常,当出现阻止脚本正常运行的问题时,PHP引擎会触发一个错误。每个错误都由一个整数值和一个相关常数表示。下表列出了一些常见的错误级别:

PHP引擎在遇到脚本问题时触发错误,但是您也可以自己触发错误,以生成更用户友好的错误消息。这样可以使应用程序更加复杂。下面介绍PHP中处理错误的一些常用方法:

基本错误处理使用die()函数

<?php // Try to open a non-existent file
     $file = fopen("sample.txt", "r");
?>

如果文件不存在,你可能会得到这样的错误: 警告:fopen(sample.txt)[函数。在C:\wamp\www\project\test.php第2行中没有这样的文件或目录

如果我们遵循一些简单的步骤,我们可以防止用户得到这样的错误消息:

<?php
if(file_exists("sample.txt")){
    $file = fopen("sample.txt", "r");
} else{
    die("Error: The file you are trying to access doesn't exist.");
}
?>

现在如果你运行上面的脚本,你会得到这样的错误消息:错误:你试图访问的文件不存在。

正如您所看到的,通过在尝试访问文件之前实现一个简单的检查文件是否存在,我们可以生成一个对用户更有意义的错误消息。

上面使用的die()函数只是显示自定义错误消息,如果没有找到'sample.txt'文件,则终止当前脚本。

创建自定义错误处理程序

您可以创建自己的错误处理函数来处理PHP引擎生成的运行时错误。自定义错误处理程序为您提供了更大的灵活性和对错误的更好控制,它可以检查错误并决定如何处理错误,它可以向用户显示消息,将错误记录在文件或数据库中或通过电子邮件发送,尝试修复问题并继续执行,退出脚本执行或完全忽略错误。

自定义错误处理函数必须能够处理至少两个参数(errno和errstr),但是它可以选择接受额外的三个参数(errfile, errline和errcontext),如下所述:

下面是一个简单的自定义错误处理函数示例。这个处理程序customError()在发生错误时被触发,无论错误多么小。然后,它将错误的详细信息输出到浏览器,并停止脚本的执行。

<?php
// Error handler function
function customError($errno, $errstr){
    echo "<b>Error:</b> [$errno] $errstr";
}
?>

您需要告诉PHP使用您的自定义错误处理函数—只需调用内置的set_error_handler()函数,并传入函数名。

<?php
// Error handler function
function customError($errno, $errstr){
    echo "<b>Error:</b> [$errno] $errstr";
}
 
// Set error handler
set_error_handler("customError");
 
// Trigger error
echo($test);
?>

错误日志

在文本文件中记录错误消息

你也可以在日志文件中记录错误的详细信息,就像这样:

<?php
function calcDivision($dividend, $divisor){
    if($divisor == 0){
        trigger_error("calcDivision(): The divisor cannot be zero", E_USER_WARNING);
        return false;
    } else{
        return($dividend / $divisor);
    }
}
function customError($errno, $errstr, $errfile, $errline, $errcontext){
    $message = date("Y-m-d H:i:s - ");
    $message .= "Error: [" . $errno ."], " . "$errstr in $errfile on line $errline, ";
    $message .= "Variables:" . print_r($errcontext, true) . "\r\n";
    
    error_log($message, 3, "logs/app_errors.log");
    die("There was a problem, please try again.");
}
set_error_handler("customError");
echo calcDivision(10, 0);
echo "This will never be printed.";
?>

触发错误

尽管PHP引擎在遇到脚本问题时会触发错误,但是您自己也可以触发错误。这有助于使您的应用程序更加健壮,因为它可以在潜在的问题变成严重错误之前标记出来。

要在你的脚本中触发一个错误,调用trigger_error()函数,传入你想要生成的错误消息:

trigger_error("There was a problem.");

考虑下面的函数,它计算两个数的除法。

<?php
function calcDivision($dividend, $divisor){
    return($dividend / $divisor);
}
 
// Calling the function
echo calcDivision(10, 0);
?>

如果将一个0(0)值作为$除数参数传递,PHP引擎生成的错误将看起来像这样:警告:在C:\wamp\www\project\test.php第3行中除以0

这条消息看起来信息量不大。考虑以下示例,该示例使用trigger_error()函数生成错误。

<?php
function calcDivision($dividend, $divisor){
    if($divisor == 0){
        trigger_error("The divisor cannot be zero", E_USER_WARNING);
        return false;
    } else{
        return($dividend / $divisor);
    }
}
 
// Calling the function
echo calcDivision(10, 0);
?>

现在,脚本在第4行生成以下错误消息:警告:在C:\wamp\www\project\error.php中,除数不能为零

正如您所看到的,与前一个示例相比,第二个示例生成的错误消息更清楚地解释了问题。

参考:https://www.tutorialrepublic.com/php-tutorial/php-error-handling.php

除了error_reporting和display_errors ini设置外,您还可以从web服务器的日志文件中获得语法错误。当我在开发PHP时,我将我的开发系统的web服务器日志加载到我的编辑器中。每当我测试一个页面并得到一个空白屏幕时,日志文件就会失效,我的编辑器会询问我是否要重新加载它。当我这样做时,我跳到底部,那里有语法错误。例如:

[Sun Apr 19 19:09:11 2009] [error] [client 127.0.0.1] PHP Parse error:  syntax error, unexpected T_ENCAPSED_AND_WHITESPACE, expecting T_STRING or T_VARIABLE or T_NUM_STRING in D:\\webroot\\test\\test.php on line 9

你需要从PHP中获取有用错误的两行关键代码是:

ini_set('display_errors',1);
 error_reporting(E_ALL);

正如其他贡献者所指出的那样,出于安全原因,这些功能在默认情况下是关闭的。作为一个有用的技巧——当你设置你的网站时,为你的不同环境做一个切换是很方便的,这样在你的本地和开发环境中,这些错误默认是打开的。这可以通过以下代码实现(理想情况下是在index.php或配置文件中,这样从一开始就处于活动状态):

switch($_SERVER['SERVER_NAME'])
{
    // local
    case 'yourdomain.dev':
    // dev
    case 'dev.yourdomain.com':
        ini_set('display_errors',1);
        error_reporting(E_ALL);
    break;
    //live
    case 'yourdomain.com':
        //...
    break;
}