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

How can I get useful error messages in PHP?

提问人:Candidasa 提问时间:5/10/2009 最后编辑:TylerHCandidasa 更新时间:8/16/2023 访问量:696144

问:

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

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

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

PHP 调试 错误处理

评论

1赞 Alex 7/15/2012
coding.smashingmagazine.com/2011/11/30/......
5赞 Pacerier 4/4/2015
@JuannStrauss,这太轻描淡写了。当你最终看到错误时,它会说.或者也许“必须是整数的实例,给定的整数”。T_PAAMAYIM_NEKUDOTAYIM
2赞 Pupil 9/9/2015
关于这个的教程:code2real.blogspot.com/2015/06/...
0赞 Matthew Lock 8/17/2021
如果出现解析错误,则这些操作都不适用于许多 Web 主机,并且您可能无权访问错误日志。您需要在本地计算机上安装 php(Windows 上的 XAMPP 等)并执行命令行 synax 检查php.exe -l <your file name>

答:

530赞 Darryl Hein 5/10/2009 #1

默认情况下,显示错误处于关闭状态,因为您不希望“客户”看到错误消息。

请查看 PHP 文档中的此页面,以获取有关 2 个指令的信息: 和 . 可能是你想改变的那个。error_reportingdisplay_errorsdisplay_errors

因此,您有 3 个选择:

(1) 您可以检查错误日志文件,因为它将包含所有错误(除非已禁用日志记录)。要启用错误日志记录,请确保将配置指令设置为 。当错误不是在 PHP 中发生,而是由 Web 服务器发出时,日志也很有用。log_errorsOn

(2)您可以添加以下2行,以帮助您调试不是同一文件中发生的语法错误的错误:

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

请注意,在实时服务器上,后者应设置为(但只能设置为后者,因为您仍然需要从日志文件中了解发生的所有错误)。Off

但是,对于同一文件中发生的语法错误,上述命令将不起作用,您需要在 php.ini 中启用它们。如果您无法修改 php.ini,您也可以尝试将以下行添加到 .htaccess 文件中,尽管现在很少支持它:

php_flag  display_errors        on
php_value error_reporting       -1

