如何在PHP中使用trigger_error时获得正确的行号?

uurv41yg  于 2023-10-15  发布在  PHP
关注(0)|答案(6)|浏览(133)

我使用trigger_error在自定义类中“抛出”错误。我的问题是trigger_error打印出调用trigger_error的行号。例如,给定以下代码:

01    <?php
02        class Test {
03            function doAction() {
04                $this->doSubAction();
05            }
06            
07            function doSubAction() {
08                if(true)
09                    trigger_error('Custom error', E_USER_WARNING);
10            }
11        }
12        
13        $var = new Test();
14        $var->doAction();
15    ?>

PHP将打印出以下内容:

警告:test.php自定义错误第9行**

如何让PHP返回doAction()函数被调用的那一行(在类外部调用的方法,忽略所有内部调用),如下所示?

警告:test.php自定义错误14行**
**修改:**修改我的例子,使其更接近我想要实现的目标。

qnakjoqk

qnakjoqk1#

最好的办法是设置一个显示完整堆栈跟踪的错误处理程序。
设置自定义错误处理程序,并在其中调用debug_print_backtrace()。你会发现这在一般情况下是有用的,在这个特定的情况下也是如此。

dy1byipe

dy1byipe2#

好了,对于那些对我的最终解决方案感兴趣的人,我在我们的框架中集成了以下代码,它在我们可以测试的所有情况下都返回正确的行号。我们在生产中使用它。
ErrorHandler class
它捕获未捕获的PHP异常,PHP错误和PEAR::Error s。如果代码中有一些框架特定的函数,你需要稍微修改一下,但它们应该不难找到。好好享受吧!

igsr9ssn

igsr9ssn3#

两个选择,没有一个是特别可口的:

  • 让test()在参数中提供__LINE__(例如:“test(__LINE__)“,并将参数给予trigger_error)。设置错误处理程序以打印自定义错误消息。***:-)
  • 设置一个错误处理程序,让它调用并处理debug_backtrace()的超大输出。此功能在调试时很有用...但对你的目的来说太过分了。请不要将此功能用作系统常规操作的一部分。

简短回答:太难了,不要尝试。:-|

roejwanj

roejwanj4#

我通常也会在那里放一个trigger_error()。这确保了我知道调用它的确切位置以及实际错误发生的确切位置。然后,在生产过程中,我会将所有错误通过电子邮件发送给自己。我知道这不是自动的,但至少你可以追踪发生了什么。

sulc1iza

sulc1iza5#

我想我会把我的两分钱投入到锅里,讨论一下我通常使用的东西,无论是按原样还是经过小的定制,我构建的PHP库经常被其他开发人员使用。
我将程序执行过程中可能出现的错误细分为两类:那些是错误编程的结果,以及那些由于用户错误或某些外部因素而发生的。对于前者,我将trigger_error与E_USER_ERROR结合使用,而后者则是一个Exception,特别是一个包Exception,然后由库中的所有其他对象继承。
开发错误的一个例子是,在一个应该是字符串的参数中传递一个整数(V7之前),或者访问一个不存在的类的方法或属性。(您可以在这里发挥自己的开发人员想象力。)显然,另一个开发人员不会关心错误是在__get或__set语句或其他一些神奇的构造的内部深处生成的,而是想知道他们的错误具体在哪里。让我们面对现实吧……开发人员不喜欢费力地回溯。
因此,我用来本地化错误消息的方法很简单:

function localize_error_msg($msg, $level) {
    $level = (int)$level;
    $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, $level + 1)[$level];
    return $msg . " in " . $backtrace['file'] . " on line " . $backtrace['line'];
}

我传入了依赖于所使用的构造的回溯级别,通常是1或2,其余的是不言自明的。
为了防止重复的“in file on line n”,我添加了这个错误处理程序:

set_error_handler(function($errno, $errstr, $errfile, $errline) {
    if (preg_match('/on line \d+$/', $errstr) === 1)
        die($errstr);
    else return false;
}, E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE);

再说一次,我喜欢保持简单。有人可能会说错误消息的本地化应该发生在处理程序中,但是,你必须能够传递深度,现在是处理程序内部的额外2层,然后,它变得混乱。
快乐小径!

llew8vvj

llew8vvj6#

你应该设置一个错误处理程序,只为你的函数和类打印自定义错误消息。这是一个简单的例子,适用于PHP 5,7和8:

function my_error_handler($errno, $errstr, $errfile, $errline) {

  static $callables = array(
    "myFunc",
    "myClass::myFunc1",
    "myClass->myFunc2",
    "myNamespace\MyClass->myFunc",
  );

  $trace = debug_backtrace();
  if (isset($trace[2])) {
    $trace = $trace[2];

    $callable = "";
    if (isset($trace["class"])) {
      $callable .= $trace["class"];
    }
    if (isset($trace["type"])) {
      $callable .= $trace["type"];
    }
    if (isset($trace["function"])) {
      $callable .= $trace["function"];
    }

    if (in_array($callable, $callables)) {
      die("Fatal error: " . $errstr . " in " . $trace["file"] . " on line " . $trace["line"]);
    }
  }  
  return false;
}

set_error_handler("my_error_handler", E_USER_ERROR);

测试:

function myFunc() {
  trigger_error("My Error", E_USER_ERROR);
}

// Fatal error: My Error in <some file> on line XXX
myFunc(); // <-- LINE XXX is here

相关问题