Il m'est souvent arrivé de gérer des données qui peuvent être soit un tableau, soit une variable null, et d'alimenter foreach
avec ces données.
$values = get_values();
foreach ($values as $value){
...
}
Lorsque vous alimentez une foreach avec des données qui ne sont pas un tableau, vous recevez un avertissement:
Avertissement: Argument non valide fourni pour foreach () dans [...]
En supposant qu'il ne soit pas possible de refactoriser la fonction get_values()
pour toujours renvoyer un tableau (compatibilité ascendante, code source non disponible, quelle que soit la raison), je me demande quel est le moyen le plus propre et le plus efficace d'éviter ces avertissements:
$values
dans un tableau$values
dans un tableauforeach
avec une if
Personnellement, je trouve que c’est le plus propre, mais je ne sais pas si c’est le plus efficace.
if (is_array($values) || is_object($values))
{
foreach ($values as $value)
{
...
}
}
La raison de ma préférence est qu'il n'alloue pas un tableau vide quand vous n'avez rien pour commencer de toute façon.
Celui-ci, ça va? beaucoup plus propre et tout en une seule ligne.
foreach ((array) $items as $item) {
// ...
}
J'utilise habituellement une construction semblable à celle-ci:
/**
* Determine if a variable is iterable. i.e. can be used to loop over.
*
* @return bool
*/
function is_iterable($var)
{
return $var !== null
&& (is_array($var)
|| $var instanceof Traversable
|| $var instanceof Iterator
|| $var instanceof IteratorAggregate
);
}
$values = get_values();
if (is_iterable($values))
{
foreach ($values as $value)
{
// do stuff...
}
}
Notez que cette version particulière n’est pas testée, elle est directement saisie dans SO depuis la mémoire.
Edit: ajouté Traversable check
Merci de ne pas utiliser le casting comme solution, Même si d’autres le suggèrent comme une option valide pour éviter une erreur, cela peut en provoquer une autre.
Soyez conscient: Si vous attendez une forme spécifique de tableau à renvoyer, cela peut échouer. Plus de contrôles sont nécessaires pour cela.
Par exemple. En convertissant un booléen dans un tableau
(array)bool
, NON donnera un tableau vide, mais un tableau avec un élément contenant la valeur booléenne sous la forme int:[0=>0]
ou[0=>1]
.
J'ai écrit un test rapide pour présenter ce problème . (Voici un backup Test au cas où la première URL de test échoue.)
Sont inclus des tests pour: null
, false
, true
, une class
, une array
et undefined
.
Testez toujours votre saisie avant de l’utiliser inforeach. Suggestions:
$array = is_array($var) or is_object($var) ? $var : [] ;
try{}catch(){}
array_key_exists
sur une clé spécifique, ou tester la profondeur d'un tableau (s'il en existe une!) .Essaye ça:
//Force array
$dataArr = is_array($dataArr) ? $dataArr : array($dataArr);
foreach ($dataArr as $val) {
echo $val;
}
;)
$values = get_values();
foreach ((array) $values as $value){
...
}
Le problème est toujours nul et Casting est en fait la solution de nettoyage.
Tout d'abord, chaque variable doit être initialisée. Toujours.
Casting n'est pas une option.
if get_values (); peut retourner différents types de variables, cette valeur doit être vérifiée, bien sûr.
Extension plus concise de @ code de Kris
function secure_iterable($var)
{
return is_iterable($var) ? $var : array();
}
foreach (secure_iterable($values) as $value)
{
//do stuff...
}
spécialement pour l'utilisation de code de gabarit intérieur
<?php foreach (secure_iterable($values) as $value): ?>
...
<?php endforeach; ?>
Si vous utilisez php7 et que vous voulez gérer uniquement les erreurs non définies, c'est le plus propre IMHO
$array = [1,2,3,4];
foreach ( $array ?? [] as $item ) {
echo $item;
}
foreach ($arr ? $arr : [] as $elem) {
// Does something
}
Cela ne vérifie pas s'il s'agit d'un tableau, mais ignore la boucle si la variable est null ou un tableau vide.
Que diriez-vous de cette solution:
$type = gettype($your_iteratable);
$types = array(
'array',
'object'
);
if (in_array($type, $types)) {
// foreach code comes here
}
Je ne sais pas si c'est le cas, mais ce problème semble se produire plusieurs fois lors de la migration de sites WordPress ou de sites dynamiques en général. Si tel est le cas, assurez-vous que l'hébergement vers lequel vous migrez utilise la même version PHP utilisée par votre ancien site.
Si vous ne migrez pas votre site et qu’il s’agit simplement d’un problème qui a été soulevé, essayez de le mettre à jour vers PHP 5. Ce problème est résolu. Cela peut sembler une solution idiote, mais a fait le tour pour moi.
Un cas exceptionnel pour cet avis se produit si vous définissez un tableau sur null dans une boucle foreach
if (is_array($values))
{
foreach ($values as $value)
{
$values = null;//WARNING!!!
}
}
Qu'en est-il de définir un tableau vide comme solution de secours si get_value()
est vide?
Je ne peux pas penser au chemin le plus court.
$values = get_values() ?: [];
foreach ($values as $value){
...
}
Je vais utiliser une combinaison de empty, isset et is_array
$array = ['dog', 'cat', 'lion'];
if(!empty($array) && isset($array) && is_array($array){
//loop
foreach ($array as $values) {
echo $values;
}
}
Il semble aussi y avoir une relation avec l'environnement:
J'ai eu cette erreur "argument invalide fourni foreach ()" seulement dans l'environnement dev, mais pas dans prod (je travaille sur le serveur, pas localhost).
En dépit de l'erreur, var_dump a indiqué que le tableau était bien là (dans les deux cas, app et dev).
Le if (is_array($array))
autour du foreach ($array as $subarray)
a résolu le problème.
Désolé, je ne peux pas expliquer la cause, mais comme cela m'a pris un certain temps pour trouver une solution, j'ai pensé à mieux partager cela en tant qu'observation.
Utilisez la fonction is_array, lorsque vous passerez un tableau dans une boucle.
if (is_array($your_variable)) {
foreach ($your_variable as $item) {
//your code
}
}
Avertissement argument non valide fourni pour foreach () display tweets . Allez à "/ wp-content/plugins/display-tweets-php" . Ensuite, insérez ce code sur la ligne 591, elle fonctionnera parfaitement.
if (is_array($tweets)){
foreach ( $tweets as $Tweet )
{
...
}
}