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

时间:2008-10-09 02:58:17

标签: php error-handling

我正在使用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

修改:修改我的示例,使其更贴近我想要实现的目标。

5 个答案:

答案 0 :(得分:2)

最好的办法是设置一个显示完整堆栈跟踪的错误处理程序。

设置自定义错误处理程序,并在其中调用debug_print_backtrace()。在这种特殊情况下,您会发现这一点很有用。

答案 1 :(得分:0)

两种选择,都不是特别适合:

  • 覆盖让test()在参数中提供__LINE__(例如“test(__LINE__)”,并将参数提供给trigger_error)。设置错误处理程序以打印自定义错误消息。 注意:这是非常丑陋的。 : - )

  • 设置错误处理程序,让它调用并处理debug_backtrace()的可怕大量输出。这个函数在调试时非常有用......但是对于你想要做的事情来说太过分了。请不要将此功能用作系统常规操作的一部分。

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

好的,对于那些对我的最终解决方案感兴趣的人,我在我们的框架中集成了以下代码,在我们可以测试的所有情况下返回正确的行号。我们正在生产中使用它。

ErrorHandler class

它捕获未捕获的PHP异常,PHP错误和PEAR::Error。如果代码具有一些特定于框架的功能,您将需要稍微修改它,但它们不应该难以追踪。享受!

答案 4 :(得分:0)

我想我会把我的两分钱扔到底池中,讨论我通常使用的内容,无论是原样还是小型自定义,我构建的PHP库通常被其他开发人员使用。

我将程序执行过程中可能出现的错误细分为两类:错误编程导致的错误以及由于用户错误或某些外部因素导致的错误。对于前者,我将trigger_error与E_USER_ERROR结合使用,后者使用Exception,特别是包异常,然后由库中的所有其他异常继承。

开发错误的一个示例是在参数中传递一个整数,该参数应该是一个字符串(在V7之前)或访问一个不存在的类的方法或属性。 (你可以在这里使用你自己的开发人员的想象力。)显然,另一个开发人员并不关心错误是在__get或__set语句或其他一些魔法结构的内部产生的,而是他们&#39;我想知道他们的错误在哪里。让我们面对现实吧...开发人员不想涉及回溯。

因此我用来本地化错误消息的方法就是:

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,其余部分是自解释的。

为防止&#34;在第n&#34;行的文件中重复序列,我添加了这个错误处理程序:

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个深度,而且,它之后会变得混乱这一点。

快乐小径!