我能想到的最好的是
function is_array_alike($array) {
return is_array($array) || (is_object($array) && $array instanceof ArrayAccess && $array instanceof Traversable && $array instanceof Serializable && $array instanceof Countable);
}
啊。还有更漂亮的吗?
编辑:is_object
的测试似乎没有必要。我在PHP手册的instanceof中添加了一节关于这一点的内容。
好吧,因为你在帖子中确实使用了"漂亮"一词,所以为了可读性,只需要简单地修改一下外观:
function is_array_or_alike($var) {
return is_array($var) ||
($var instanceof ArrayAccess &&
$var instanceof Traversable &&
$var instanceof Serializable &&
$var instanceof Countable);
}
更改说明:
函数名称更改:"
is_array_alike
"->"is_array_or_alike
"只是为了清楚地表明数组和相似性都在测试中。参数/参数名称更改:
$array
->$var
,因为"$array
"已经在某种程度上预设了参数的类型为数组。堆叠&;'可读性和符合Drupal编码标准的条件:最多80个字符行。由于您是Drupal核心维护人员之一,我想我假设这个函数可能会进入Drupal,所以您可能在提交之前就已经完成了。
您认为
is_object()
是不必要的,这是正确的。在Java中,这是必要的,因为如果第一个操作数不是对象,instanceof
会引发编译时错误,但我刚才在PHP中检查了一下,没有错误,只是bool(false)的结果。
我赞同paulmatthews86关于你提供一个用例的建议。如果我们不知道标准,就很难提供建议。例如,借用鸭子类型范式的观点,instanceof
测试是有用的,但不一定是强制性的,甚至不一定是完整的。如果您更感兴趣的是$var
可以做什么以及它在某些上下文中的行为,那么您可以使用反射来检查是否存在稍后需要在其上调用的方法,或者您可以测试它在传递给数组函数时的行为是否如预期。例如,它与array_udiff_assoc
、array_chunk
等一起"工作"吗?如果这些行为对您的用例更重要,那么这些测试可能会取代instanceof
类型的测试,当然会有很多重叠。
希望这能有所帮助。有兴趣看看如果你决定发布它,你最终会做出什么决定。
使用
function isIter($abc) {
return (is_array($abc) || $abc instanceof Traversable);
}
即使ArrayObject
实现了Serializable
,但对象必须实现为类似数组的假设是错误的。
情况恰恰相反。您可以使用Serializable
来有效地防止对象的序列化。所以我会考虑将其从接口检查中删除。
此外,如果您在没有对象的情况下使用instanceof
,您将看到一个(致命)错误。我建议您将对"类数组"对象的检查委托给叶函数,并使您对输入类型不太严格的函数使用它:
function is_array_or_object_arraylike($var) {
return is_array($var)
|| (is_object($var) && is_object_arraylike($var))
;
}
function is_object_arraylike($obj) {
return $obj instanceof ArrayAccess
&& $obj instanceof Traversable
&& $obj instanceof Countable
;
}
还要记住,即使对象是类似数组的,它也不能与大多数数组函数一起使用。它也不能很好地与foreach
配合使用,因此您应该更好地概述您在这里寻找的阵列功能。
这里有一个新的PHP 7.3规范,它实现了is_countable
函数https://wiki.php.net/rfc/is-countable
基于规范&对于以前的PHP版本,您可以使用此
if (is_array($foo) || $foo instanceof Countable) {
return count($foo);
}
或者你也可以实现一种类似的polyfill
if (!function_exists('is_countable')) {
function is_countable($c) {
return is_array($c) || $c instanceof Countable;
}
}