Недопустимый аргумент для foreach ()

Мне часто приходится обрабатывать данные, которые могут быть либо массивом, либо нулевой переменной, и передавать некоторые данные для этих данных.

 $values = get_values(); foreach ($values as $value){ ... } 

Когда вы кормите foreach данными, которые не являются массивом, вы получаете предупреждение:

Предупреждение: неверный аргумент, предоставленный foreach () в […]

Предполагая, что невозможно get_values() функцию get_values() чтобы всегда возвращать массив (обратная совместимость, недоступный исходный код, по какой-либо другой причине), мне интересно, какой из них самый чистый и эффективный способ избежать этих предупреждений:

  • Вычисление $values массива
  • Инициализация $values для массива
  • Обертка foreach с if
  • Другое (пожалуйста, предлагайте)

Лично я считаю, что это самый чистый – не уверен, что это самый эффективный, ум!

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

Причина моего предпочтения заключается в том, что он не выделяет пустой массив, когда вам вообще нечего начинать.

Как насчет этого? много чистых и все в одной линии.

 foreach ((array) $items as $item) { // ... } 

Обычно я использую конструкцию, подобную этой:

 /** * Determine if a variable is iterable. ie 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... } } 

Обратите внимание, что эта конкретная версия не протестирована, ее набрали непосредственно в SO из памяти.

Изменить: добавлена ​​проверка на перемещение

Пожалуйста, не зависеть от кастинга как решения , хотя другие предлагают это как допустимый вариант для предотвращения ошибки, это может привести к другому.

Имейте в виду : если вы ожидаете вернуть определенную форму массива, это может не сработать. Для этого требуются дополнительные проверки.

Например, приведение boolean в массив (array)bool не приведет к пусту массива, а массив с одним элементом, содержащим логическое значение как int: [0=>0] или [0=>1] .

Я написал быстрый тест, чтобы представить эту проблему . (Вот тест резервного копирования, если первый тестовый URL-адрес не работает.)

Включены тесты для: null , false , true , class , array и undefined .


Всегда проверяйте свой ввод перед его использованием в foreach. Предложения:

  1. Быстрая проверка типов : $array = is_array($var) or is_object($var) ? $var : [] ; $array = is_array($var) or is_object($var) ? $var : [] ;
  2. Тип подсказки массивов в методах перед использованием foreach и указания типов возврата
  3. Обертка foreach внутри if
  4. Использование блоков try{}catch(){}
  5. Разработка надлежащего кода / тестирования перед выпуском продукции
  6. Чтобы проверить массив на правильную форму, вы можете использовать array_key_exists на определенном ключе или проверить глубину массива (когда он один!) .
  7. Всегда извлекайте свои вспомогательные методы в глобальное пространство имен, чтобы уменьшить дубликат кода

Попробуй это:

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

😉

 $values = get_values(); foreach ((array) $values as $value){ ... } 

Проблема всегда равна нулю, а литье – это чистое решение.

Прежде всего, каждая переменная должна быть инициализирована. Всегда.
Кастинг не вариант.
если get_values ​​(); может возвращать переменную типа, это значение должно быть проверено, конечно.

Более сжатое расширение кода @ Kris

 function secure_iterable($var) { return is_iterable($var) ? $var : array(); } foreach (secure_iterable($values) as $value) { //do stuff... } 

особенно для использования кода внутри шаблона

 <?php foreach (secure_iterable($values) as $value): ?> ... <?php endforeach; ?> 
 foreach ($arr ? $arr : [] as $elem) { // Does something } 

Это не проверяет, является ли это массивом, но пропускает цикл, если переменная имеет значение null или пустой массив.

Если вы используете php7 и хотите обрабатывать только неопределенные ошибки, это самый чистый IMHO

 $array = [1,2,3,4]; foreach ( $array ?? [] as $item ) { echo $item; } 

Я не уверен, что это так, но эта проблема возникает несколько раз при переносе сайтов WordPress или миграции динамических сайтов в целом. Если это так, убедитесь, что хостинг, на котором выполняется миграция, использует ту же версию PHP, которую использует ваш старый сайт.

Если вы не переносите свой сайт, и это просто проблема, возникшая при попытке обновления до PHP 5. Это позаботится о некоторых из этих проблем. Может показаться глупым решением, но сделал трюк для меня.

Исключительный случай для этого уведомления возникает, если вы устанавливаете массив в null внутри цикла foreach

 if (is_array($values)) { foreach ($values as $value) { $values = null;//WARNING!!! } } 

Похоже, что есть отношение к окружающей среде:

У меня был «недопустимый аргумент, предоставленный foreach ()», ошибка только в среде dev, но не в prod (я работаю на сервере, а не на localhost).

Несмотря на ошибку, var_dump указал, что массив там хорошо (в обоих случаях – приложение и dev).

Значение if (is_array($array)) вокруг foreach ($array as $subarray) решило проблему.

Извините, что я не могу объяснить причину, но поскольку мне потребовалось некоторое время, чтобы понять решение, я подумал о том, чтобы лучше поделиться этим как наблюдением.

предупреждение неверный аргумент, предоставленный для твитов foreach (). идти к . / WP-содержание / плагины / дисплей-твиты-PHP

вставьте это устройство в линию номер 591. Он будет работать отлично

 if (is_array($tweets)){ foreach ( $tweets as $tweet ) { ... } } 

Я буду использовать комбинацию пустых, isset и is_array как

 $array = ['dog', 'cat', 'lion']; if(!empty($array) && isset($array) && is_array($array){ //loop foreach ($array as $values) { echo $values; } } 

Используйте функцию is_array, когда вы передадите массив в цикл foreach.

 if (is_array($your_variable)) { foreach ($your_variable as $item) { //your code } } 

Как насчет этого решения:

 $type = gettype($your_iteratable); $types = array( 'array', 'object' ); if (in_array($type, $types)) { // foreach code comes here } 

я бы сделал то же самое, что и Энди, но использовал «пустую» функцию.

вот так:

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