如何在PHP中获得有用的错误消息?

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

弄清楚出了什么问题是非常困难的。 我最终注释掉了代码,在各处输入“ echo”语句,等等,试图缩小问题的范围。 但是肯定有更好的方法吧?

有没有办法像Java一样使PHP产生有用的错误消息?


#1楼

为了快速进行实用的故障排除,我通常建议在SO上执行以下操作:

error_reporting(~0); ini_set('display_errors', 1);

放在出现问题的脚本的开头。 这不是完美的,完美的变体是您还在php.ini启用了该功能,并在PHP中记录了错误以捕获语法和启动错误。

此处概述的设置显示所有错误,注意和警告,包括严格的错误,无论哪个PHP版本。

接下来要考虑的事情:

  • 安装Xdebug并使用IDE启用远程调试。

另请参阅:


#2楼

错误和警告通常显示在....\\logs\\php_error.log....\\logs\\apache_error.log具体取决于您的php.ini设置。

有用的错误通常也指向浏览器,但由于它们不是有效的html,因此不会显示。

因此, "tail -f ”您的日志文件,当您出现空白屏幕时,请使用IE的“视图”->“源”菜单选项来查看原始输出。


#3楼

我一直在php脚本的最顶部使用此语法。

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

#4楼

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>");
}

#5楼

在页面顶部选择一个参数

error_reporting(E_ERROR | E_WARNING | E_PARSE);

#6楼

打开错误报告是正确的解决方案,但是它似乎在打开错误报告的程序中无效,而仅在随后包含的程序中有效。

因此,我总是创建一个文件/程序(我通常将其称为“ genwrap.php”),该文件/程序具有与此处流行的解决方案相同的代码(即,打开错误报告),并且还包括我实际上想要的页面呼叫。

有2个步骤可实现此调试;

一个 -创建genwrap.php并将以下代码放入其中:

<?php
error_reporting(-1);
ini_set('display_errors', 'On');

include($_REQUEST['page']);
?>

-通过genwrap.php更改要调试的程序/页面的链接,

例如:更改:

