在发出通知/警告时停止脚本执行

时间:2012-05-09 16:38:21

标签: php configuration

是否可以让PHP在全局通知/警告后停止执行?

我们运行的开发服务器上有很多站点,但是想强迫我们的开发人员修复这些警告/通知(或者至少向他们寻求帮助),而不是忽略并继续前进。

6 个答案:

答案 0 :(得分:48)

是的,有可能。这个问题涉及如何处理PHP中的错误这一更普遍的问题。您应该使用set_error_handlerdocs定义并注册自定义错误处理程序,以自定义PHP错误的处理。

恕我直言,最好在任何PHP错误上抛出异常并使用try / catch块来控制程序流,但是这一点的意见不同。

要实现OP的既定目标,您可以执行以下操作:

function errHandle($errNo, $errStr, $errFile, $errLine) {
    $msg = "$errStr in $errFile on line $errLine";
    if ($errNo == E_NOTICE || $errNo == E_WARNING) {
        throw new ErrorException($msg, $errNo);
    } else {
        echo $msg;
    }
}

set_error_handler('errHandle');

上述代码会在ErrorExceptionE_NOTICE被引发时抛出E_WARNING,从而有效地终止脚本输出(如果未捕获异常)。抛出PHP错误的异常最好与并行异常处理策略(set_exception_handler)结合使用,以便在生产环境中正常终止。

请注意,上面的示例不会尊重@错误抑制运算符。如果这对您很重要,只需添加一个支票error_reporting(),如下所示:

function errHandle($errNo, $errStr, $errFile, $errLine) {
    if (error_reporting() == 0) {
        // @ suppression used, don't worry about it
        return;
    }
    // handle error here
}

答案 1 :(得分:6)

您可以在php.ini file­Docs

中对此进行全局配置

您可以通过使用auto_prepend_file directive­Docs指定所有PHP进程所包含的文件来执行此操作:

auto_prepend_file "/full/path/to/a/prepend-file.php"

在你的全局php.ini文件中执行此操作将确保前置文件中的代码将始终被执行。然后,您可以使用它来注册将turn all errors into exceptions­Docs

的全局错误处理程序
<?php
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");

这个小脚本会将所有错误/警告/通知等转换为ErrorException

将它与error_reporting ini directive­Docs结合使用,这些值在php.ini文件中描述。

抛出异常是非常严格的事情。您的程序员将被迫处理警告和错误,否则代码将无法正常工作。

对于您的程序员来说,这可能太过分了,而且在您公司内部并不是社会可接受的。相反,你也可以记录所有错误,并在输出结尾处添加它们(或者在顶部使用输出缓冲来增加它们。)

另一种方法是将错误和警告记录到日志文件中,然后使用另一个进程监视该文件并聚合信息。您可以创建一个记分板,显示每个应用程序的警告数量,并使其在办公室中可见,这样每个人都可以看到团队的表现如何,或者像这样有趣。

我想说的是:除了技术问题之外,这是一个社交问题,你需要具有创造性,并实际上从开发人员那里谈论问题。您需要明确为什么修复警告和错误以及他们的编码和技能将从中受益的重要性。

答案 2 :(得分:6)

从PHP 5.3.0开始:

set_error_handler(
    function(int $nSeverity, string $strMessage, string $strFilePath, int $nLineNumber){
        if(error_reporting()!==0) // Not error suppression operator @
            throw new \ErrorException($strMessage, /*nExceptionCode*/ 0, $nSeverity, $strFilePath, $nLineNumber);
    },
    /*E_ALL*/ -1
);

答案 3 :(得分:3)

如果您在开发环境中,可以考虑安装模块Xdebug并在PHP ini文件中的某处设置xdebug.halt_level=E_WARNING|E_NOTICE|E_USER_WARNING|E_USER_NOTICE。开发人员可以重置xdebug.halt_level,但基于set_error_handler的答案存在同样的问题,因为我们可以将处理程序恢复为原始值。

答案 4 :(得分:0)

其他解决方案实现了一个自定义错误处理程序,它覆盖了默认的错误记录机制。这意味着当我们设置自定义错误处理程序时,通知/警告不再以默认方式打印,因此我们更改的不仅仅是&#34;在通知/警告时停止脚本执行&#34;。

但是,我需要一种方法来打印消息 - 在我的情况下是在PHP CLI中 - 因为输出然后由另一个程序解析。所以我不想以某种方式打印消息,但方式与PHP通常完全相同。我只是想要在打印通知/警告后立即停止退出代码!= 0,并且不会改变任何内容其他

不幸的是,似乎没有退出脚本的默认方式而不更改整个错误处理。所以我需要在PHP中重新实现默认的错误处理程序(在C中实现)。

为此,我查看了PHP源代码中的默认错误打印机制,并将相关的部分从C移植到PHP以获取以下错误处理程序,我想与您分享以防您需要的东西类似:

set_error_handler(
    function($errNo, $errStr, $errFile, $errLine) {
        $error_type_str = 'Error';
        // Source of the switch logic: default error handler in PHP's main.c
        switch ($errNo) {
            case E_ERROR:
            case E_CORE_ERROR:
            case E_COMPILE_ERROR:
            case E_USER_ERROR:
                $error_type_str = "Fatal error";
                break;
            case E_RECOVERABLE_ERROR:
                $error_type_str = "Recoverable fatal error";
                break;
            case E_WARNING:
            case E_CORE_WARNING:
            case E_COMPILE_WARNING:
            case E_USER_WARNING:
                $error_type_str = "Warning";
                break;
            case E_PARSE:
                $error_type_str = "Parse error";
                break;
            case E_NOTICE:
            case E_USER_NOTICE:
                $error_type_str = "Notice";
                break;
            case E_STRICT:
                $error_type_str = "Strict Standards";
                break;
            case E_DEPRECATED:
            case E_USER_DEPRECATED:
                $error_type_str = "Deprecated";
                break;
            default:
                $error_type_str = "Unknown error";
                break;
        }
        fwrite(STDERR, "PHP $error_type_str:  $errStr in $errFile on line $errLine\n");
        exit(1);
    },
    E_ALL
);

答案 5 :(得分:-4)

您可以在服务器的PHP配置文件中打开 error_reporting E_ALL

在PHP 5中,可以使用新的错误级别E_STRICT。由于E_STRICT未包含在E_ALL中,因此您必须明确启用此类错误级别。在开发期间启用E_STRICT有一些好处。 STRICT消息将帮助您使用最新和最好的建议编码方法,例如警告您使用已弃用的函数。

参考:PHP Configuration Manual

以下设置指导您输出脚本中的所有错误。请注意,这些将需要包含在所有脚本文件的开头。

<?php

// Turn off all error reporting
error_reporting(0);

// Report simple running errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);

// Reporting E_NOTICE can be good too (to report uninitialized
// variables or catch variable name misspellings ...)
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);

// Report all errors except E_NOTICE
// This is the default value set in php.ini
error_reporting(E_ALL ^ E_NOTICE);

// Report all PHP errors (see changelog)
error_reporting(E_ALL);

// Report all PHP errors
error_reporting(-1);

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

?>