(3) 另一种选择是使用在键入时检查错误的编辑器,例如 PhpEd、VSCode 或 PHPStorm。它们都带有一个调试器,可以提供更详细的信息。(PhpEd 调试器与 xdebug 非常相似,直接集成到编辑器中,因此您可以使用 1 个程序来完成所有操作。

评论

30赞 Gumbo 5/11/2009
2039 是 的值。查看 docs.php.net/manual/en/errorfunc.constants.phpE_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
0赞 jacekn 6/15/2013
我喜欢.htaccess文件的选项。它帮助我在不属于公共网站的区域进行调试。非常感谢这个提示!
2赞 Ivan Yarych 3/27/2016
我想补充一点,将错误记录到文件中(并在那里查找它们)是最好的解决方案。不要依赖在页面上显示错误 - 它们可能会破坏它,您可能会忘记为生产站点打开错误报告,这将给您将来带来麻烦
10赞 soulmerge 5/10/2009 #2

您可以在 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');
63赞 Tomalak 5/10/2009 #3

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

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

这覆盖了 php.ini 中的默认设置,这些设置只是使 PHP 将错误报告到日志中。

评论

2赞 Tomalak 5/10/2009
这是真的。在这种情况下,必须直接在 ini 中设置这些值 -- 对于纯开发环境,这可能更可取。
10赞 Ólafur Waage 5/10/2009 #4
error_reporting(E_ALL | E_STRICT);

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

4赞 Ayman Hourieh 5/10/2009 #5

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

error_reporting = E_ALL | E_STRICT

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

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

error_reporting = (E_ALL | E_STRICT) & ~E_NOTICE

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

display_errors = "On"

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

display_errors = "stderr"
30赞 gnarf 5/10/2009 #6

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

评论

2赞 hbw 5/10/2009
事实上,这是一个非常有用的调试工具,它使错误消息更加冗长,具有完整的堆栈跟踪和变量转储等。
2赞 Sander Marechal 5/10/2009
是的。然后使用 VimDebugger 插件之类的东西来单步执行您的代码并找出出错的地方。
1赞 Some Canuck 5/10/2009
此处是带有 xdebug 的 NetBeans。这真是太棒了。我是 PHP(通常是 ASP.NET)的新手,以前一直在发布 echo 语句。
5赞 Daniel Sorichetti 5/10/2009 #7

若要启用完整的错误报告,请将以下内容添加到脚本中:

error_reporting(E_ALL);

这会导致出现最少的警告。而且,以防万一:

ini_set('display_errors', '1');

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

评论

0赞 Darryl Hein 5/11/2009
与Tomalak的回答一样,这不适用于语法错误。
4赞 jmucchiello 5/11/2009 #8

除了 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
61赞 James Anderson 9/25/2009 #9

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

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

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

评论

13赞 Matthew Scharley 9/25/2009
可悲的是,查看页面源也未显示任何内容。
2赞 Guss 9/25/2009
解析错误应该在 Apache 的错误日志中可见,无论您在其他任何地方使用什么设置。如果您无法控制服务器,那么获取 apache 错误日志可能很困难,但我建议您与您的提供商交谈,并且有一些方法可以向您公开错误日志。除此之外,我只能建议其他人拥有的内容 - 在部署到生产环境之前,检查您的代码以解析本地开发服务器中的错误。此外,验证 IDE(如 Eclipse 的 PDT)可能会有很大帮助。
5赞 Matthew Scharley 5/31/2011
回到这一点,我最近遇到了一个堆栈溢出问题,即使在日志中也没有产生任何错误,并且在我将 xdebug 安装到服务器中之前才表现出来。嘎。
0赞 Tom 1/16/2019
如果无法修改 php.ini,请在其中创建一个 .htaccess 文件。php_flag display_errors 1
2赞 Lewis LaCook 9/25/2009 #10

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

评论

0赞 Matthew Scharley 9/25/2009
我无法访问 php.ini。当这些错误弹出时,这是一个语法错误,所以print_r无济于事。
3赞 carl 9/25/2009
如果您无权访问 php.ini,则不应在该服务器上进行开发。使用共享主机进行生产,使用本地计算机进行开发。
0赞 Matthew Scharley 9/25/2009
当生产中发生错误时?我们都愿意相信这不会发生,但它确实发生了。
2赞 carl 9/25/2009
如果在生产环境中出现分析错误,则说明开发模型有问题。:)如果您有其他错误,则无论如何都不希望向用户显示该错误 + 您应该具有适当的错误处理机制。
2赞 James Anderson 9/25/2009
我建议您下载 apache XAMP 或 WAMPserver 并在您的 PC 上设置开发环境。如果您的工作站环境与服务器环境一样受限,则可以使用不需要任何管理员权限或特殊权限即可安装和运行的 portableapps.com/apps/development/xampp
2赞 too much php 9/25/2009 #11

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

此外,您应该检查以确保您没有使用“”,如果您使用了“@include...”,它可能会使您的错误静音或“@some_function(...)”,位于堆栈跟踪的某个位置。@

评论

