Nieprawidłowy argument podany dla foreach()

Często zdarza mi się obsługiwać dane, które mogą być tablicą lub zmienną null i karmić nimi niektóre foreach.

$values = get_values();

foreach ($values as $value){
  ...
}

Kiedy karmisz foreach danymi, które nie są tablicami, otrzymujesz Ostrzeżenie:

Warning: Invalid argument supplied for foreach () in [...]

Zakładając, że nie jest możliwe refaktorowanie funkcji get_values(), aby zawsze zwracała tablicę (wsteczna kompatybilność, niedostępny kod źródłowy, niezależnie od innych powodów), zastanawiam się który jest najczystszym i najskuteczniejszym sposobem uniknięcia tych ostrzeżeń:

  • Casting $values do tablicy
  • Inicjalizacja $values do tablicy
  • owijanie foreach z if
  • Inne (proszę sugerować)
 248
Author: Geoffrey Hale, 2010-04-13

18 answers

[1]} osobiście uważam, że jest to najbardziej czyste - Nie wiem, czy jest to najbardziej wydajne, umysł!

if (is_array($values) || is_object($values))
{
    foreach ($values as $value)
    {
        ...
    }
}

Powodem moich preferencji jest to, że nie przydziela pustej tablicy, gdy i tak nie masz nic na początek.

 424
Author: Andy Shellam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-27 20:57:40

A może ten? dużo czystsze i wszystko w jednej linii.

foreach ((array) $items as $item) {
 // ...
 }
 76
Author: Ajith R Nair,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-08 17:08:27

Zwykle używam konstrukcji podobnej do tej:

