Invalid argument supplied for foreach()

PhpForeach

Php Problem Overview


It often happens to me to handle data that can be either an array or a null variable and to feed some foreach with these data.

$values = get_values();

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

When you feed a foreach with data that are not an array, you get a warning:

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

Assuming it's not possible to refactor the get_values() function to always return an array (backward compatibility, not available source code, whatever other reason), I'm wondering which is the cleanest and most efficient way to avoid these warnings:

  • Casting $values to array
  • Initializing $values to array
  • Wrapping the foreach with an if
  • Other (please suggest)

Php Solutions


Solution 1 - Php

Personally I find this to be the most clean - not sure if it's the most efficient, mind!

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

The reason for my preference is it doesn't allocate an empty array when you've got nothing to begin with anyway.

Solution 2 - Php

How about this one? lot cleaner and all in single line.

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

Solution 3 - Php

I usually use a construct similar to this:

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

Note that this particular version is not tested, its typed directly into SO from memory.

Edit: added Traversable check

Solution 4 - Php

Please do not depend on casting as a solution, even though others are suggesting this as a valid option to prevent an error, it might cause another one.

Be aware: If you expect a specific form of array to be returned, this might fail you. More checks are required for that.

> E.g. casting a boolean to an array (array)bool, will NOT result in an empty array, but an array with one element containing the boolean value as an int: [0=>0] or [0=>1].

I wrote a quick test to present this problem. (Here is a backup Test in case the first test url fails.)

Included are tests for: null, false, true, a class, an array and undefined.


Always test your input before using it in foreach. Suggestions:

  1. Quick type checking: $array = is_array($var) or is_object($var) ? $var : [] ;
  2. Type hinting arrays in methods before using a foreach and specifying return types
  3. Wrapping foreach within if
  4. Using try{}catch(){} blocks
  5. Designing proper code / testing before production releases
  6. To test an array against proper form you could use array_key_exists on a specific key, or test the depth of an array (when it is one !).
  7. Always extract your helper methods into the global namespace in a way to reduce duplicate code

Solution 5 - Php

Try this:

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

;)

Solution 6 - Php

$values = get_values();

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

Problem is always null and Casting is in fact the cleaning solution.

Solution 7 - Php

First of all, every variable must be initialized. Always.
Casting is not an option.
if get_values(); can return different type variable, this value must be checked, of course.

Solution 8 - Php

If you're using php7 and you want to handle only undefined errors this is the cleanest IMHO

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

Solution 9 - Php

foreach ($arr ?: [] as $elem) {
    // Do something
}

This doesen't check if it is an array, but skips the loop if the variable is null or an empty array.

Update from PHP 7.0 you should use the null coalescing operator:

foreach ($arr ?? [] as $elem) {
    // Do something
}

This would solve the warning mentioned in the comment (here a handy table that compares ?: and ?? outputs).

Solution 10 - Php

Warning invalid argument supplied for foreach() display tweets. go to /wp-content/plugins/display-tweets-php. Then insert this code on line number 591, It will run perfectly.

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

Solution 11 - Php

More concise extension of @Kris's code

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

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

especially for using inside template code

<?php foreach (secure_iterable($values) as $value): ?>
    ...
<?php endforeach; ?>

Solution 12 - Php

As of PHP >= 7.1.0 use is_iterable

https://www.php.net/manual/en/function.is-iterable.php

if (is_iterable($value)) {
    foreach ($value as $v) {
        ...
    }
}

Solution 13 - Php

There seems also to be a relation to the environment:

I had that "invalid argument supplied foreach()" error only in the dev environment, but not in prod (I am working on the server, not localhost).

Despite the error a var_dump indicated that the array was well there (in both cases app and dev).

The if (is_array($array)) around the foreach ($array as $subarray) solved the problem.

Sorry, that I cannot explain the cause, but as it took me a while to figure a solution I thought of better sharing this as an observation.

Solution 14 - Php

Exceptional case for this notice occurs if you set array to null inside foreach loop

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

Solution 15 - Php

I'll use a combination of empty, isset and is_array as

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

if (!empty($array) && isset($array) && is_array($array) {
    //loop
    foreach ($array as $values) {
        echo $values; 
    }
}

Solution 16 - Php

I am not sure if this is the case but this problem seems to occur a number of times when migrating wordpress sites or migrating dynamic sites in general. If this is the case make sure the hosting you are migrating to uses the same PHP version your old site uses.

If you are not migrating your site and this is just a problem that has come up try updating to PHP 5. This takes care of some of these problems. Might seem like a silly solution but did the trick for me.

Solution 17 - Php

Use is_array function, when you will pass array to foreach loop.

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

Solution 18 - Php

How about this solution:

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

if (in_array($type, $types)) {
	// foreach code comes here
}

Solution 19 - Php

What about defining an empty array as fallback if get_value() is empty?
I can't think of a shortest way.

$values = get_values() ?: [];

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

Solution 20 - Php

This warning is happening because the array that you want use is empty, you can use of below condition:

if ($your_array != false){
   foreach ($your_array as $value){
         echo $value['your_value_name'];
    }
}

Solution 21 - Php

i would do the same thing as Andy but i'ld use the 'empty' function.

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRoberto AloiView Question on Stackoverflow
Solution 1 - PhpAndy ShellamView Answer on Stackoverflow
Solution 2 - PhpAjith R NairView Answer on Stackoverflow
Solution 3 - PhpKrisView Answer on Stackoverflow
Solution 4 - PhpAARTTView Answer on Stackoverflow
Solution 5 - PhpGigolNftView Answer on Stackoverflow
Solution 6 - PhpboctulusView Answer on Stackoverflow
Solution 7 - PhpYour Common SenseView Answer on Stackoverflow
Solution 8 - PhpEdwin RodríguezView Answer on Stackoverflow
Solution 9 - PhpT30View Answer on Stackoverflow
Solution 10 - PhpSaad KhananiView Answer on Stackoverflow
Solution 11 - PhpHongKilDongView Answer on Stackoverflow
Solution 12 - PhpTechDingoView Answer on Stackoverflow
Solution 13 - PhparaldhView Answer on Stackoverflow
Solution 14 - PhpFarid MovsumovView Answer on Stackoverflow
Solution 15 - PhpRotimiView Answer on Stackoverflow
Solution 16 - PhpErikView Answer on Stackoverflow
Solution 17 - PhpdevView Answer on Stackoverflow
Solution 18 - PhpJulianView Answer on Stackoverflow
Solution 19 - PhpQuentin VeronView Answer on Stackoverflow
Solution 20 - PhpMohamad ShabihiView Answer on Stackoverflow
Solution 21 - Phpas_bold_as_loveView Answer on Stackoverflow