$.ajax('dir/pgm.php?param=val').done(function(data) { /* ... */

$.ajax('dir/genwrap.php?page=pgm.php&param=val').done(function(data) { /* ... */

#7楼

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

<?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复制并粘贴了它,但是我确信它是可行的。


#8楼

对于开发人员来说,“错误”是最有用的事情,他们可以了解他们的错误并解决它们,以使系统完美运行。

PHP提供了一些更好的方法来了解开发人员代码为何以及在何处获取错误,因此,通过了解这些错误,开发人员可以通过多种方式使他们的代码变得更好。

在脚本顶部编写以下两行以获取所有错误消息的最佳方法:

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

在IDE中使用调试器工具(如xdebug)的另一种方法。


#9楼

PHP配置

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

  1. display_errors
  2. error_reporting

生产中 ,通常将display_errors设置为Off (这是一件好事,因为通常不希望在生产现场显示错误!)。

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

error_reporting (自PHP 5.3起)默认设置为E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED (意味着,所有内容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条目下找到它。


#10楼

要从PHP中获得有用的错误,您需要执行以下两条关键操作:

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

正如其他贡献者所指出的,出于安全原因,默认情况下将其关闭。 作为有用的提示-在设置站点时,方便地针对不同的环境进行切换,以使这些错误在本地和开发环境中默认为ON。 这可以通过以下代码来实现(最好在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;
}

#11楼

您可能还想尝试将PHPStorm用作代码编辑器。 在编辑器中键入内容时,它将立即发现许多PHP和其他语法错误。


#12楼

error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);
ini_set('html_errors', 1);

另外,您可以使用xdebug获得更多详细信息。


#13楼

如果您是Ubuntu用户,则转到终端并运行此命令

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

它将显示最近的50个错误。 apache2的错误文件error.log记录了所有错误。


#14楼

除了上述许多出色的答案外,您还可以在项目中实现以下两个功能。 他们将在应用程序/脚本退出之前捕获所有非语法错误。 在这些功能内,您可以进行回溯并记录日志或向公众呈现令人愉快的“站点正在维护”消息。

致命错误:

register_shutdown_function

http://php.net/manual/zh/function.register-shutdown-function.php

错误:

set_error_handler

http://php.net/manual/zh/function.set-error-handler.php

回溯:

debug_backtrace

http://php.net/manual/zh/function.debug-backtrace.php


#15楼

我建议使用Nette Tracy以更好地可视化PHP中的错误和异常:

Nette Tracy屏幕截图


#16楼

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

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

如何在开发中始终避免WSOD

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

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

如何找到您的(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); 如果您加载的配置文件已关闭display_errors ,则在PHP脚本的顶部或像此处一样使用.htaccess并不会帮助您避免在发生语法或解析错误时(如此处的情况)避免WSOD。

许多人(和PHP的原始安装程序)将使用默认情况下已关闭display_errors的production-ini文件,这通常会导致您在此处遇到同样的挫败感。 由于PHP在启动时已经将其关闭,因此遇到语法或解析错误,并且无法输出任何内容。 您期望您的ini_set('display_errors',1); PHP脚本的顶部应该避免这种情况,但是PHP无法解析您的代码并不重要,因为它永远不会到达运行时。


#17楼

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

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

register_shutdown_function('shutdown');

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


#18楼

对于那些使用nginx并具有白色屏幕的用户,即使对于<?php echo 123;文件也是如此<?php echo 123; 。 在我的情况下,nginx配置文件中没有PHP的必需选项:

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

该选项不在fastcgi_params文件中,因此PHP无法正常工作,并且日志中没有任何错误。


#19楼

打开您的php.ini,确保将其设置为:

display_errors = On

重新启动服务器。


#20楼

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

#21楼

除了所有出色的答案之外,我还要特别提及MySQLi和PDO库。

为了...

  1. 总是看到与数据库相关的错误,并且
  2. 避免检查方法的返回类型以查看是否出错

最好的选择是配置库以引发异常

MySQLi的

将其添加到脚本顶部附近

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

在使用new mysqli()mysqli_connect()之前,最好将其放置。

PDO

设置PDO::ATTR_ERRMODE属性PDO::ERRMODE_EXCEPTION您的连接实例。 您可以在构造函数中执行此操作

$pdo = new PDO('driver:host=localhost;...', 'username', 'password', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);

或创建后

$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

#22楼

这个答案是由冗余部门的部门带来的。

  1. ini_set() / php.ini / .htaccess / .user.ini

    现在已经充分介绍了display_errorserror_reporting设置。 但是只是回顾一下何时使用哪个选项:

    • ini_set()error_reporting()仅适用于运行时错误。
    • php.ini应编辑php.ini以进行开发设置。 (Web服务器和CLI版本通常具有不同的php.ini)。
    • .htaccess标志仅适用于过时的设置(查找新的托管服务商!管理良好的服务器更便宜。)
    • .user.ini是现代安装程序(FCGI / FPM)的部分php.ini。

    作为运行时错误的粗略替代方案,您通常可以使用:

     set_error_handler("var_dump"); // ignores error_reporting and `@` suppression 
  2. error_get_last()

    禁用error_display时,可用于检索上次运行时通知/警告/错误。

  3. $php_errormsg

    是一个超局部变量,还包含最后一个PHP运行时消息。

  4. isset()即将消失!

    我知道这会得罪很多人,但issetempty 应该由新人使用。 您可以验证代码正常工作添加通知抑制。 但是从来没有。

    我们最近收到的许多“无法解决的问题”问题都是由于输入错误而导致的,例如:

     if(isset($_POST['sumbit'])) # ↑↑ 

    如果您的代码被isset / empty / array_keys_exists您将不会得到任何有用的通知。 有时使用@会更明智 ,因此通知和警告至少会记录在日志中。

  5. assert_options(ASSERT_ACTIVE|ASSERT_WARNING);

    获取有关assert()节的警告。 (这很不常见,但是更精通的代码可能包含一些代码。)

    PHP7也需要php.ini中的zend.assertions=1

  6. declare(strict_types=1);

    将PHP转换为严格类型的语言并不能解决很多逻辑错误,但绝对是调试的一种选择。

  7. PDO / MySQLi

    @Phil已经提到了PDO / MySQLi错误报告选项。 当然,其他数据库API也有类似的选项。

  8. json_last_error() + json_last_error_msg

    用于JSON解析。

  9. preg_last_error()

    对于regexen。

  10. CURLOPT_VERBOSE

    要调试curl请求,至少需要CURLOPT_VERBOSE。

  11. shell/exec()

    同样,shell命令执行不会自行产生错误。 您总是需要2>&1并查看$ errno。


#23楼

以下启用所有错误:

ini_set('display_startup_errors', 1);
ini_set('display_errors', 1);
error_reporting(-1);

另请参阅以下链接


#24楼

如果您超酷,则可以尝试:

$test_server = $_SERVER['SERVER_NAME'] == "127.0.0.1" || $_SERVER['SERVER_NAME'] == "localhost" || substr($_SERVER['SERVER_NAME'],0,3) == "192";

ini_set('display_errors',$test_server);
error_reporting(E_ALL|E_STRICT);

仅在本地运行时才会显示错误。 它还为您提供了test_server变量,以便在适当的其他地方使用。

在脚本运行之前不会发生任何错误,但是对于我所犯的99%的错误,这不是问题。


#25楼

要坚持这一点并使之具有意义,您可以编辑php.ini文件。 它通常存储在/etc/php.ini/etc/php/php.ini ,但是更多本地php.ini可能会覆盖它,具体取决于您的托管服务提供商的设置准则。 在顶部检查phpinfo()文件的“ Loaded Configuration File ”,以确保最后加载哪个Loaded Configuration File

在该文件中搜索display_errors。 应该只有3个实例,其中2个已注释。

将未注释的行更改为:

display_errors = stdout

#26楼

对于语法错误,您需要在php.ini中启用错误显示。 默认情况下,这些功能是关闭的,因为您不希望“客户”看到错误消息。 检查 PHP文档中的此页面 ,以获取有关2个指令的信息: error_reportingdisplay_errorsdisplay_errors可能是您想要更改的一种。 如果您无法修改php.ini,也可以将以下行添加到.htaccess文件中:

php_flag  display_errors        on
php_value error_reporting       2039

您可能要考虑将E_ALL的值(如Gumbo所述)用于您的PHP版本,以进行error_reporting以获取所有错误。 更多信息

其他3个项目:(1)您可以检查错误日志文件,因为它将包含所有错误(除非已禁用日志记录)。 (2)添加以下两行将帮助您调试不是语法错误的错误:

error_reporting(-1);
ini_set('display_errors', 'On');

(3)另一个选择是使用编辑器,例如PhpEd ,在键入时检查错误。 PhpEd还带有调试器,该调试器可以提供更多详细信息。 (PhpEd调试器与xdebug非常相似,并且直接集成到编辑器中,因此您可以使用1个程序来完成所有工作。)

卡特曼的链接也很好: http//www.ibm.com/developerworks/library/os-debug/


#27楼

您可以在PHP中注册自己的错误处理程序 。 例如,在这些晦涩的情况下,将所有错误转储到文件中可能会帮助您。 请注意,无论当前的error_reporting设置为什么,函数都会被调用。 很基本的例子:

function dump_error_to_file($errno, $errstr) {
    file_put_contents('/tmp/php-errors', date('Y-m-d H:i:s - ') . $errstr, FILE_APPEND);
}
set_error_handler('dump_error_to_file');

#28楼

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

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

这将覆盖php.ini中的默认设置,该默认设置仅使PHP将错误报告给日志。


#29楼

error_reporting(E_ALL | E_STRICT);

并在php.ini中打开显示错误


#30楼

您可以启用完整的错误报告(包括通知和严格的消息)。 有人觉得这太冗长,但是值得一试。 将error_reporting设置为E_ALL | E_STRICT 您的php.ini中的E_ALL | E_STRICT

error_reporting = E_ALL | E_STRICT

E_STRICT将通知您不赞成使用的功能,并为您提供有关执行某些任务的最佳方法的建议。

如果您不希望收到通知,但发现其他消息类型有帮助,请尝试排除通知:

error_reporting = (E_ALL | E_STRICT) & ~E_NOTICE

还要确保在php.ini中启用了display_errors 。 如果您的PHP版本低于5.2.4,请将其设置为On

display_errors = "On"

如果您的版本是5.2.4或更高版本,请使用:

display_errors = "stderr"

#31楼

有一个非常有用的扩展名为“ xdebug ”,它也可以使您的报告更好。


#32楼

FirePHP也可能有用。


#33楼

要打开完整的错误报告,请将其添加到脚本中:

error_reporting(E_ALL);

这甚至会显示最小的警告。 并且,以防万一:

ini_set('display_errors', '1');

会强制显示错误。 应该在生产服务器中将其关闭,但在开发时则不应将其关闭。


#34楼

除了error_reporting和display_errors ini设置之外,您还可以从Web服务器的日志文件中获取SYNTAX错误。 在开发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
发布了0 篇原创文章 · 获赞 0 · 访问量 2232

猜你喜欢

转载自blog.csdn.net/p15097962069/article/details/103893683