如何模拟并捕获Kint中的非常规PHP操作数且不触发报错
回答
1. Kint实现操作数修饰符不报错的底层逻辑
核心原理是利用PHP的一元运算符优先级 + 类型转换规则实现:
- 函数调用的优先级高于所有一元运算符(
~、+、!、-都属于一元运算符),所以写~d($var)时,PHP会先执行d($var),再把返回值交给~运算符处理,而非反过来。 - Kint的
d()/s()等方法不会直接输出内容,也不会返回空值,而是先返回一个内部封装的临时对象。这个对象实现了所有对应一元运算符触发的类型转换魔术方法:- 触发
!运算时,PHP会尝试将对象转为布尔值,触发对应魔术方法 - 触发
+/-运算时,PHP会尝试将对象转为数值类型,触发对应魔术方法 - 触发
~运算时,PHP会尝试将对象转为字符串/整型,触发对应魔术方法
- 触发
- 每触发一次运算符对应的魔术方法,Kint就会在临时对象上追加对应的修饰标记,所有运算符处理完成后,再执行最终的输出逻辑。
你之前写的模拟函数用return;默认返回null,PHP对null执行一元运算符运算时自然会报「不支持的操作数类型」致命错误。
2. 模拟捕获带修饰符调用的实现方案
最简方案
如果只需要避免报错、不输出任何内容,不需要额外逻辑,直接调整d()、s()函数的返回值为字符串类型即可,所有一元运算符都可以正常作用在字符串上,不会触发致命错误:
function d() { // 返回空字符串承接所有运算符操作 return ''; } function s() { return ''; }
可扩展方案
如果后续需要对不同修饰符做额外处理,可以返回一个实现了魔术方法的空占位类,兼容所有组合修饰符写法:
<?php /** * 空占位类,承接所有一元运算符操作 */ class KintBlackhole { // 触发布尔转换时调用(对应!运算符) public function __toString() { return ''; } // 兜底所有调用 public function __call($name, $arguments) { return $this; } public static function __callStatic($name, $arguments) { return new self(); } } class Kint { public static $enabled_mode = false; public function __call($m, $a) { return new KintBlackhole(); } public static function __callStatic($m, $a) { return new KintBlackhole(); } } $kint = new Kint(); function d() { return new KintBlackhole(); } function s() { return new KintBlackhole(); } // 原有常量定义保留 \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 ) );
内容的提问来源于stack exchange,提问作者Blizzardengle
相关产品推荐
相关产品推荐

