it-swarm.com.ru

Как проверить, является ли переменная массивом? ... или чем-то похожим на массив

Я хочу использовать цикл foreach с переменной, но эта переменная может быть разных типов, например NULL.

Поэтому перед foreach я проверяю это:

if(is_array($var)){
  foreach($var as ...

Но я понял, что это также может быть класс, реализующий интерфейс Iterator. Может быть, я слепой, но как проверить, реализует ли класс интерфейс? Есть ли что-то вроде функции is_a или оператора inherits? Я нашел class_implements, я могу использовать его, но, может быть, есть что-то попроще?

И, во-вторых, что более важно, я полагаю, что эта функция существует, будет достаточно, чтобы проверить, является ли переменная is_array или «реализует интерфейс Iterator», или мне следует проверить что-то большее?

78
Voitcus

Если вы используете foreach внутри функции и ожидаете массив или объект Traversable , вы можете напечатать подсказку этой функции с помощью: 

function myFunction(array $a)
function myFunction(Traversable)

Если вы не используете foreach внутри функции или ожидаете обоих вы можете просто использовать эту конструкцию , чтобы проверить, можете ли вы перебрать переменную:

if (is_array($a) or ($a instanceof Traversable))
66
Shoe

foreach может обрабатывать массивы и объекты. Вы можете проверить это с помощью:

$can_foreach = is_array($var) || is_object($var);
if ($can_foreach) {
    foreach ($var as ...
}

Вам не нужно специально проверять наличие Traversable , как другие намекали на это в своих ответах, потому что все объекты - как и все массивы - доступны в PHP.

Более технически:

foreach работает со всеми видами обходных путей, то есть с массивами, с простыми объектами (где просматриваются доступные свойства) и объектами Traversable (или, скорее, объектами, которые определяют внутренний обработчик get_iterator). 

( источник )

Проще говоря, в обычном PHP программировании, когда переменная 

  • массив
  • объект

и не

  • НОЛЬ
  • ресурс
  • скаляр

вы можете использовать foreach на нем.

12
hakre

Вы можете проверить экземпляр Traversable с помощью простой функции. Это будет работать для всего этого Iterator, потому что Iterator extends Traversable

function canLoop($mixed) {
    return is_array($mixed) || $mixed instanceof Traversable ? true : false;
}
5
Baba
<?php
$var = new ArrayIterator();

var_dump(is_array($var), ($var instanceof ArrayIterator));

возвращает bool(false) или bool(true)

2
Alexey

Функции

<?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)
0
Eduardo Cuomo

Поскольку PHP 7.1 существует псевдотип iterable именно для этой цели. Подсказка типа iterable принимает любой массив, а также любую реализацию интерфейса Traversable. PHP 7.1 также представила функцию is_iterable() . Для более старых версий см. Другие ответы здесь для выполнения эквивалентного принудительного исполнения без новых встроенных функций.

Честная игра: как указывал BlackHole, этот вопрос кажется дубликатом повторяющихся объектов и подсказок типа массива? и его или ее ответ более подробно, чем мой.

0
faintsignal