0赞 Matthew Scharley 9/25/2009
是的。 在服务器范围的配置中处于关闭状态,但它显示较少的错误,例如参数编号不匹配等。在这个项目中,我根本没有使用过运算符,并且通常出于这个原因倾向于避免使用它。display_errors@
0赞 too much php 9/25/2009
您还应该检查某处的 PHP 脚本是否未更改display_errors。
0赞 Matthew Scharley 9/25/2009
我已经从头开始构建了这个框架,所以不,它不是(除非核心中的某些东西出于某种原因改变了它......
0赞 too much php 9/25/2009
如果调用未定义的函数(生成致命错误),是否看到该错误消息?
-1赞 Milan Babuškov 9/25/2009 #12

如果错误出现在 PHP 代码中,则可以在代码中使用 error_reporting() 函数设置为全部报告。

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

0赞 Denegen 9/25/2009 #13

某些应用程序确实通过调用如下内容来自行处理这些指令:

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

从而覆盖您的 .htaccess 设置。

32赞 FDisk 9/25/2009 #14

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

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

评论

3赞 Matthew Scharley 9/25/2009
对不起,但是 -1 没有阅读已经发布的其他答案。正如已经多次提到的,这在.htaccess中得到了解决。
12赞 FDisk 9/25/2009
通常的“免费托管”会忽略 .htaccess
16赞 Eli 9/25/2009 #15

我不知道它是否会有所帮助,但这是我为 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>");
}

评论

0赞 Pacerier 10/14/2014
@Eli,不过,每个页面请求都有运行时开销。
0赞 justnajm 7/20/2017
上 1 表示忽略调试设置但服务器已配置的概念,在部署或维护(正在开发中)时很好
1赞 Quamis 9/25/2009 #16

在代码中使用将导致 intepreter 悄悄地死亡并中止脚本解析。您应该检查无效函数,并尽量不要使用错误压缩运算符(@ char )@inexistent_function_call();

6赞 user577803 1/17/2011 #17

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

display_errors = On

重新启动服务器。

468赞 Eljakim 7/5/2011 #18

以下选项将启用所有错误:

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

另请参阅以下链接

评论

29赞 Marc B 7/5/2011
最好在 .ini 文件级别进行这些更改。从脚本中打开错误报告是没有用的,因为它对语法错误或其他终止编译阶段的致命错误没有帮助。脚本在开始执行并到达报告替代之前很久就被终止了。
0赞 Eljakim 7/5/2011
你确实是对的。我没有注意到移动到您自己的服务器。
6赞 borrible 7/5/2011
运行 phpinfo() 以查找正确的 php.ini 文件。查找 Loaded Configuration File 行。
1赞 csi 2/22/2014
如果要查找编译阶段发生的错误,请检查通常位于 /var/log/apache2/error.log 的 apache 日志
2赞 PeeHaa 9/5/2015
当启用严格类型时,此答案将在 php7 上失败,因为 的第二个参数是字符串。ini_set
17赞 Rich Bradshaw 7/5/2011 #19

如果你超级酷,你可以尝试:

$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赞 Jaap Haagmans 6/23/2014
如果要区分本地环境和生产环境,则只需全局启用或禁用错误(在php.ini中),而不是在也可以是生产代码的代码中启用或禁用错误。如果您需要在其生产环境中调试生产网站,并且只希望您能够查看错误,请使用 检查客户端是否是您。$_SERVER['REMOTE_HOST']
16赞 Ram 7/5/2011 #20

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

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

将未注释的行更改为:

display_errors = stdout
27赞 hakre 1/24/2013 #21

为了快速、动手地进行故障排除,我通常建议在 SO 上:

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

放在正在进行故障排除的脚本的开头。这并不完美,完美的变体是你也在 和 你在 PHP 中记录错误以捕获语法和启动错误。php.ini

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

接下来要考虑的事项:

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

另请参阅:

17赞 Kld 5/6/2013 #22

在页面顶部,选择一个参数

error_reporting(E_ERROR | E_WARNING | E_PARSE);
0赞 kris 6/15/2013 #23

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

