如何不用eval且避免自动类型转换,验证变量匹配字符串定义的类型?
替代eval的严格类型检查实现
可以实现一个不依赖eval、且做严格类型检查的函数来满足需求。核心思路是解析类型字符串,拆分出所有需要匹配的类型项,然后对每个类型项执行严格的类型校验逻辑,避免PHP的自动类型转换。
实现代码
function test_type(mixed $value, string $type): bool { // 处理可空类型:将 ?Type 转换为 null|Type $type = str_replace('?', 'null|', $type); // 拆分联合类型为单个类型数组 $types = array_map('trim', explode('|', $type)); foreach ($types as $singleType) { if (match ($singleType) { 'null' => $value === null, 'bool' => is_bool($value), 'int' => is_int($value), 'float' => is_float($value), 'string' => is_string($value), 'array' => is_array($value), 'object' => is_object($value) && !is_callable($value), // 排除可调用对象 'callable' => is_callable($value), 'iterable' => is_iterable($value), 'mixed' => true, // mixed 匹配所有类型 default => is_object($value) && $value instanceof $singleType, }) { return true; } } return false; }
关键逻辑说明
类型字符串预处理:
- 把可空类型语法
?Type转换为null|Type,统一用联合类型的方式处理 - 拆分
|分隔的联合类型,得到单个类型的数组
- 把可空类型语法
严格类型校验:
- 基础类型使用PHP的
is_*系列函数(比如is_bool、is_int),这些函数会做严格类型判断,不会触发自动转换 - 类/接口类型使用
instanceof检查,确保值是该类或其子类/实现类的实例 mixed直接返回true,因为它匹配所有类型object类型特意排除了可调用对象(因为is_object($callable)会返回true,但通常我们希望callable和object是区分开的,可根据需求调整)
- 基础类型使用PHP的
测试用例验证
var_dump(test_type(null, "int")); // bool(false) 符合预期 var_dump(test_type(null, "?int")); // bool(true) 符合预期 var_dump(test_type("hello, world", "bool")); // bool(false) 符合预期(严格检查,不会把非空字符串转成true) var_dump(test_type(new DateTime(), "DateTimeInterface")); // bool(true) 符合预期 var_dump(test_type(new DateTime(), "null|int|DateTime|DateTimeImmutable")); // bool(true) 符合预期
扩展说明
如果需要支持更多PHP类型(比如never、void,不过这两个类型通常用于函数返回值,不适合变量检查),或者自定义类型别名,可以在match分支中添加对应的处理逻辑。
内容的提问来源于stack exchange,提问作者Roemer
相关产品推荐
相关产品推荐

