首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从Kint中模拟/捕获不寻常的PHP操作数

如何从Kint中模拟/捕获不寻常的PHP操作数
EN

Stack Overflow用户
提问于 2021-11-04 19:46:46
回答 2查看 96关注 0票数 2

背景(简介)

金特是一个PHP调试工具,可以作为PHP的var_dump()print_r()debug_backtrace()的更强大的替代品。Kint的一个不寻常的特性--至少对于PHP --是以操作数的形式使用实时修饰符的能力。下面是手册中关于该功能的说明:

有几个实时修饰符可以使用:

  • ~d($var)这个调用将以纯文本格式输出。
  • +d($var)将忽略深度级别限制,输出所有内容。小心,这会把你的浏览器挂在大对象上!
  • !d($var)将自动扩展输出。
  • -d($var)将尝试对以前的输出进行ob_clean,并在打印后刷新。
  • 您也可以组合修饰符:~+d($var)

如果需要更多信息,有一个类似于这个问题的老出了这么多问题

问题

  1. Kint如何在不触发PHP错误的情况下添加这些操作数?
  2. 我如何模拟/捕获使用这些操作数的调用?

如果不加载Kint,如果尝试使用这些操作数或创建自己的函数来捕获Kint调用,则会得到Fatal error: Uncaught Error: Unsupported operand types

重要:,我正在使用kint.phar文件,而不是使用composer或任何类型的CLI使用。

我的用例(请不要因问题而分心)

我为那些好奇的人添加这些信息,并进一步澄清我的问题。我真诚地想学习和理解他们是如何做到这一点的,并希望对此作出答复。这个问题与维护/批评/不同意我的用例无关:

为了安全和优化,我正在创建一个假的(空的) Kint类,当我的站点处于生产模式时加载它。这确保了在意外情况下留在代码中的任何Kint调用不会触发致命错误,永远不会输出任何内容,并且与加载真正的Kint类相比使用更少的资源。

我知道您可以使用Kint::$enabled_mode = false;禁用Kint,但不要关注这个问题。下面是我用来伪造Kint类的代码。所缺少的只是捕获使用这些非标准操作数的调用:

代码语言:javascript
复制
/**
 * Fake class.
 */
class Kint {

    const STATIC_BLACKHOLE = '';

    public static $enabled_mode = false;

    public function blackhole( $a ) {
        return;
    }

    public function __call( $m, $a ) {
        return call_user_func_array( array( $this, $this->blackhole ), $a );
    }

    public static function __callStatic( $m, $a ) {
        return self::STATIC_BLACKHOLE;
    }

}
$kint = new Kint();

// Alias of Kint::dump().

/**
 * Fake function to catch d().
 *
 * @return void
 */
function d() {
    return;
}

// Kint::dump basic mode.

/**
 * Fake function to catch s().
 *
 * @return void
 */
function s() {
    return;
}

\define( 'KINT_DIR', '/classes/Kint' );
\define( 'KINT_WIN', DIRECTORY_SEPARATOR !== '/' );
\define( 'KINT_PHP70', ( \version_compare( PHP_VERSION, '7.0' ) >= 0 ) );
\define( 'KINT_PHP71', ( \version_compare( PHP_VERSION, '7.1' ) >= 0 ) );
\define( 'KINT_PHP72', ( \version_compare( PHP_VERSION, '7.2' ) >= 0 ) );
\define( 'KINT_PHP73', ( \version_compare( PHP_VERSION, '7.3' ) >= 0 ) );
\define( 'KINT_PHP74', ( \version_compare( PHP_VERSION, '7.4' ) >= 0 ) );
\define( 'KINT_PHP80', ( \version_compare( PHP_VERSION, '8.0' ) >= 0 ) );
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-11-04 22:07:08

“实时修饰符”都是有效的PHP一元运算符:

因此,只要函数返回运算符通常使用的值类型,就完全允许在这些运算符中使用前缀函数调用。

代码语言:javascript
复制
function foo() {
    return 0;
}

// All of these work just fine, and generate no errors:
-foo();
+foo();
!foo();
~foo();

据我所知,Kint在其函数中所做的是使用debug_backtrace()获取调用函数的源文件。然后,它打开该文件,读取它,定位调用行,并解析它,以确定使用了什么“实时修饰符”作为函数调用的前缀。例如,考虑消息来源:

代码语言:javascript
复制
function d($var) {
    // dump $var
}

~d($GLOBALS);

d()函数中的代码通常无法判断其返回值即将由~操作符修改。(这不应该!这样做完全违反了词法和逻辑范围。)但是,Kint转义这个作用域,重新解析源文件,找到~,然后使用它来修改函数中的代码生成的输出。

这一技术非常混乱,构成了巨大的性能打击,范围违反,并提出了一个安全问题.所有这些都提供了一个低级的实现语言已经具备的基本功能-函数参数.我绝不会让这个模块接近我的任何生产服务器。

尽管如此,我的建议是忘记试图用noops覆盖Kint的运行时功能。相反,构建管道以便无法部署Kint:

  • 确保在撰写要求中使用--dev
  • 确保在部署脚本中使用--no-dev
  • 添加一个检查到您的引导或前端控制器,以立即中止,如果Kint是加载。
  • 在部署前使用PHPCS中的“禁用函数”嗅探,以检测源中遗留的Kint函数的任何用法。
票数 2
EN

Stack Overflow用户

发布于 2021-11-08 21:44:29

这是Kint的原作者。

我解决了大多数提出的关于操作数本身的实现细节( 在这个答案中 )的问题。

下面是OP usecase:

I通常会做的是在生产中包括Kint!它是完全安全的-或与任何其他作曲家包一样安全。它经常更新过去的10+年。它包含在测试中,仅通过包含它,甚至在禁用时调用它,都不会对性能造成任何可测量的影响。

代码语言:javascript
复制
Kint::$enabled_mode = false;

此外,我喜欢使用它来记录复杂的变量( ofc有很大的性能成本来支付详细的费用),以及类似的功能,无论如何都需要它出现在生产中。

如链接答案中所述,操作数是实时调试时常用用例的缩写。如果您想推出依赖于操作数的永久功能,我只需将其重写到详细的版本中,以使其更易读:

所以,例如

代码语言:javascript
复制
$log = @d($var);

化作

代码语言:javascript
复制
$oldReturnValue = Kint::$return;
Kint::$return = true;

$log = Kint::dump($var);

Kint::$return = $oldReturnValue;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69845019

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档