因此,我总是创建一个文件/程序(我通常称之为“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) { /* ... */
178赞 m4dm4x1337 8/13/2013 #24

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

<?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 9/25/2014
我从该代码中得到一个空白页。“关机处理程序中有错误”是什么意思,我应该怎么做才能解决问题?
0赞 Pacerier 10/14/2014
@PaoloM,他说的是上面函数中的错误。基本上,这是一种权宜之计,代替了适当的错误处理。ShutdownHandler
0赞 MajAfy 4/4/2015
谢谢,很有用,但是我怎样才能禁用此功能中的错误?E_NOTICE
0赞 Sam Jason Braddock 8/29/2016
这是正确的解决方案,但在发生错误时要小心信息泄露......(更喜欢日志记录而不是回显给用户)
1赞 COil 9/22/2016
当 Symfony 无法正确捕获致命错误时,我正在使用它。
5赞 user3176739 2/1/2014 #25

“错误”是开发人员了解错误并解决它们以使系统完美运行的最有用的东西。

PHP 提供了一些更好的方法来了解开发人员为什么以及他们的代码段在哪里出现错误,因此通过了解这些错误,开发人员可以在许多方面改进他们的代码。

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

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

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

58赞 Madara's Ghost 2/3/2014 #26

PHP配置

php.ini 中的 2 个条目决定了错误的输出:

  1. display_errors
  2. error_reporting

在生产中,通常设置为 (这是一件好事,因为在生产站点中显示错误通常是不可取的!display_errorsOff

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

error_reporting(从 PHP 5.3 开始)默认设置为 (这意味着,除了通知、严格标准和弃用通知之外,所有内容都会显示)。如有疑问,请将其设置为显示所有错误。检查E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATEDE_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条目下找到它。

评论

0赞 JustinCB 12/9/2020
对于运行时配置,您可以将这些行放入一个单独的文件和带有错误的 php 文件中。include
8赞 Code Synthesis 6/10/2014 #27

从 PHP 中获取有用错误所需的两个关键行是:

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

正如其他贡献者所指出的,出于安全原因,这些默认是关闭的。作为一个有用的提示 - 当您设置站点时,可以方便地为不同的环境进行切换,以便这些错误在本地和开发环境中默认处于打开状态。这可以通过以下代码来实现(最好在索引.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赞 user1681048 6/18/2014 #28

您可能还想尝试使用 PHPStorm 作为您的代码编辑器。当您在编辑器中键入时,它会发现许多 PHP 和其他语法错误。

15赞 Yan.Zero 8/19/2014 #29
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);
ini_set('html_errors', 1);

此外,您还可以使用 xdebug 获取更详细的信息。

评论

0赞 jewelhuq 1/5/2016
可以从 php.ini 启用 Xdebug
6赞 Ashutosh Jha 11/10/2014 #30

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

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

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

0赞 Vladimir Ramik 3/8/2015 #31

除了上面很多很好的答案之外,您还可以在项目中实现以下两个功能。他们将在应用程序/脚本退出之前捕获每个非语法错误。 在函数中,您可以进行回溯并记录或向公众呈现令人愉快的“网站正在维护中”消息。

致命错误:

register_shutdown_function

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

错误:

set_error_handler

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

回溯:

debug_backtrace

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

15赞 Ondřej Šotek 7/16/2015 #32

我推荐 Nette Tracy 来更好地可视化 PHP 中的错误和异常:

Nette Tracy screenshot

评论

3赞 Jan Drábek 7/5/2016
Tracy 负责正确设置所有显示错误和错误报告选项,以便在原始帖子中描述的情况下提供输出。因此,这个工具对于解决提问者“谁能推荐好的PHP调试技巧、工具和技术吗?
17赞 Sherif 11/12/2015 #33

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

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

如何在开发中始终避免 WSOD

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

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

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

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

<?php
phpinfo();

然后将浏览器指向那里,查看已加载的配置文件解析的其他 .ini 文件,它们通常位于 your 的顶部,将包含所有已加载配置文件的绝对路径。phpinfo()

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


只是不要在生产中这样做

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

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

27赞 Eduardo Oliveira 1/6/2016 #34

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

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

register_shutdown_function('shutdown');

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

评论

1赞 Rafael Mena Barreto 4/27/2017
对于陷入网络主机的人来说,这是纯金,它没有显示错误,但允许零日志访问
1赞 Aamnah 8/9/2016 #35

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

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

3赞 AVKurov 7/5/2017 #36

对于那些使用 nginx 并且即使文件也有白屏的人。就我而言,我在nginx配置文件中没有PHP所需的选项:<?php echo 123;

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

此选项不fastcgi_params文件中,因此 PHP 不起作用,日志中没有任何错误。

评论

0赞 Salem 8/14/2019
我遇到了同样的问题,这是由于 Nginx 默认配置文件缺少该行。
16赞 Abuzer Firdousi 12/5/2017 #37
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
5赞 Phil 9/14/2018 #38

除了这里所有精彩的答案之外,我还想特别提到MySQLi和PDO库。

为了...

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

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

MySQLi的

将此项添加到脚本顶部附近

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

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

PDO的

将属性设置为 on your connection instance。您可以在构造函数中执行此操作PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION

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

或创建后

$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
4赞 mario 5/17/2019 #39

这个答案是由裁员部门带给大家的。

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

    这些设置现在已经足够覆盖了。但只是回顾一下何时使用哪个选项:display_errorserror_reporting

    • ini_set() 和 error_reporting() 仅适用于运行时错误。
    • 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']))
    #                  ↑↑
    

    如果你的代码中充斥着 //,你不会收到任何有用的通知。有时使用 @ 更明智,因此至少会将通知和警告发送到日志中。issetemptyarray_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()

    对于正则表达式。

  10. CURLOPT_VERBOSE

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

  11. shell/exec()

    同样,shell 命令执行本身也不会产生错误。你总是需要并偷看$errno。2>&1

2赞 Yogi Ghorecha 12/6/2019 #40

PHP 错误处理

有时,应用程序将无法按预期运行,从而导致错误。有许多原因可能导致错误,例如:

Web 服务器可能磁盘空间不足 用户可能在表单字段中输入了无效值 您尝试访问的文件或数据库记录可能不存在 应用程序可能没有写入磁盘上的文件的权限 应用程序需要访问的服务可能暂时不可用 这些类型的错误称为运行时错误,因为它们在脚本运行时发生。它们与脚本运行之前需要修复的语法错误不同。

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

了解错误级别

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

enter image description here

每当 PHP 引擎遇到脚本问题时,它都会触发错误,但您也可以自己触发错误以生成更用户友好的错误消息。这样,您可以使您的应用程序更加安全。以下部分描述了一些用于处理 PHP 中的错误的常用方法:

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

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

如果该文件不存在,您可能会收到如下错误: 警告:fopen(sample.txt) [function.fopen]:无法打开流:第 2 行 C:\wamp\www\project\test.php 中没有这样的文件或目录

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

<?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),如下所述:

enter image description here

下面是一个简单的自定义错误处理函数的示例。每当发生错误时,都会触发此处理程序 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) 的值作为 $divisor 参数传递,则 PHP 引擎生成的错误将如下所示: 警告:在第 3 行的 C:\wamp\www\project\test.php 中除以零

此消息看起来信息量不大。请考虑以下示例,该示例使用 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

评论

0赞 skomisa 10/1/2022
您从 tutorialrepublic.com/php-tutorial/php-error-handling.php 复制了您的答案,但没有注明出处。不要把别人的作品当作自己的作品来展示。
0赞 Saghachi 1/3/2021 #41

我像这样解决了整个 500 个问题:

A. 检查 php.ini 参数

  1. 菲律宾比索.ini >> error_reporting = E_ALL |E_STRICT
  2. php.ini >> display_errors = 开
  3. php.ini >> display_startup_errors = 关闭

B. 更新 IIS 管理器参数

  1. IIS 管理器 >>错误页 >> 500 >> 编辑功能设置>>详细错误

在此步骤中,您将收到 500 个这样的错误,并且没有加载 HTML。

enter image description here

  1. IIS 管理器>> FastCGI 设置 >> php-cgi.exe >> 标准错误模式>> IgnoreAndReurn200

在此步骤中,您可以看到包含此类 PHP 错误的 HTML 页面。 enter image description here

并完成:)