【问题标题】:How to get proper line number when using trigger_error in PHP?在 PHP 中使用 trigger_error 时如何获取正确的行号?
【发布时间】:2008-10-09 02:58:16
【问题描述】:

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

编辑:修改了我的示例,使其更接近我想要实现的目标。

【问题讨论】:

    标签: php error-handling


    【解决方案1】:

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

    设置自定义错误处理程序,并在其中调用 debug_print_backtrace()。您会发现这通常很有用,在这种特定情况下也是如此。

    【讨论】:

      【解决方案2】:

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

      ErrorHandler class

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

      【讨论】:

      • 哇,这就是我一直在寻找的一切。做得很好!
      【解决方案3】:

      两种选择,没有一种特别好吃:

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

      • 设置一个错误处理程序,并让它调用和处理 debug_backtrace() 的巨大输出。此功能在调试时很有用......但对于您正在尝试做的事情来说太过分了。请不要将此功能用作系统常规操作的一部分。

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

      【讨论】:

      • 可能需要行号表示某种非常糟糕错误,开发人员需要在其中进行一些认真的调试。在那种情况下,我不会认为解析 debug_backtrace() 输出的开销会过大。
      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        我想我会把我的两分钱扔进锅里,讨论我通常使用的东西,无论是按原样还是通过小的自定义,我构建的 PHP 库经常被其他开发人员使用。

        我将程序执行期间可能出现的错误分为两类:一类是错误编程造成的,另一类是由于用户错误或某些外部因素造成的。对于前者,我将 trigger_error 与 E_USER_ERROR 结合使用,后者是一个 Exception,特别是一个包 Exception,然后由库中的所有其他 Exceptions 继承。

        开发错误的一个例子是在参数中传递一个整数,该参数应该是一个字符串(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 层,而且,它在之后变得混乱那个。

        快乐的足迹!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-07-19
          • 2021-10-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-07
          • 1970-01-01
          • 2020-05-07
          相关资源
          最近更新 更多