/**
 * 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...
    }
}

Zauważ, że ta konkretna wersja nie jest testowana, jest wpisywana bezpośrednio do SO z pamięci.

Edit: added Traversable check

 37
Author: Kris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-25 13:47:49

Proszę nie zależeć od odlewania jako rozwiązania , nawet jeśli inni sugerują to jako ważną opcję, aby zapobiec błędowi, może to spowodować inny.

Be aware: Jeśli spodziewasz się, że zostanie zwrócona określona forma tablicy, może to cię zawieść. W tym celu wymagana jest większa liczba kontroli.

Np. dodanie elementu logicznego do tablicy (array)bool, spowoduje NIE powstanie pusta tablica, ale tablica z jednym elementem zawierającym wartość logiczną jako int: [0=>0] lub [0=>1].

Napisałem szybki test, aby przedstawić ten problem . (Tutaj jest test kopii zapasowej na wypadek, gdyby pierwszy testowy url nie powiódł się.)

W zestawie znajdują się testy na: null, false, true, a class, an array i undefined.


Zawsze przetestuj swoje wejście przed użyciem go w foreach. Sugestie:

  1. szybkie sprawdzanie typu : $array = is_array($var) or is_object($var) ? $var : [] ;
  2. wpisz tablice hinting w metodach przed użyciem foreach i określanie typów zwracanych
  3. owijanie foreach wewnątrz if
  4. użycie try{}catch(){} bloków
  5. projektowanie właściwego kodu / testowanie przed wydaniami produkcyjnymi
  6. aby przetestować tablicę pod odpowiednim formularzem, możesz użyć array_key_exists na określonym kluczu, lub przetestować głębokość tablicy (gdy jest ona jedna !).
  7. zawsze wyodrębniaj metody pomocnicze do globalnej przestrzeni nazw, aby zmniejszyć zduplikowany kod
 13
Author: AARTT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:54

Spróbuj tego:

//Force array
$dataArr = is_array($dataArr) ? $dataArr : array($dataArr);
foreach ($dataArr as $val) {
  echo $val;
}

;)

 6
Author: GigolNet Guigolachvili,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-30 12:52:18
$values = get_values();

foreach ((array) $values as $value){
  ...
}

Problem jest zawsze zerowy, a odlewanie jest w rzeczywistości rozwiązaniem czyszczącym.

 4
Author: boctulus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-02 16:59:44

Po pierwsze, każda zmienna musi być zainicjalizowana. Zawsze.
Casting nie wchodzi w grę.
jeśli get_values (); może zwrócić zmienną innego typu, to ta wartość musi być oczywiście sprawdzona.

 3
Author: Your Common Sense,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-13 14:11:25

Bardziej zwięzłe rozszerzenie @ Kod Krisa

function secure_iterable($var)
{
    return is_iterable($var) ? $var : array();
}

foreach (secure_iterable($values) as $value)
{
     //do stuff...
}

Szczególnie do użycia wewnątrz kodu szablonu

<?php foreach (secure_iterable($values) as $value): ?>
    ...
<?php endforeach; ?>
 3
Author: HongKilDong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:24
foreach ($arr ? $arr : [] as $elem) {
    // Does something 
}

Nie sprawdza, czy jest to tablica, ale pomija pętlę, jeśli zmienna ma wartość null lub pustą tablicę.

 2
Author: T30,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-14 02:41:50

Jeśli używasz php7 i chcesz obsłużyć tylko niezdefiniowane błędy to jest to najczystsze IMHO

$array = [1,2,3,4];
foreach ( $array ?? [] as $item ) {
  echo $item;
}
 2
Author: Edwin Rodríguez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-09 15:27:03

Nie jestem pewien, czy tak jest, ale ten problem wydaje się występować wiele razy podczas migracji witryn wordpress lub migracji dynamicznych witryn w ogóle. W takim przypadku upewnij się, że hosting, na który migrujesz, używa tej samej wersji PHP, której używa Twoja stara witryna.

Jeśli nie migrujesz witryny i jest to tylko problem, który pojawił się spróbuj zaktualizować do PHP 5. To rozwiązuje niektóre z tych problemów. Może wydawać się głupie rozwiązanie, ale zrobił sztuczkę dla mnie.

 1
Author: Erik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-12 13:16:28

Wyjątkowy przypadek dla tego powiadomienia występuje, jeśli ustawisz tablicę na null wewnątrz pętli foreach

if (is_array($values))
{
    foreach ($values as $value)
    {
        $values = null;//WARNING!!!
    }
}
 1
Author: Farid Movsumov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-18 09:24:52

Co powiesz na to rozwiązanie:

$type = gettype($your_iteratable);
$types = array(
    'array',
    'object'
);

if (in_array($type, $types)) {
    // foreach code comes here
}
 1
Author: Julian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-01 12:04:11

Wydaje się również, że istnieje związek ze środowiskiem:

Miałem ten błąd "invalid argument supplied foreach ()" tylko w środowisku dev, ale nie w prod( pracuję na serwerze, nie na localhost).

Pomimo błędu var_dump wskazywał, że tablica jest tam dobrze (w obu przypadkach app i dev).

if (is_array($array)) wokół foreach ($array as $subarray) rozwiązał problem.

Przepraszam, że nie mogę wyjaśnić przyczyny, ale ponieważ zajęło mi trochę czasu, aby znaleźć rozwiązanie, pomyślałem o lepiej podzielić się tym jako obserwacją.

 0
Author: araldh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-22 11:36:42

Użyję kombinacji empty, isset i is_array jako

$array = ['dog', 'cat',  'lion'];

if(!empty($array)  && isset($array)  && is_array($array){
//loop
foreach ($array as $values) {
echo $values; 
}
}
 0
Author: Akintunde-Rotimi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-06 17:10:50

Użyj funkcji is_array, gdy przekażesz tablicę do pętli foreach.

if (is_array($your_variable)) {
  foreach ($your_variable as $item) {
   //your code
}
}
 0
Author: Super Model,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-21 21:46:43

Warning invalid argument supplied for foreach () display tweets. przejdź do "/ wp-content / plugins / display-tweets-php". Następnie wstaw ten kod na linii numer 591, będzie działać idealnie.

if (is_array($tweets)){  
        foreach ( $tweets as $tweet ) 
    {
        ...
    }
}
 0
Author: Saad Khanani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-03 02:59:48

Zrobiłbym to samo co Andy, ale użyłbym funkcji 'empty'.

Like so:

if(empty($yourArray))
{echo"<p>There's nothing in the array.....</p>";}
else
{
foreach ($yourArray as $current_array_item)
  {
    //do something with the current array item here
  } 
}
 -3
Author: as_bold_as_love,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-30 17:40:04