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


583

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

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

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




4
@JuannStrauss,这是低估了。当您终于看到错误时,它说T_PAAMAYIM_NEKUDOTAYIM。或者,也许“必须是整数的实例,给定整数”
Pacerier

Answers:


498

对于语法错误,您需要在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/


25
的值是2039 E_ERROR | E_WARNING | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE。参见docs.php.net/manual/en/errorfunc.constants.php
Gumbo,2009年

我喜欢.htaccess文件的选项。它可以帮助我在不属于公共网站的区域中进行调试。非常感谢这个技巧!
jacekn

1
我会添加日志记录错误到文件(并在那里查找它们)是最好的解决方案。不要依赖在页面上显示错误-它们会破坏它,您可以忘记为生产站点打开错误报告,这将来会给您带来麻烦
Ivan Yarych

455

以下启用所有错误:

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

另请参阅以下链接


28
最好在.ini文件级别进行这些更改。从脚本内部打开错误报告是没有用的,因为它对语法错误或其他致命错误无济于事,这些错误会杀死编译阶段。该脚本在开始执行并到达报告替代项之前就被杀死。
Marc B

你确实是对的。我没有注意到此举已移至您自己的服务器。
Eljakim 2011年

6
运行phpinfo()来找到正确的php.ini文件。查找“ 加载的配置文件”行。
11

1
如果您正在寻找在编译阶段发生的错误,请检查您的apache日志,该日志通常位于/var/log/apache2/error.log
csi

1
启用严格类型输入后,此答案将在php7上失败,因为的第二个参数ini_set是字符串。
PeeHaa

175

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

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


4
我从该代码中得到一个空白页。“关闭处理程序中有错误”是什么意思,我应该怎么做才能解决该问题?
Paolo M

@PaoloM,他说的是上述功能中的错误ShutdownHandler。基本上,这是适当处理错误的权宜之计。
Pacerier,2014年

谢谢,非常有用,但是如何禁用E_NOTICE此功能中的错误?
MajAfy 2015年

这是正确的解决方案,但是在发生错误时要小心信息泄露((最好记录日志而不是向用户回显)
Sam Jason Braddock

1
当Symfony无法正确捕获致命错误时,我将使用此功能。
线圈2016年

61

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

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

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


13
可悲的是,查看页面源也什么也没显示。
马修·沙利

2
解析错误应该在Apache的错误日志中可见,无论您在其他任何地方进行了什么设置。如果您无法控制服务器,那么获取apache错误日志可能会很困难,但是我建议您与提供者联系,并且有一些方法可以向您公开错误日志。除此之外,我只能提出其他建议-在部署到生产之前,请检查您的代码以解析本地开发服务器中的错误。另外,诸如Eclipse的PDT之类的验证IDE可能会有很大帮助。
Guss

5
回到这个问题,我最近遇到了一个堆栈溢出问题,即使在日志中也没有产生任何错误,并且直到我将xdebug安装到服务器中时才表现出来。加。
马修·沙利

如果您无法修改php.ini,请在其中创建一个.htaccess文件php_flag display_errors 1
汤姆(Tom)

59

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

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

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


2
确实如此。在这种情况下,必须直接在ini中设置值-对于纯开发环境,无论如何还是更可取的。
Tomalak

53

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为显示所有错误。检查

哇!没有检查!我无法更改我的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条目下找到它。


30

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


2
确实,这是一个非常有用的调试工具-使用完整的堆栈跟踪,变量转储以及所有内容,使错误消息更加冗长。
hbw

2
是。然后使用VimDebugger插件之类的代码逐步检查代码,找出问题出在哪里。
Sander Marechal,2009年

1
带有xdebug的NetBeans。它是如此真棒。我是PHP的新手(通常是ASP.NET),之前一直在发布echo语句。
某些Canuck节目2009年

30

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

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

3
很抱歉,但-1无法阅读已经发布的其他答案。正如已经多次提到的,这在.htaccess中得到了照顾。
马修·沙利

12
通常的“免费托管”会忽略.htaccess
FDisk

27

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

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

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

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

接下来要考虑的事情:

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

另请参阅:


27

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

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

register_shutdown_function('shutdown');

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


1
对于被卡在虚拟主机中的人来说,这是纯金,它没有显示错误但允许零日志访问
Rafael Mena Barreto

18

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

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

如何在开发中始终避免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,无论在运行时更改(例如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);在你的PHP脚本的顶部或使用的.htaccess像你这样在这里,是不是会帮助你避免WSOD当一个语法或解析错误发生时(像你的情况在这里),如果你的加载配置文件已display_errors关闭。

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


17

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

$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%的错误,这不是问题。


2
如果您要区分本地环境和生产环境,则应该简单地全局(在php.ini中)启用或禁用错误,而不是在也可以是生产代码的代码中启用或禁用错误。如果您需要在生产环境中调试生产网站,并且只希望您能够查看错误,请使用$_SERVER['REMOTE_HOST']检查客户端是否是您。
Jaap Haagmans 2014年

17

在页面顶部选择一个参数

error_reporting(E_ERROR | E_WARNING | E_PARSE);

16

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

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

将未注释的行更改为:

display_errors = stdout

16

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

@Eli,但是,每个页面请求都有运行时开销。
Pacerier,2014年

up 1的概念,它忽略调试设置,但是配置了服务器,这在您部署或维护(开发中)时
很好

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

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


可以从php.ini中启用Xdebug
jewelhuq,


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


9

您可以在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');

7

要从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;
}


6

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

display_errors = On

重新启动服务器。


6

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


6

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

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

它将显示最近的50个错误。error.logapache2 有一个错误文件,其中记录了所有错误。


5

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

error_reporting(E_ALL);

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

ini_set('display_errors', '1');

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


与Tomalak的答案一样,这不适用于语法错误。
达里尔·海因

5

对于开发人员来说,“错误”是最有用的东西,它可以帮助他们了解错误并解决它们,以使系统正常运行。

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

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

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

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


4

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

error_reporting = E_ALL | E_STRICT

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

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

error_reporting = (E_ALL | E_STRICT) & ~E_NOTICE

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

display_errors = "On"

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

display_errors = "stderr"

4

除了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

3

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

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

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


我有同样的问题,其原因是Nginx默认配置文件缺少该行。
塞勒姆
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.