Я хочу использовать foreach
цикл с переменной, но, например, эта переменная может быть разных типов NULL
.
Итак, прежде чем foreach
я его протестирую:
if(is_array($var)){
foreach($var as ...
Но я понял, что это также может быть класс, реализующий Iterator
интерфейс. Может, я слепой, но как проверить, реализует ли класс интерфейс? Есть что-то вроде is_a
функции или inherits
оператора? Нашел class_implements
, могу пользоваться, а может есть что попроще?
И во-вторых, что более важно, я полагаю, что эта функция существует, было бы достаточно, чтобы проверить, является ли переменная is_array
или «реализует Iterator
интерфейс», или я должен проверить что-то еще?
Ответы:
Если вы используете
foreach
внутри функции и ожидаете массив или объект Traversable, вы можете ввести подсказку для этой функции с помощью:function myFunction(array $a) function myFunction(Traversable)
Если вы не используете
foreach
внутри функции или ожидаете и того, и другого, вы можете просто использовать эту конструкцию, чтобы проверить, можете ли вы перебирать переменную:if (is_array($a) or ($a instanceof Traversable))
источник
is_array
что это дорого. Вычислительные затраты, казалось, увеличивались с увеличением размера массива (что не имеет смысла, поскольку он просто проверяет, является ли он массивом). Но со мной случилось ужасное в библиотеке. См. Мой комментарий в связанном вопросе. Будетinstanceof Traversable
работать с массивами? У меня не было возможности проверить его работоспособность.Traversable
так что да.$var = array(1,2,3);
результатами:is_array($var) = true
и$var instanceof Traversable = false
.Iterator
и поэтому не работают сTraversable
.foreach
может обрабатывать массивы и объекты. Вы можете проверить это с помощью:$can_foreach = is_array($var) || is_object($var); if ($can_foreach) { foreach ($var as ... }
Вам не нужно специально проверять это,
Traversable
поскольку другие намекали на это в своих ответах, потому что все объекты - как и все массивы - можно перемещать в PHP.Более технически:
( источник )
Проще говоря в обычном программировании PHP, когда переменная
и не
вы можете использовать
foreach
на нем.источник
Вы можете проверить экземпляр
Traversable
с помощью простой функции. Это сработает для всего этого,Iterator
потому чтоIterator extends Traversable
function canLoop($mixed) { return is_array($mixed) || $mixed instanceof Traversable ? true : false; }
источник
<?php $var = new ArrayIterator(); var_dump(is_array($var), ($var instanceof ArrayIterator));
возвращается
bool(false)
илиbool(true)
источник
Функции
<?php /** * Is Array? * @param mixed $x * @return bool */ function isArray($x) : bool { return !isAssociative($x); } /** * Is Associative Array? * @param mixed $x * @return bool */ function isAssociative($x) : bool { if (!is_array($array)) { return false; } $i = count($array); while ($i > 0) { if (!isset($array[--$i])) { return true; } } return false; }
пример
<?php $arr = [ 'foo', 'bar' ]; $obj = [ 'foo' => 'bar' ]; var_dump(isAssociative($arr)); # bool(false) var_dump(isAssociative($obj)); # bool(true) var_dump(isArray($obj)); # bool(false) var_dump(isArray($arr)); # bool(true)
источник
Начиная с PHP 7.1 существует псевдотип
iterable
именно для этой цели. Подсказка типаiterable
принимает любой массив, а также любую реализациюTraversable
интерфейса. PHP 7.1 также представил эту функциюis_iterable()
. Для более старых версий см. Другие ответы здесь, чтобы выполнить принудительное применение эквивалентного типа без новых встроенных функций.Честная игра: как указал BlackHole, этот вопрос, похоже, является дубликатом Iterable объектов и подсказок типа массива? и его или ее ответ более подробен, чем мой.
источник