Лучшее, что я мог придумать, это
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 об этом.
Хорошо, так как вы использовали слово «симпатичный» в своем посте, просто быстрое предложение о косметических изменениях для удобочитаемости:
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
», чтобы было ясно, что тестируются как массивы, так и is_array_or_alike
.
Изменение имени параметра / arg: $array
-> $var
потому что « $array
» уже является предпосылкой того, что аргумент имеет массив типов.
Stacking && 'ed условия для удобочитаемости и соответствия стандарту кодирования Drupal: 80-char line max. Поскольку вы являетесь одним из ведущих разработчиков Drupal, я предполагаю, что я предполагаю, что эта функция, возможно, войдет в Drupal, так что, возможно, вы сделали бы это до того, как все это закончите.
Вы правы, что is_object()
. В Java это было бы необходимо, потому что instanceof
выдавал ошибку времени компиляции, если первый операнд не был объектом, но я только что проверил в PHP и нет ошибки, а результат bool (false).
Я предлагаю второе предложение paulmatthews86 о том, что вы предоставляете прецедент. Трудно дать рекомендации, если мы не знаем критериев. Например, чтобы немного охарактеризовать точку зрения парадигмы утки, тесты instanceof
были бы полезны, но не обязательно обязательно или даже полностью. Если вас больше интересует то, что может сделать переменная $var
и как она ведет себя в определенных контекстах, тогда вы можете использовать рефлексию, чтобы проверить наличие методов, которые нужно вызвать на ней позже, или вы можете проверить, что она ведет себя как ожидалось при передаче функций массива. например, «работает» с array_udiff_assoc
, array_chunk
и т. д. Если эти поведения более важны для ваших случаев использования, тогда эти тесты могут заменить instanceof
типа тестирования, хотя, конечно, будет много перекрытий.
Надеюсь это поможет. Заинтересованы в том, что вы, наконец, решите, решите ли вы опубликовать его.
есть интерфейс итератора в php http://php.net/manual/en/class.iterator.php
использование
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
, поэтому вам следует лучше описать, какие функции массива вы ищете здесь.