Недопустимый аргумент, указанный для foreach()
Со мной часто случается обрабатывать данные, которые могут быть либо массивом, либо нулевой переменной, и снабжать некоторые foreach
этими данными.
$values = get_values();
foreach ($values as $value){
...
}
Когда вы вводите в foreach данные, которые не являются массивом, вы получаете предупреждение:
Предупреждение: Неверный аргумент, указанный для foreach() в [...]
Предполагая, что невозможно выполнить рефакторинг функции get_values()
, чтобы всегда возвращать массив (обратная совместимость, недоступный исходный код, по любой другой причине), я интересно, какой самый чистый и эффективный способ избежать этих предупреждений:
- Приведение
$values
к массиву - Инициализация
$values
в массив - Обертывание
foreach
с помощьюif
- Другое (пожалуйста, предложите)
18 answers
Лично я нахожу это наиболее чистым - не уверен, что это наиболее эффективно, имейте в виду!
if (is_array($values) || is_object($values))
{
foreach ($values as $value)
{
...
}
}
Причина моего предпочтения в том, что он не выделяет пустой массив, когда вам все равно не с чего начинать.
Как насчет этого? намного чище и все в одну линию.
foreach ((array) $items as $item) {
// ...
}
Я обычно использую конструкцию, подобную этой:
/**
* 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...
}
}
Обратите внимание, что эта конкретная версия не тестируется, она вводится непосредственно в SO из памяти.
Редактировать: добавлен Проходимый проверка
Пожалуйста, не полагайтесь на приведение в качестве решения, даже если другие предлагают это как допустимый вариант для предотвращения ошибки, это может привести к другой ошибке.
Имейте в виду: Если вы ожидаете, что будет возвращена определенная форма массива, это может вас подвести. Для этого требуется больше проверок.
Например, приведение логического значения к массиву
(array)bool
приведет НЕ к пустому массиву, а к массиву с одним элементом, содержащим логическое значение в виде значение int:[0=>0]
или[0=>1]
.
Я написал краткий тест, чтобы представить эту проблему. (Вот тест резервного копирования на случай сбоя первого тестового URL.)
Включены тесты для: null
, false
, true
, a class
, an array
и undefined
.
Всегда проверяйте свой ввод, прежде чем использовать его в foreach. Предложения:
-
Быстрая проверка типа:
$array = is_array($var) or is_object($var) ? $var : [] ;
- Введите массивы намеков в методах перед использованием foreach и указание типов возвращаемых данных
- Обертывание для каждого в пределах if
- Использование
try{}catch(){}
блоков - Разработка правильного кода/тестирование перед выпуском продукции
- Чтобы проверить массив на соответствие правильной форме, вы можете использовать
array_key_exists
для определенного ключа, или проверить глубину массива (когда он один !). - Всегда извлекайте свои вспомогательные методы в глобальное пространство имен, чтобы уменьшить количество повторяющихся кодов
Попробуйте это:
//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
}
Это не проверяет, является ли это массивом, но пропускает цикл, если переменная равна нулю или является пустым массивом.
Если вы используете 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!!!
}
}
Как насчет этого решения:
$type = gettype($your_iteratable);
$types = array(
'array',
'object'
);
if (in_array($type, $types)) {
// foreach code comes here
}
По-видимому, также существует связь с окружающей средой:
У меня была ошибка "неверный аргумент, предоставленный foreach()" только в среде разработки, но не в prod (я работаю на сервере, а не на локальном хосте).
Несмотря на ошибку, var_dump указывал, что массив был в порядке (в обоих случаях приложение и разработчик).
if (is_array($array))
вокруг foreach ($array as $subarray)
решена проблема.
Извините, что я не могу объяснить причину, но так как мне потребовалось некоторое время, чтобы найти решение, я подумал о том, чтобы лучше поделиться этим в качестве наблюдения.
Я буду использовать комбинацию empty, 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
}
}
Предупреждение недопустимый аргумент, предоставленный для отображения твитов foreach(). перейдите в раздел "/wp-контент/плагины/отображение-твиты-php". Затем вставьте этот код в строку номер 591, он будет работать идеально.
if (is_array($tweets)){
foreach ( $tweets as $tweet )
{
...
}
}
Я бы сделал то же самое, что и Энди, но я бы использовал функцию "пусто".
Вот так:
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
}
}