如何让PHP错误显示出来?

1986
我已经检查了我的 PHP ini 文件(php.ini),并且已经设置了 display_errors 和错误报告是 E_ALL。我已经重启了我的 Apache web 服务器。
我甚至在我的脚本顶部加入了这些行,但它甚至无法捕捉简单的解析错误。例如,我使用 "$" 声明变量,但我没有关闭语句";"。但所有我的脚本在出现这些错误时都显示一个空白页,但我希望实际上在浏览器输出中看到错误
error_reporting(E_ALL);
ini_set('display_errors', 1);

还有什么需要做的吗?


10
我尚未完全确定为什么有时候可以行得通,而有时候又不行,但对于任何想要快速切换PHP脚本中错误(或通过$_REQUEST参数启用它们)的人来说,这两行代码大多数情况下都能够奏效。 - brandonscript
你可以通过在php ini文件中启用xdebug来查看错误的详细信息。 - jewelhuq
1
大多数特定的编辑器/ IDE,例如Notepad++、Eclipse等都内置了语法检查和高亮功能。它们将显示您所描述的问题。请不要在生产环境中显示错误。黑客会喜欢这样做,因为在大多数情况下,路径会被显示出来。您可以定义错误/异常处理程序,在此处理程序中,您可以记录问题并向开发人员发送一封电子邮件,以便在出现问题时立即修复它。请参见https://www.php.net/manual/en/function.set-error-handler.php 和https://www.php.net/manual/en/function.set-exception-handler.php。 - Alexander Behling
27个回答

20
为了显示解析错误,您可以使用一个小技巧,而不是在php.ini中设置 display_errors:使用include。以下是三个代码片段: 文件:tst1.php
<?php
error_reporting(E_ALL);
ini_set('display_errors', 'On');
// Missing " and ;
echo "Testing

如果直接运行该文件,并且在php.ini中设置 display_errors 为0,将不会显示任何内容。

现在,请尝试以下操作:

文件:tst2.php

<?php
error_reporting(E_ALL);
ini_set('display_errors', 'On');
include ("tst3.php");

文件:tst3.php

<?php
// Missing " and ;
echo "Testing

现在运行tst2.php,该文件设置错误报告,然后包含tst3。你会看到:

