【问题标题】:How can I get useful error messages in PHP?如何在 PHP 中获得有用的错误消息?
【发布时间】:2021-12-15 18:00:45
【问题描述】:

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

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

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

【问题讨论】:

标签: php debugging error-handling


【解决方案1】:

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

php_flag  display_errors        on
php_value error_reporting       2039

您可能需要考虑为您的 PHP 版本使用 E_ALL 的值(如 Gumbo 所述)error_reporting 以获取所有错误。 more info

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

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

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

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

【讨论】:

  • 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
  • 我喜欢 .htaccess 文件的选项。它可以帮助我在不属于公共网站的区域进行调试。非常感谢这个提示!
  • 我会补充一点,将错误记录到文件中(并在那里查找)是最好的解决方案。不要依赖在页面上显示错误 - 它们可能会破坏它,您可能会忘记为生产站点打开错误报告,这将在未来给您带来麻烦
【解决方案2】:

您可以在 PHP 中注册自己的error handler。例如,将所有错误转储到文件中可能会对您有所帮助。请注意,无论您当前的 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');

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

    • 确实如此。在这种情况下,必须直接在 ini 中设置值——对于纯开发环境,这可能更可取。
    【解决方案4】:
    error_reporting(E_ALL | E_STRICT);
    

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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

        • 确实,这是一个非常有用的调试工具——使错误消息更加详细,包括完整的堆栈跟踪和变量转储等等。
        • 是的。然后使用 VimDebugger 插件之类的东西来单步调试你的代码并找出哪里出错了。
        • NetBeans 与 xdebug 在这里。它是如此真棒。我是 PHP 新手(通常是 ASP.NET),之前一直在发出 echo 语句。
        【解决方案7】:

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

        error_reporting(E_ALL);
        

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

        ini_set('display_errors', '1');
        

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

        【讨论】:

        • 与 Tomalak 的回答一样,这不适用于语法错误。
        【解决方案8】:

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

        【讨论】:

          【解决方案9】:

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

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

          所以"tail -f" 你的日志文件和当你得到一个空白屏幕时使用 IE 的 "view" -> "source" 菜单选项来查看原始输出。

          【讨论】:

          • 遗憾的是,查看页面源代码也没有显示任何内容。
          • 解析错误应该在 Apache 的错误日志中可见,无论您在其他任何地方有什么设置。如果您无法控制服务器,那么获取 apache 错误日志可能会很困难,但我建议您与您的提供商交谈,并且有一些方法可以向您公开错误日志。除此之外,我只能建议其他人有什么 - 在部署到生产之前检查您的代码以解析本地开发服务器中的错误。此外,Eclipse 的 PDT 等验证 IDE 可能会有很大帮助。
          • 回到这个问题,我最近遇到了一个堆栈溢出问题,即使在日志中也没有产生任何错误,并且在我将 xdebug 安装到服务器之前没有表现出来。嘎。
          • 如果不能修改php.ini,创建一个.htaccess文件,里面有php_flag display_errors 1
          【解决方案10】:

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

          【讨论】:

          • 我无权访问 php.ini。而当这些错误出现时,就是语法错误,所以 print_r 也无济于事。
          • 如果您无权访问 php.ini,则不应在该服务器上进行开发。使用共享主机进行生产,使用本地计算机进行开发。
          • 当生产中发生错误时?我们都愿意相信这不会发生,但它确实发生了。
          • 如果您在生产中遇到解析错误,则说明您的开发模型有问题。 :) 如果您有不同的错误,则无论如何您都不希望向用户显示该错误+您应该有适当的错误处理机制。
          • 我建议您下载 apache XAMP 或 WAMPserver 并在您的 PC 上设置开发环境。如果您的工作站环境与服务器环境一样受限,您可以使用portableapps.com/apps/development/xampp,它不需要任何管理员权限或特殊权限即可安装和运行。
          【解决方案11】:

          您确定 PHP 实际上是从 .htaccess 中获取“display_errors”设置吗?检查phpinfo()函数的输出以确保。

          此外,您应该检查以确保您没有使用过“@”,如果您使用过“@include ...”或“@some_function(...)”,可能会消除您的错误,在堆栈跟踪的某处。

          【讨论】:

          • 是的。 display_errors 在服务器范围的配置中处于关闭状态,但它显示的错误较少,例如参数编号不匹配等。我在这个项目中根本没有使用 @ 运算符,并且出于这个原因通常倾向于避免它。
          • 您还应该检查 display_errors 没有被某个地方的 PHP 脚本更改。
          • 我是从头开始构建这个框架的,所以不,它不是(除非核心中的某些东西出于某种原因改变了它......)
          • 如果你调用一个未定义的函数(产生一个致命错误),你看到那个错误信息了吗?
          【解决方案12】:

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

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

          【讨论】:

            【解决方案13】:

            一些应用程序自己处理这些指令,通过调用这样的东西:

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

            从而覆盖您的 .htaccess 设置。

            【讨论】:

              【解决方案14】:

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

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

              【讨论】:

              • 对不起,-1 因为没有阅读已经发布的其他答案。正如已经多次提到的,这在 .htaccess 中得到了解决。
              • 通常的“免费托管”会忽略 .htaccess
              【解决方案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>");
              }
              

              【讨论】:

              • @Eli,这有一个运行时开销,每个页面请求
              • up 1 表示忽略调试设置但服务器配置的概念,在您部署或维护(开发中)时很好
              【解决方案16】:

              在您的代码中使用@inexistent_function_call(); 将导致解释器安静地死掉并中止脚本解析。您应该检查无效函数并尽量不要使用错误抑制运算符(@ char)

              【讨论】:

                【解决方案17】:

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

                display_errors = On
                

                重启你的服务器。

                【讨论】:

                  【解决方案18】:

                  以下启用所有错误:

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

                  另见以下链接

                  【讨论】:

                  • 最好在 .ini 文件级别进行这些更改。从脚本中打开错误报告是没有用的,因为它对语法错误或其他导致编译阶段的致命错误没有帮助。脚本在开始执行并到达报告覆盖之前很久就被杀死了。
                  • 你确实是对的。我没有注意到移动到你自己的服务器。
                  • 运行 phpinfo() 找到正确的 php.ini 文件。查找 Loaded Configuration File 行。
                  • 如果您正在寻找在编译阶段发生的错误,请检查您的 apache 日志,这些日志通常位于 /var/log/apache2/error.log
                  • 这个答案在php7启用严格类型时会失败,因为ini_set的第二个参数是一个字符串。
                  【解决方案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% 的错误,这不是问题。

                  【讨论】:

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

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

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

                  将未注释的行更改为:

                  display_errors = stdout
                  

                  【讨论】:

                    【解决方案21】:

                    对于快速的动手故障排除,我通常建议在这里:

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

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

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

                    接下来要考虑的事情:

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

                    参见:

                    【讨论】:

                      【解决方案22】:

                      在页面顶部选择一个参数

                      error_reporting(E_ERROR | E_WARNING | E_PARSE);
                      

                      【讨论】:

                        【解决方案23】:

                        fastcgi_paramsfastcgi.conf 配置文件未正确包含在服务器配置中时,我也看到了此类错误。所以对我来说修复很愚蠢:

                        include /etc/nginx/fastcgi_params;

                        花了我一个 小时 才发现...

                        【讨论】:

                          【解决方案24】:

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

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

                          【讨论】:

                            【解决方案25】:

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

                            <?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 复制并粘贴了它,但没有测试它,但我确信它可以工作。

                            【讨论】:

                            • 我从该代码中得到一个空白页。 “您在关闭处理程序中有错误”是什么意思,我应该怎么做才能解决问题?
                            • @PaoloM,他说上面的函数ShutdownHandler 有错误。基本上,这是代替正确错误处理的权宜之计。
                            • 谢谢,很有用,但如何禁用此功能中的E_NOTICE 错误?
                            • 这是正确的解决方案,但在发生错误时要小心信息披露...(更喜欢记录而不是回显给用户)
                            • 我在 Symfony 无法正确捕获致命错误时使用它。
                            【解决方案26】:

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

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

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

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

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

                            【讨论】:

                              【解决方案27】:

                              PHP 配置

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

                              1. display_errors
                              2. error_reporting

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

                              但是,在开发中,它应该设置为On,这样错误才会显示出来。 检查

                              error_reporting(从 PHP 5.3 开始)默认设置为 E_ALL &amp; ~E_NOTICE &amp; ~E_STRICT &amp; ~E_DEPRECATED(意思是,除了通知、严格标准和弃用通知之外的所有内容都会显示)。如有疑问,请将其设置为 E_ALL 以显示所有错误。 检查

                              哇哇哇!没有检查!我无法更改我的 php.ini!

                              真可惜。通常共享主机不允许更改其 php.ini 文件,因此该选项不可用。但不要害怕!我们有other options

                              运行时配置

                              在所需的脚本中,我们可以在运行时更改 php.ini 条目!意思是,它会在脚本运行时运行!甜蜜!

                              @987654325@(E_ALL);
                              @987654326@("display_errors", "On");

                              这两行的效果与上面修改 php.ini 条目的效果相同!太棒了!

                              我仍然收到空白页/500 错误!

                              这意味着脚本甚至还没有运行!这通常发生在您遇到语法错误时!

                              由于语法错误,脚本甚至无法运行。它在编译时失败,这意味着它将使用 php.ini 中的值,如果您没有更改,可能不允许显示错误。

                              错误日志

                              此外,PHP 默认记录错误。在共享主机中,它可能位于专用文件夹中或与违规脚本位于同一文件夹中。

                              如果您有权访问 php.ini,则可以在 error_log 条目下找到它。

                              【讨论】:

                              • 对于运行时配置,您可以将这些行放到一个单独的文件中 & include 出现错误的 php 文件中。
                              【解决方案28】:

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

                              【讨论】:

                                【解决方案29】:

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

                                【讨论】:

                                  【解决方案30】:
                                  error_reporting(E_ALL | E_STRICT);
                                  ini_set('display_errors', 1);
                                  ini_set('html_errors', 1);
                                  

                                  另外,您可以通过xdebug获取更多详细信息。

                                  【讨论】:

                                  • Xdebug 可以从 php.ini 启用
                                  猜你喜欢
                                  相关资源
                                  最近更新 更多