2010-08-02 2 views
3

exemple:Quelle est la meilleure façon de vérifier qu'un élément est prêt à être utilisé dans une boucle foreach() en php?

foreach($boxes as $box) { 
    echo "$box \n"; 
} 

Utilisé pour être assez facile, je pourrais simplement envelopper le foreach autour d'un chèque comme:

if(is_array($boxes) && count($boxes) > 0) { 
    //foreach loop here 
} 

Sans avoir à se soucier d'un avertissement se levée si pour une raison quelconque mauvaise entrée a été passé au tableau $ boxes.

Lorsque des itérateurs ont été ajoutés au mélange, cela ne fonctionne plus, car les objets Iteratable ne sont pas des tableaux. Donc, j'ai quelques solutions, mais je me demande s'il existe une «meilleure pratique» pour cela.

// 1: 
if($boxes instanceof Traversable && count($boxes) > 0) { 
    //foreach loop here 
} 

// 2: 
if($boxes && count($boxes) > 0) { 
    //foreach loops here 
} 

Il y en a d'autres, mais ceux-ci semblent les plus évidents. N'importe qui a des suggestions. Les documents PHP semblent être silencieux.

Répondre

4

Vous ne devriez pas avoir le count($array) > 0 part, parce que a) foreach fonctionne très bien avec des tableaux vides, b) Les objets peuvent être Traversable encore ne pas être Countable et c) la valeur retournée par count() peut même (pour les objets) soit déconnecté de la nombre d'éléments que la traversée va générer.

Et n ° 1, il est différent de # 2; puisque $boxes instanceOf Traversable n'est pas la même chose que $boxes. Notez également que les tableaux internes n'implémentent pas Traversable.

Je voudrais aller avec

if (is_array($boxes) || $boxes instanceof Traversable) { 
    foreach (...) 
} 

Cela ne garantit toujours pas que la traversal sera couronnée de succès; l'itération peut lancer une exception à tout moment. En particulier, pour certaines classes, il peut être illogique de les parcourir plus d'une fois.

+0

Ah, ouais ... J'aime. On dirait que je compliquais un peu les choses. Je vais faire quelques tests avec cette configuration et voir comment cela fonctionne. –

2

Je pense généralement dans ces cas, vous savez sans doute que la variable va être itérable si elle est non nulle ou faux, etc., donc je serais heureux de le faire:

if ($boxes) { 
    foreach ($boxes as $box) {} 
} 

Peut-être que est naïve si

+0

Cela devrait être bon, mais notez que si $ boxes était défini comme un nombre ou une chaîne, il serait toujours évalué à true. – NullUserException

+0

Cette solution ne semble pas assez complète. Tout objet qui n'est pas null/false sera toujours évalué par foreach, même s'il ne s'agit pas d'un tableau ou d'un itérable. OP pourrait ne pas avoir le luxe de faire ces hypothèses. –

+0

En général, oui. Mais je cherche spécifiquement à éliminer les Notices dans notre code où, pour une raison quelconque, $ boxes a quelque chose dedans, mais le foreach soulève un avis.Il y a probablement d'autres problèmes qui doivent être résolus dans la chaîne, mais pour l'instant, nettoyer les journaux suffisamment pour trouver ces erreurs est ma priorité. Merci! –

0

une possibilité en fonction de votre version php est un casting:

<?php 

$a = array('foo', array('bar')); 

foreach ($a as $thing) 
    foreach ((array) $thing as $item) // <-- here 
    echo "$item\n"; 
?> 
0

Ce test donnera vrai pour les deux tableaux et des objets ressemblant à un tableau

if (is_array($obj) || $obj instanceof Traversable) { 
    foreach ($obj as $item) { /* foreach loop is safe here */ 
    } 
} 
0

En vous pouvez itérer PHP5 sur tout tableau ou un objet si ..

if (is_array($my_var) || is_object($my_var)) { 
    // Do some foreachin' 
} 
Questions connexes