4

在 file1.php 中:

set_error_handler('my_error_handler');
set_exception_handler('my_exception_handler');

function my_error_handler($errNo, $errStr, $errFile, $errLine, $whatever = null){
  // here ErrFile and $errLine are correct only for native funcs...
  throw New ErrorException($errStr, 0, $errNo, $errFile, $errLine);
}

function my_exception_handler($exception){
  print $exception->getLine(); // correct only for native functions
  print $exception->getFile(); // correct only for native functions
}

在 file2.php 中,一个示例函数定义:

function foo($requiredArg){

}

在 file3.php 中,调用 foo:

  foo();

产生:

foo() 缺少参数 1,在第 2 行的 file3.php 中调用并定义...

消息是正确的,但是当我尝试获取文件并使用$exception->getFile()and $exception->getLine()(在我的异常处理程序中)时,我得到了定义 foo() 的文件和行,而不是调用它的位置...

但是使用原生 PHP 函数,我得到了调用函数的文件和行(这就是我想要的)。

4

2 回答 2

2

它只是归结为最接近的第一。

当您使用核心或内置函数时,它们的定义包含在 PHP 的核心中。这意味着与用户定义的函数相比,该函数的定义不可用,用户定义的函数的定义很容易获得。

如果您在引用用户定义函数错误的函数内部运行debug_backtrace();or ,您将首先看到函数的定义,然后是函数的调用。如果您调用内部函数,您只会看到调用行,因为 PHP 无法告诉您脚本或包含文件中定义内部函数的代码行,因为它是在核心中定义的。$exception->getTrace();exception_handler

这是错误处理的操作顺序。如果要获取调用该函数的实际行,可以查看跟踪并获取第二个数组对行号的引用。

于 2012-07-20T17:31:45.687 回答
1

好问题!

对于本机和用户定义的函数,事情似乎确实有所不同。但是,一件显而易见的事情是,如果它是本机的,则无法真正告诉您函数的定义位置,因为它是用 C 编写的,而不是 PHP。不过,在用户空间代码的情况下,找出它被调用的地方会很高兴。一种方法是仅从捕获的异常中解析该错误消息,您可以获得创建它的文件和行。

function my_exception_handler($exception)
{
    $message = $exception->getMessage();
    $file    = $exception->getFile();
    $line    = $exception->getLine();

    if(strpos($message, 'called in') !== false) {
        preg_match('/called in .*php/', $message, $matches);
        $file = str_replace('called in ', '', $matches[0]);

        preg_match('/on line \d/', $message, $matches);
        $line = str_replace('on line ', '', $matches[0]);
    }

    echo 'line: ' . $line . PHP_EOL;
    echo 'file: ' . $file . PHP_EOL;
}

来自问题的基于输出的描述,已更改my_exception_handler

line: 4
file: /tmp/file3.php
于 2012-07-20T17:24:24.900 回答