/ Kint

Kint modifier原理

当调试PHP代码时,我们通常使用var_dump()、print_r()和debug_backtrace()来输出我们想看到的信息,但是都很不友好。Kint 是一款开源的PHP调试工具,它提供了更好的调试体验。

在看使用文档时,我发现了一个有趣的功能,http://raveren.github.io/kint/#advanced,其中的Real-time modifiers一节,我们可以在Kint::dump()函数前加上+ – ! @这个四个符号来改变Kint::dump的输出行为。

按理说,单纯的PHP,函数应该是无法直接侦测到外界对该函数的调用方式,而且官方文档也说了,这不是PHP的语法:

Kint also uses a non-standard PHP feature: modifiers. This is not a language feature;

于是就看了下Kint的源码,看看具体是怎么实现的。

因为改变的是Kint::dump()函数的行为,所以我们直奔dump函数。

粗略看一眼dump的代码,发现dump内的局部变量$modifier影响了dump函数的行为,所以我们就要看$modifier是从哪来的。

$trace = debug_backtrace(); list( $names, $modifier, $callee, $previousCaller ) = self::_getPassedNames( $trace );

很明显,我们应该去分析_getPassedNames这个函数,与$modifier变量相关的代码如下:

$file = fopen( $callee['file'], 'r' ); //变量$callee是从debug_backtrace中获取的,是调用Kint::dump相关的那一项 $line = 0; $source = ''; while ( ( $row = fgets( $file ) ) !== false ) { if ( ++$line > $callee['line'] ) break; $source .= $row; } fclose( $file ); //获取源文件中从调用Kint::dump那行开始直到结束的所有代码。 $source = self::_removeAllButCode( $source ); //格式化源代码,具体看下文 $codePattern = empty( $callee['class'] ) ? $callee['function'] : $callee['class'] . "\x07*" . $callee['type'] . "\x07*" . $callee['function']; preg_match_all( "#\x07{(?{$codePattern}\x07*(\()#i", $source, $matches, PREG_OFFSET_CAPTURE ); $match = end( $matches[2] ); $modifier = end( $matches[1] ); $modifier = $modifier[0];

其中self::_removeAllButCode()函数会把php源代码进行一次格式化,把php注释、html删除,把”” “<?=”、空白字符以及”;”替换成”\x07″。$codePattern则是Kint::dump的正则表达式(因为Kint提供一些别名函数,例如d()和dd()来代替Kint::dump(),因此$codePattern需要根据具体情况生成),当正则匹配到Kint::dump函数时,就能获取到Kint::dump前面的符号,然后根据具体符号实现不同的操作。

Kint modifier原理
Share this