为了账号安全,请及时绑定邮箱和手机立即绑定

如何从生产 PHP 代码中获取正确的调试上下文?

如何从生产 PHP 代码中获取正确的调试上下文?

PHP
至尊宝的传说 2021-11-26 15:38:55
要求我们在网络服务器上运行生产 PHP 代码。在某些情况下,我们希望使用上下文信息来丰富调试输出(例如到 error.log)。上下文可以具有任意字段和结构。我们的目标是找到一个通用的调试生成函数,它在任何极端情况下都不会产生警告。如果输出只是部分是可以接受的。TL; 博士所有三个 PHP 标准函数都会在特定上下文中导致警告:print_r和var_dump无法处理连接关闭的 mysqli 对象var_export无法处理递归题有没有办法将任意对象的上下文作为人类可读的字符串返回?测试用例// Dealing with recursion:$recObj = new stdClass();$recObj->recursion = $recObj;print_r   ($recObj);  // worksvar_export($recObj);  // throws: "Warning: var_export does not handle circular references"var_dump  ($recObj);  // works// dealing with mysqli$mysqli = mysqli_connect('mysql', 'root', 'myPass', 'mysql');print_r   ($mysqli);  // worksvar_export($mysqli);  // works as in "does not throw warnings" but all values are nullvar_dump  ($mysqli);  // works// Try again with closed connectionmysqli_close($mysqli);print_r   ($mysqli);  // throws: "Warning: print_r(): Couldn't fetch mysqli"var_export($mysqli);  // works (again all values are null)var_dump  ($mysqli);  // throws: Warning: var_dump(): Couldn't fetch mysqli根据关闭的 mysqli 连接的相关性:如果您在错误处理程序或注册的关闭函数中进行上下文打印(这是一个很好的位置),一旦您到达该连接,mysqli 对象将已经自动关闭连接处理程序。如您所见,没有任何内置输出方法能够返回您抛出的任何上下文。考虑的选项可以使用@notation 来抑制警告。但是,注册的错误处理程序和关闭函数仍然会被错误调用,并且需要自定义逻辑来忽略该特定错误。这可能会隐藏真正的错误,并且如果处理像 sentry.io 这样的 3rd 方错误跟踪系统也会变得非常烦人该serialize()函数在任何情况下都不会产生警告,但缺乏人类可读性。该json_encode()函数可以比序列化更具可读性,但它在递归测试用例中不返回任何内容......
查看完整描述

1 回答

?
不负相思意

TA贡献1777条经验 获得超10个赞

我没有找到一个内置的打印功能,它在包含具有关闭连接的 mysqli 对象时不会导致错误/警告(我实际上将其归类为错误/不需要的行为)。


我们结束了加入的Symfony Vardumper通过


composer require symfony/var-dumper

并编写一个小辅助函数来显示来自 cli 脚本或浏览器的正确和漂亮的输出:


use Symfony\Component\VarDumper\Cloner\VarCloner;

use Symfony\Component\VarDumper\Dumper\CliDumper;

use Symfony\Component\VarDumper\Dumper\HtmlDumper;


class Debug {

    /**

     * Method provides a function which can handle all our corner-cases for producing 

     * debug output.

     *

     * The corner cases are:

     * - objects with recursion

     * - mysqli references (also to closed connections in error handling)

     *

     * The returned result will be:

     *  - formatted for CLI if the script is run from cli

     *  - HTML formatted otherwise

     *      - The HTML formatted output is collapsed by default. Use CTRL-left click to 

     *        expand/collapse all children

     *  - You can force html|cli formatting using the optional third parameter

     *

     * Uses the Symfony VarDumper composer module.

     *

     * @see https://github.com/symfony/var-dumper

     * @see https://stackoverflow.com/questions/57520457/how-to-get-proper-debug-context-from-production-php-code-print-r-vs-var-export

     * @param mixed       $val    - variable to be dumped

     * @param bool        $return - if true, will return the result as string

     * @param string|null $format null|cli|html for forcing output format

     * @return bool|string

     */

    public static function varDump($val, $return = false, $format = null) {

        if (is_null($format)) {

            $format = php_sapi_name() == 'cli' ? 'cli' : 'html';

        }

        $cloner = new VarCloner();

        if ($format === 'cli') {

            $dumper = new CliDumper();

        } else {

            $dumper = new HtmlDumper();

        }


        $output = fopen('php://memory', 'r+b');

        $dumper->dump($cloner->cloneVar($val), $output);

        $res = stream_get_contents($output, -1, 0);


        if ($return) {

            return $res;

        } else {

            echo $res;

            return true;

        }

    }

}

那个方法


可以处理我传递给它的所有输入而没有错误或警告

CLI 和 HTML 的格式都很好

将结果作为字符串返回,以便将其转发到外部错误跟踪系统,如哨兵

所以它勾选了我在最初问题中要求的所有方框。


感谢@BlackXero 正确理解问题并将我指向正确的方向。


查看完整回答
反对 回复 2021-11-26
  • 1 回答
  • 0 关注
  • 178 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信