【问题标题】:How to trace call to output buffer如何跟踪对输出缓冲区的调用
【发布时间】:2017-12-14 03:15:38
【问题描述】:

所以场景是我有一个使用输出缓冲的应用程序,除了预期的结果之外,该应用程序还返回了一些额外的数据。我可以操纵将预期结果添加到输出缓冲区的点,以确认在应用程序的这一点上,发送到输出缓冲区的数据是正确的,因此意外的额外数据必须来自另一个来源。

我怀疑问题是不在 PHP 脚本标签内的杂散字符,但我无法确定哪些(如果有)文件是罪魁祸首。据我所知,可能包含一些文件实际上正在对额外数据进行明确的echo

所以我希望捕获写入输出缓冲区的任何文件的文件名和行号,但事实证明这比我预期的要困难得多。我知道最初的ob_start 在哪里,所以我一直在尝试使用自定义的output_callback。以下是我已经尝试过的一些事情:

ob_start(function($string) { 
    return __FILE__ . ":" . __LINE__ . " : " $string; 
});

这将返回定义函数的文件名和行号,而不是调用它的位置(正如预期的那样,我猜,但开始不好)。

ob_start(function($string) { 
    return print_r(debug_print_backtrace(), true) . " : " $string; 
});

这会引发有关销毁 lambda 函数的错误。

ob_start(function($string) { 
    return var_dump(debug_backtrace()) . " : " $string; 
});

这有好坏参半的结果。我承认我不完全确定为什么。但在大多数情况下,var_dump 解析为一个空字符串(什么都没有),但在一种情况下,它似乎生成了一些跟踪数组,但没有任何反映 ob_start 调用来源的东西(换句话说,不管它输出,实际调用 echo 的源文件不是跟踪的一部分)。

请记住,通过上述内容,我一直在进行一些非常基本的测试,只是为了弄清楚当我准备将自定义 output_callback 函数放入故障排除上下文时会是什么样子。所以这个问题不是特定于应用程序的,我只是想找到一种通用的方法来拦截输出函​​数(echo、print 等)并获取有关输出调用起源的信息。

【问题讨论】:

    标签: php output-buffering debug-backtrace


    【解决方案1】:

    可能的解决方案

    1

    如果您的代码使用输出缓冲来输出该杂散字符,则以下解决方案可以提供帮助。你也是对的,它只在输出缓冲被刷新/检索时才起作用,而不是在每个 print/echo 语句中。此外,所有的原生函数在回调函数中都不起作用,print_r 就是其中之一,但我们可以抛出 Exception。请尝试以下代码,看看它是否可以帮助您解决问题。

    ob_start(function($buffer) {
        try {
            $stackTrace = debug_print_backtrace();
            throw new \Exception($stackTrace, 1);
        } catch (\Exception $ex) {
            //This line can be logged to a file instead of appending to the buffer
            $buffer .= PHP_EOL.$ex->getTraceAsString().PHP_EOL.PHP_EOL;
        }
        return $buffer;
    });
    

    2

    如果第一个解决方案不能帮助解决您的问题,您可能需要使用高级调试和分析工具,例如 Xdebug

    3

    如果您真的不关心在当前行之前已经回显的内容,或者如果您想将来证明类似的问题不会发生,您可以在您之前使用 ob_end_clean 清除缓冲区ob_start。

    ob_end_clean();
    ob_start();
    

    4

    在结束标记后查找所有 PHP 空白:

    pcregrep -rMl '\?>[\s\n]+\z' *
    

    pcregrep -rM '\?>[\s]+[^\S]*$' *.php
    

    【讨论】:

    • 我认为这不能作为故障排除工具,因为 1)它不会指出哪些文件对输出有贡献(因此我们无法更清楚地了解输出的位置来自)和 2)在您的示例中,它假定 fudgey 输出出现在 ob_start 之前,但不一定是这种情况。自定义扩展可能会在正确的ob_start 内容范围内对输出做出贡献,但只是有错误或在不应该输出的时候输出。目标是确定任何潜在输出的来源。
    • 做更多的测试,我现在知道自定义ob_callback 函数是在输出缓冲区被刷新/检索时调用的,而不是每次写入时,我是这么理解的。有什么方法可以在输出缓冲区更新时触发回调?
    • 是否可以(或建议)覆盖php://output 流,使其正常运行,但也会向错误日志发送时间戳或其他标识符,然后可以根据跟踪进行协调文件?
    • 嗨@Anthony 我已经根据你的 cmets 更新了我的答案。
    • 嗨@Anthony 第一个选项对您有什么帮助吗?
    猜你喜欢
    • 1970-01-01
    • 2011-01-20
    • 2011-07-24
    • 2011-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多