有没有办法测试
$var
是否满足除此之外的字符串中定义的类型:
function test_type(mixed $value, string $type): bool
{
try {
eval('(fn('.$type.' $a)=>true)($value);');
return true;
}
catch (Throwable $e) {
return false;
}
}
test_type(null, "int") ; // returns false.
test_type(null, "?int") ; // return true.
test_type("hello, world", "bool") ; // returns true. I want it to return false
test_type(new DateTime, "DateTimeInterface") ; // return true.
test_type(new DateTime, "null|int|DateTime|DateTimeImmutable") ; // return true
这种方法有两个不需要进一步解释的主要问题:
test_type("hello, world", "bool")
=> true
)有没有办法避免这些问题呢?我用谷歌搜索了很多,但到目前为止还没有找到任何东西。
@Jaquarh 让我相信,通过真正的测试,这比我想象的要容易得多。他的版本是这个解决方案的基础。谢谢,贾夸!
我没有使用资源进行测试,因为我不存储它们,如果有人想使用资源添加答案,请这样做。
<?php
function test_type(mixed $value, string $type): bool
{ $foundType = strtolower(gettype($value));
$foundType = ['boolean'=>'bool', 'integer'=>'int', 'double'=>'float'][$foundType] ?? $foundType;
$type = str_replace('?', 'null|', $type);
$typesUnion = explode('|', $type);
$typesIntersection = explode('&', $type);
if ( count($typesIntersection)>1) {
if ( ! is_object($value) ) return false;
foreach($typesIntersection as $subtype) {
if ( ! ($value instanceof $subtype)) return false;
}
return true;
}
foreach($typesUnion as $subtype) {
if ( is_null($value) && strtolower($subtype)=='null' ) return true;
if ( $value === false && strtolower($subtype)=='false' ) return true;
if ( $value === true && strtolower($subtype)=='true' ) return true;
if ( is_callable($value) && strtolower($subtype)=='callable' ) return true;
if ( is_object($value) ) { if ( $value instanceof $subtype) return true; }
elseif ( $foundType == strtolower($subtype) ) return true;
}
return false;
}
enum hello { case world; case earth; case mars; };
echo (int) test_type(false, "int|bool"); // 1
echo (int) test_type(null, "?int"); // 1
echo (int) test_type(null, "int|string"); // 0
echo (int) test_type("hello, world", "?bool"); // 0
echo (int) test_type(hello::world, "hello"); // 1
echo (int) test_type(false, "DateTimeInterface|false"); // 1
echo (int) test_type(true, "DateTimeInterface|false"); // 0
echo (int) test_type(new DateTime, "DateTimeInterface|false"); // 1
echo (int) test_type(new DateTime, "null|int|DateTime|DateTimeImmutable"); // 1
echo (int) test_type(new DateTime, "DateTime&DateTimeInterface"); // 1
echo (int) test_type([1,2,3,4], "Array"); // 1
echo (int) test_type(fn($x) => $x+1, "callable"); // 1