【问题标题】:How to check for arrayness in PHP?如何检查 PHP 中的数组?
【发布时间】:2012-09-03 00:17:31
【问题描述】:

我能想到的最好的是

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 的测试似乎没有必要。我已经在 instanceof PHP 手册中添加了一节。

【问题讨论】:

  • 你的方法对我来说似乎没问题。 Is there something more pretty? 怀疑。
  • 您是否尝试确定该变量是否可以像数组一样访问(例如$array['test']),或者您是否可以像数组一样对其进行迭代?
  • 你能给出这个功能的用例吗?当然,您想知道它是否是其中任何一种情况。不像数组。

标签: php arrayaccess


【解决方案1】:

php中有迭代器接口http://php.net/manual/en/class.iterator.php

使用

function isIter($abc) {
    return (is_array($abc) || $abc instanceof Traversable);
}

【讨论】:

  • 这与提出的问题完全无关。
  • arrayness 带有 iterable.is'nt it.
【解决方案2】:

好吧,既然您在帖子中确实使用了“漂亮”这个词,只是为了提高可读性而对外观进行快速建议:

function is_array_or_alike($var) {
  return is_array($var) ||
           ($var instanceof ArrayAccess  &&
            $var instanceof Traversable  &&
            $var instanceof Serializable &&
            $var instanceof Countable);
}

变化说明:

  1. 函数名称更改:“is_array_alike”->“is_array_or_alike”只是为了明确表示正在测试数组和相似性。

  2. 参数/参数名称更改:$array -> $var 因为“$array”已经在某种程度上预设了参数是数组类型。

  3. 为了可读性和符合 Drupal 编码标准的堆叠 &&'ed 条件:最多 80 个字符行。由于您是 Drupal 核心维护者之一,我想我假设此功能可能会进入 Drupal,因此您可能会在提交之前完成此操作。

  4. is_object() 是不必要的,这是正确的。在 Java 中这是必要的,因为如果第一个操作数不是对象,instanceof 会抛出编译时错误,但我刚才在 PHP 中检查并没有错误,只是 bool(false) 的结果。

我同意 paulmatthews86 的建议,即您提供一个用例。如果我们不知道标准,就很难提供建议。例如,从鸭子类型范式的角度借用一点,instanceof 测试会很有用,但不一定是强制性的,甚至不一定是完整的。如果您对 $var 可以做什么以及它在某些上下文中的行为方式更感兴趣,那么您可以使用反射来检查是否存在需要稍后对其调用的方法,或者您可以测试它的行为方式传递给数组函数时预期。例如它是否与array_udiff_assocarray_chunk 等一起“工作”。如果这些行为对您的用例更重要,那么这些测试可能会取代instanceof 类型测试,尽管当然会有很多重叠。

希望这会有所帮助。如果您决定发布它,有兴趣看看您最终决定的内容。

【讨论】:

  • 是的,这旨在成为 Drupal 核心中 Twig 和渲染系统之间(临时?)BC 层的一部分。为了使渲染工作,我们需要渲染数组成为 ArrayAccess 以便更改正确传播。 OTOH 系统中有许多 is_array 检查现在失败了。
  • 酷。希望到目前为止,向 Twig 的过渡进展顺利。我对最新的 Twig 源进行了快速 grep,并查看了对 ArrayAccess、Traversable 和 Countable 的 instanceof 检查,但没有找到任何“instanceof Serializable”测试。您是否出于特定原因包括 Serializable?
【解决方案3】:

尽管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,因此您应该在此处更好地概述您要查找的数组功能。

【讨论】:

  • 测试一下,instanceof 在非对象上使用时不会致命。你在那个问题上实际上是错误的。我完全不知道你在说什么 Serializable 这里。如果您的意思是 __sleep()__wakeup 不受支持,Serializable 允许使用 unserialize 方法获取序列化数据,因此它可以做的不仅仅是 __wakeup
【解决方案4】:

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;
    }

}

【讨论】:

  • 这些$array instanceof ArrayAccess && $array instanceof Traversable && $array instanceof Serializable怎么样。
  • @chx 我不完全确定为什么 PHP RFC 只指定了单实例检查,但我认为他们有他们的原因,虽然我也想知道
猜你喜欢
  • 2021-02-05
  • 1970-01-01
  • 1970-01-01
  • 2021-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多