Je veux utiliser une boucle foreach
avec une variable, mais cette variable peut être composée de nombreux types différents, par exemple NULL
.
Donc avant foreach
je le teste:
if(is_array($var)){
foreach($var as ...
Mais j’ai réalisé que c’était aussi une classe qui implémentait l’interface Iterator
. Peut-être que je suis aveugle mais comment vérifier si la classe implémente l'interface? Existe-t-il quelque chose comme fonction is_a
ou opérateur inherits
? 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 encore, je suppose que cette fonction existe, suffirait pour vérifier si la variable is_array
ou "implémente l'interface Iterator
" ou si je dois tester quelque chose de plus?
Si vous utilisez foreach
dans une fonction et que vous attendez un tableau ou un objet Traversable , vous pouvez taper le conseil pour cette fonction avec:
function myFunction(array $a)
function myFunction(Traversable)
Si vous n'utilisez pas foreach
dans une fonction ou si vous attendez les deux vous pouvez simplement utiliser cette construction pour vérifier si vous pouvez parcourir la variable:
if (is_array($a) or ($a instanceof Traversable))
foreach
peut 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 rechercher spécifiquement Traversable
comme d'autres l'ont laissé entendre dans leurs réponses, car tous les objets - comme tous les tableaux - peuvent être parcourus en PHP.
Plus techniquement:
foreach
fonctionne avec toutes sortes d'objets traversables, c'est-à-dire avec des tableaux, avec des objets simples (où les propriétés accessibles sont traversées) et des objetsTraversable
(ou plutôt des objets qui définissent le gestionnaire interneget_iterator
).
( la source )
Simplement dit en programmation PHP commune, chaque fois qu'une variable est
et n'est pas
vous pouvez utiliser foreach
dessus.
Vous pouvez vérifier l'instance de Traversable
avec une fonction simple. Cela fonctionnerait pour tout ceci de Iterator
car 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));
renvoie bool(false)
ou 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)
Depuis PHP 7.1, il existe un pseudo-type iterable
exactement à cette fin. L'indication de type iterable
accepte tout tableau ainsi que toute implémentation de l'interface Traversable
. PHP 7.1 a également introduit la fonction is_iterable()
. Pour les versions plus anciennes, voir les autres réponses ici pour réaliser l'application de type équivalent sans les nouvelles fonctionnalités intégrées.
Fair-play: comme BlackHole l’a fait remarquer, cette question semble être un doublon de objets itératifs et indications de type de tableau? et sa réponse va plus en détail que la mienne.