【问题标题】:How to make a PHP autoloader throw an error when the autoloaded file has "compile-time" errors (never mind, it already does)当自动加载的文件有“编译时”错误时,如何使 PHP 自动加载器抛出错误
【发布时间】:2017-02-24 02:15:47
【问题描述】:

在我当前的配置中,每当某些 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 中都会出现相同的错误。

autoloader的代码不是我写的,但基本上是这样的:

    // 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);
        }
    }

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

我如何得到它?

【问题讨论】:

  • 从我的评论中得到答案
  • 但是这个Fatal error: Call to undefined function whatever()与语法错误无关。
  • 在 PHP7 中,大多数致命错误都已转换为可捕获的异常。 trowski.com/2015/06/24/throwable-exceptions-and-errors-in-php7
  • 您可以静态分析所有文件以消除命令行中的解析错误问题,例如在 Unixoid 上(在您的代码根目录中):find -type f -exec php -l {} \; &gt; /dev/null

标签: php autoloader spl-autoload-register


【解决方案1】:

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

php -l somefile.php 来自 PHP shell_exec('php -l /fullpath/to/somefile.php')

但您必须分析响应字符串是否有错误。

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

在 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');
    }
});

希望对您有所帮助:)

【讨论】:

  • @matteo 看看!
  • 这不会从您调用它的主文件中检查文件 include()d 的语法,是吗?
  • 问题是存在假定语法错误或致命错误的文件是自动加载器动态加载的无数文件之一,因此手动检查每个文件不太可行...
  • 不,您必须自己测试它,这可以在包含文件之前在自动加载器中进行。我不得不问:为什么你的应用程序有语法错误的文件?为什么不现在用php -l somefile.php 检查它们并修复文件,然后你就可以摆脱语法错误并继续修复其他错误。注意:在编译 php 文件之前检测到语法错误,所有其他错误都在运行时
  • 有 50% 的语法错误的无数文件,希望这些代码背后没有公司。我会踢CEO。或者是谁让这件事发生的?
【解决方案2】:

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

您的第三方代码导致了此类错误,这让我怀疑它的质量,但我们暂时忽略它。

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

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

【讨论】:

  • “如果第三方代码覆盖了错误报告,代码会按照您的建议运行的唯一方法”。不,不是。
  • “你的第三方代码导致了这样的错误让我停下来想知道它的质量”。可能我不是很清楚:原来的代码没有错误,我自己在修改的时候介绍的。此外,错误不一定在第三方代码中,它们可能在我自己的代码中,通过第三方自动加载器自动加载。问题是,虽然通常会打印 记录任何致命错误,包括解析错误和对未定义函数的调用,但在自动加载的代码中不会出现这些错误。我开始认为这是 PHP 的(非常错误的)行为。
  • 关于这个:“我开始认为这是 PHP 的(非常错误的)行为”。我试图建立一个旨在重现问题的最小测试用例,但事实并非如此。所以这给了我希望:一定是发生了一些更微妙的事情,或者这个特定的自动加载器 is 实际上正在做一些可以避免的事情并且“消除”错误。但是,我不知道要寻找什么。我已经对“error_reporting”进行了搜索,但没有任何结果,而且我在源代码中找不到任何明确地对错误做任何事情的东西。任何想法我需要寻找什么?
【解决方案3】:

使用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";
}

【讨论】:

  • 我认为这与我的问题无关。我说的是致命错误,例如语法错误,而不是异常。
猜你喜欢
  • 2023-03-03
  • 2018-03-06
  • 2016-01-01
  • 2016-09-05
  • 2015-05-27
  • 2016-04-04
  • 1970-01-01
  • 2013-10-18
  • 1970-01-01
相关资源
最近更新 更多