当自动加载文件具有"编译时"以及如何使PHP自动加载器抛出错误错误

时间:2016-10-14 15:20:59

标签: php autoloader spl-autoload-register

在我当前的配置中,每当某个PHP文件出现致命错误(例如语法错误或调用不存在的函数)时,我通常会收到如下错误消息:

Parse error: syntax error, unexpected <whatever> in /path/to/file.php on line XXX

Fatal error: Call to undefined function whatever() in /path/to/file.php on line YYY
输出中的

等。

但是,我使用的是使用第三方自动加载器的第三方库。每当在任何自动加载的类中出现致命错误(包括解析错误或调用未使用的函数 - 实际上并不完全确定后者但肯定是解析错误的情况)时,我只得到一个空白页,不仅如此:在Apache的error_log文件中甚至没有记录任何错误,通常会记录PHP致命错误。所以调试变得不可能。

我无法强调这一点:当某些自动加载文件中的致命错误为时,此仅发生。在所有其他情况下(当然包括通过require()include()等包含的文件中的错误),输出和error_log中都会显示相同的错误。

我没有编写自动加载器代码,但它基本上是这样的:

    // no idea why this line, but I don't think it's relevant:
    ini_set('unserialize_callback_func', 'spl_autoload_call');

    spl_autoload_register(array('My_Autoloader', 'autoload'), true);

    class My_Autoloader {
        static function autoload($classname) {
            $filename = //.... computes $filename from $classname
            require_once($filename);
        }
    }

如果错误不在自动加载的文件中,必须有一种方法让自动加载器抛出错误的方式与抛出(和处理)的方式相同,对吗?

我如何得到它?

3 个答案:

答案 0 :(得分:0)

语法错误仅在命令行上检查

使用PHP的php -l somefile.php shell_exec('php -l /fullpath/to/somefile.php')

但您必须分析respone字符串以查找错误。

正常回复No syntax errors detected in somefile.php

在PHP&lt; = 5.0.4中有php.net/manual/en/function.php-check-syntax.php

这是一个有效的致命错误:

register_shutdown_function(function(){
    $err=error_get_last();
    if($err['type']===1){
       /*you got an fatal error do something, write it to an file*/
       #file_put_contents(var_export($err,true),'myfatalerror.log');
    }
});

希望有所帮助:)

答案 1 :(得分:0)

代码按照您的建议行事的唯一方法是第三方代码是否覆盖了错误报告。这通常被认为是生产系统的良好实践,但它应该记录错误

您的第三方代码导致此类错误让我暂时不知道其质量,但我们暂时忽略它。

PHP的内置机制将处理报告(到浏览器)和日志记录(到文件)。在调用set_error_handler()之后,可以通过您自己的代码管理非致命错误,但是不会通过此路由传递致命错误。可以在您自己的代码using register_shutdown_function()中捕获和处理致命错误。但首先要检查日志文件。

正如您所说,如果禁用错误记录和错误报告,则停止使用此第三方代码 - 它是有毒的。

答案 2 :(得分:-2)

使用php例外,您可以将文件调用到

function inverse($x) {
    if (!$x) {
        throw new Exception('Division par zéro.');
    }
    return 1/$x;
}

try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Exception reçue : ',  $e->getMessage(), "\n";
}