解析错误:语法错误,意外的文件结尾,期望变量(T_VARIABLE)或$(T_DOLLAR_OPEN_CURLY_BRACES)或{$(T_CURLY_OPEN)在tst3.php的第4行


1
我花了一些时间来弄清楚这个问题。他们为什么改变了 PHP 5 的行为? - Hebe
1
这篇文章值得更多的点赞。在我的情况下,关键是启用错误报告并在init0.php中定义错误处理程序,然后从该文件包含init1.php,该文件可以包含其他存在错误的文件。如果在同一个包含其他存在错误文件的文件中启用错误报告,则无法正常工作。 - Magnus
1
建议的方法实际上是正确的,但解释是错误的。在PHP7中没有改变任何东西。无论是PHP5还是PHP3都无法解析带有语法错误的文件。问题是解析错误,而不是PHP版本。所提出的解决方案适用于任何PHP版本。 - Your Common Sense
我曾经运行一个非常庞大的网站,使用PHP5并设置了php.ini,所有的错误都是可见的,这解释了所有其他答案。当我升级到PHP7时,没有进行任何其他更改,就无法看到错误。因此,即使解决方案适用于每个版本,其他答案对旧版本也是正确的。 - Peter

17

在我的纯PHP项目中,我通常会使用以下代码。

if(!defined('ENVIRONMENT')){
    define('ENVIRONMENT', 'DEVELOPMENT');
}

$base_url = null;

if (defined('ENVIRONMENT'))
{
    switch (ENVIRONMENT)
    {
        case 'DEVELOPMENT':
            $base_url = 'http://localhost/product/';
            ini_set('display_errors', 1);
            ini_set('display_startup_errors', 1);
            error_reporting(E_ALL);
            break;

        case 'PRODUCTION':
            $base_url = 'Production URL'; /* https://google.com */
            error_reporting(E_ALL);
            ini_set('display_errors', 0);
            ini_set('display_startup_errors', 0);
            ini_set('log_errors', 1); // Mechanism to log errors
            break;

        default:
            exit('The application environment is not set correctly.');
    }
}

16

如果您尝试了以上所有答案(或者您无法编辑php.ini文件)但仍然无法获得错误消息,请尝试创建一个启用错误报告的新PHP文件,然后包含出问题的文件,例如:

error_reporting(E_ALL);
ini_set('display_errors', 1);
require_once('problem_file.php');

尽管我在php.ini文件中设置了一切,但这是我捕获命名空间错误的唯一方法。我的确切情况是:

//file1.php
namespace a\b;
class x {
    ...
}

//file2.php
namespace c\d;
use c\d\x; //Dies because it's not sure which 'x' class to use
class x {
    ...
}

1
不,错误报告不是日志级别,它是一个位域。使用999999是一个非常糟糕的想法,应该使用一些2的幂减1,例如2047! - peterh
你说得完全正确,@peterh!我已将其更改为E_ALL,因为这将启用所有错误的报告(除了php 5.4及以下版本中的严格错误)。 - jxmallett

14

如果你发现自己处于一种无法通过 php.ini.htaccess 修改设置的情况下,当你的 PHP 脚本包含解析错误时,就无法显示错误。那么你就需要像这样在命令行上对文件进行语法检查

find . -name '*.php' -type f -print0 | xargs -0 -n1 -P8 php -l | grep -v "No syntax errors"

如果您的主机非常严格,不允许通过php.ini.htaccess更改值,那么它也可能禁止通过ini_set更改值。 您可以使用以下PHP脚本检查:

<?php
if( !ini_set( 'display_errors', 1 ) ) {
  echo "display_errors cannot be set.";
} else {
  echo "changing display_errors via script is possible.";
}

find . -name '*.php' -type f -exec php -l {} \; | grep -v 'No syntax errors detected' 更简单。 - scones

14

你可以按照以下方式进行操作:

在您的主索引文件中设置以下参数:

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

根据您的要求,您可以选择要显示哪些内容:

对于所有错误、警告和通知:

    error_reporting(E_ALL); OR error_reporting(-1);

对于所有错误:

    error_reporting(E_ERROR);

对于所有的警告:

    error_reporting(E_WARNING);

对于所有通知:

    error_reporting(E_NOTICE);

欲了解更多信息,请查看此处


“主索引文件”是什么?是index.html文件吗? - Peter Mortensen

12

您可以添加自己的自定义错误处理程序,以提供额外的调试信息。此外,您可以将其设置为通过电子邮件向您发送信息。

function ERR_HANDLER($errno, $errstr, $errfile, $errline){
    $msg = "<b>Something bad happened.</b> [$errno] $errstr <br><br>
    <b>File:</b> $errfile <br>
    <b>Line:</b> $errline <br>
    <pre>".json_encode(debug_backtrace(), JSON_PRETTY_PRINT)."</pre> <br>";

    echo $msg;

    return false;
}

function EXC_HANDLER($exception){
    ERR_HANDLER(0, $exception->getMessage(), $exception->getFile(), $exception->getLine());
}

function shutDownFunction() {
    $error = error_get_last();
    if ($error["type"] == 1) {
        ERR_HANDLER($error["type"], $error["message"], $error["file"], $error["line"]);
    }
}

set_error_handler ("ERR_HANDLER", E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED);
register_shutdown_function("shutdownFunction");
set_exception_handler("EXC_HANDLER");

12

接受的答案包括额外选项。在我的开发Apache虚拟主机中的PHP文件中(如果您可以确保它不进入生产环境,则使用.htaccess):

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

然而,这并不会让PHP显示解析错误——显示这些错误的唯一方法是通过修改您的php.ini文件添加以下行:

display_errors = on

(如果您无法访问 php.ini,则将此行放入.htaccess中也可能有效):
// I've added some extra options that set E_ALL as per https://www.php.net/manual/en/errorfunc.configuration.php.
php_flag log_errors on
php_flag display_errors on
php_flag display_startup_errors on
php_value error_reporting 2147483647
php_value error_log /var/www/mywebsite.ext/logs/php.error.log

7
这段代码应该可以正常工作:
error_reporting(E_ALL);

然而,尝试在文件中使用手机编辑代码:

error_reporting =on

5

如果您需要快速调试,最好/简单/快速的解决方案是使用异常捕获来包围您的代码。当我想要在生产环境中快速检查某些内容时,这就是我所做的。

try {
    // Page code
}
catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

对于php7,catch (Throwable $e) 更好... 或者在 catch(Error $e) 下面添加另一个 catch 块。 - Frank Forte
这段代码实际上是很危险的。在任何情况下都不应该在生产环境中使用,因为它会泄露错误消息给任何人,而不仅仅是添加它的开发人员。在生产环境中,所有的错误必须被记录下来,这样开发人员可以随时查看错误日志。这将捕获所有的错误,而不仅仅是当开发人员刷新浏览器时发生的错误。而且不需要添加任何代码。这使得这段代码不仅危险,而且无用。 - Your Common Sense
兄弟,他正在快速调试而不是启动网站以捕获错误,危险性并不重要,没有人愿意让客户看到错误而不是空白页面。是的,我们可以为他编写一个记录器或检查他使用的内容,以提供正确的解决方案,但这是stackoverflow,需要大量的聊天和互动才能了解他的具体需求。请理性思考。 - Xakiru

4
    <?php
    // Turn off error reporting
    error_reporting(0);

    // Report runtime errors
    error_reporting(E_ERROR | E_WARNING | E_PARSE);

    // Report all errors
    error_reporting(E_ALL);

    // Same as error_reporting(E_ALL);
    ini_set("error_reporting", E_ALL);

    // Report all errors except E_NOTICE
    error_reporting(E_ALL & ~E_NOTICE);
    ?>

在您的网站上线时,出于安全原因,php.ini文件应禁用display_errors。然而,在开发环境中,为了进行故障排除,可以启用display_errors。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接