Comment vérifier si la variable est un tableau?… Ou quelque chose de semblable à un tableau

90

Je veux utiliser une foreachboucle avec une variable, mais cette variable peut être de nombreux types différents, NULLpar exemple.

Alors avant de le foreachtester:

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

Mais j'ai réalisé que cela peut aussi être une classe qui implémente l' Iteratorinterface. Peut-être que je suis aveugle mais comment vérifier si la classe implémente l'interface? Y a-t-il quelque chose comme une is_afonction ou un inheritsopérateur? J'ai trouvé class_implements, je peux l'utiliser, mais peut-être qu'il y a quelque chose de plus simple?

Et deuxièmement, plus important, je suppose que cette fonction existe, serait-il suffisant pour vérifier si la variable is_arrayou "implémente l' Iteratorinterface" ou devrais-je tester quelque chose de plus?

Voitcus
la source
2
if ($ var instanceof ArrayIterator)
Alexey
Ouais, j'étais tellement sûr que cela ne fonctionnerait pas qui n'a même pas regardé le manuel ...
Voitcus
2
Possibilité de duplication d' objets itérables et d'indication de type de tableau?
Blackhole le

Réponses:

79

Si vous utilisez à l' foreachintérieur d'une fonction et que vous attendez un tableau ou un objet Traversable , vous pouvez taper hint cette fonction avec:

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

Si vous n'utilisez pas à l' foreachintérieur d'une fonction ou que vous attendez les deux, vous pouvez simplement utiliser cette construction pour vérifier si vous pouvez itérer sur la variable:

if (is_array($a) or ($a instanceof Traversable))
Chaussure
la source
Merci. J'espère que c'est suffisant et qu'il n'y a / il n'y aura pas d'autres constructions de langage qui peuvent être itérées.
Voitcus
J'avais trouvé is_arraycher. Le coût de calcul semble augmenter avec la taille du tableau (ce qui n'a aucun sens car il s'agit simplement de vérifier s'il s'agit d'un tableau). Mais cela m'est arrivé de manière choquante dans une bibliothèque. Voir mon commentaire dans la question liée. Fonctionnera-t-il instanceof Traversableavec des tableaux? Je n'ai pas eu la chance de tester ses performances.
ADTC
@ADTC AFAIR un tableau est une instance de Traversableso yes.
Chaussure du
1
@Shoe Je l'ai essayé ici . Avec $var = array(1,2,3);les résultats sont: is_array($var) = trueet $var instanceof Traversable = false.
ADTC
@ADTC Ouais, je viens de vérifier. Les tableaux ne sont pas implémentés Iteratoret ne fonctionnent donc pas avec Traversable.
Chaussure du
15

foreachpeut gérer des tableaux et des objets. Vous pouvez vérifier cela avec:

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

Vous n'avez pas besoin de vérifier spécifiquement car Traversabled'autres l'ont laissé entendre dans leurs réponses, car tous les objets - comme tous les tableaux - sont traversables en PHP.

Plus techniquement:

foreachfonctionne avec toutes sortes de traversables, c'est-à-dire avec des tableaux, avec des objets simples (où les propriétés accessibles sont parcourues) et des Traversableobjets (ou plutôt des objets qui définissent le get_iteratorgestionnaire interne ).

( source )

Simplement dit dans la programmation PHP courante, chaque fois qu'une variable est

  • un tableau
  • un objet

et n'est pas

  • NUL
  • une ressource
  • un scalaire

vous pouvez l'utiliser foreach.

hakre
la source
5

Vous pouvez vérifier l'instance de Traversableavec une fonction simple. Cela fonctionnerait pour tout cela Iteratorparce queIterator extends Traversable

function canLoop($mixed) {
    return is_array($mixed) || $mixed instanceof Traversable ? true : false;
}
Baba
la source
"? true: false" partie est redondante. instanceof donne déjà une valeur booléenne comme résultat.
Linas le
2
<?php
$var = new ArrayIterator();

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

retourne bool(false)oubool(true)

Alexey
la source
0

Les fonctions

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

Exemple

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

Depuis PHP 7.1, il existe un pseudo-type iterableexactement dans ce but. L'indication de type iterableaccepte n'importe quel tableau ainsi que toute implémentation de l' Traversableinterface. PHP 7.1 a également introduit la fonction is_iterable(). Pour les anciennes versions, consultez les autres réponses ici pour effectuer l'application de type équivalente sans les nouvelles fonctionnalités intégrées.

Fair play: Comme l'a souligné BlackHole, cette question semble être un double des objets Iterable et des indices de type de tableau? et sa réponse va plus loin que la mienne.

faintsignal
la source