关于php:为foreach()提供的参数无效

Invalid argument supplied for foreach()

我经常会遇到这样的情况:处理可以是数组或空变量的数据,并向一些foreach提供这些数据。

1
2
3
4
5
$values = get_values();

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

当您向foreach提供非数组的数据时,会收到一条警告:

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

假设不可能重构EDCOX1的1函数,以始终返回数组(向后兼容性,不可用的源代码,不管其他原因),我想知道哪种方法是最干净和最有效的避免这些警告的方法:

  • $values投射到阵列
  • 正在将$values初始化为数组
  • if包住foreach
  • 其他(请建议)


我个人认为这是最干净的-不确定它是否是最有效的,注意!

1
2
3
4
5
6
7
if (is_array($values) || is_object($values))
{
    foreach ($values as $value)
    {
        ...
    }
}

我首选的原因是它不会在您没有任何开始的时候分配空数组。


这个怎么样?批次清洁剂,均为单线。

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


我通常使用类似这样的结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * 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中。

编辑:添加可遍历检查


请不要依赖铸造作为解决方案,尽管其他人建议将此作为防止错误的有效选项,但它可能会导致另一个错误。

注意:如果您希望返回特定形式的数组,这可能会使您失败。为此需要更多的检查。

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].

我写了一个快速测试来提出这个问题。(这里是一个备份测试,以防第一个测试URL失败。)

包括:nullfalsetrueclassarrayundefined的测试。

在foreach中使用输入之前,请始终测试输入。建议:

  • 快速型式检验:$array = is_array($var) or is_object($var) ? $var : [] ;
  • 在使用foreach和指定返回类型之前,在方法中键入提示数组
  • 将前臂包裹在if中
  • 使用try{}catch(){}
  • 在产品发布前设计适当的代码/测试
  • 要根据正确的形式测试数组,您可以在特定的键上使用array_key_exists,或者测试数组的深度(当它是一个时!).
  • 总是以减少重复代码的方式将助手方法提取到全局命名空间中。

  • 试试这个:

    1
    2
    3
    4
    5
    //Force array
    $dataArr = is_array($dataArr) ? $dataArr : array($dataArr);
    foreach ($dataArr as $val) {
      echo $val;
    }

    ;)


    1
    2
    3
    4
    5
    $values = get_values();

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

    问题总是空的,而铸造实际上是清洗解决方案。


    首先,必须初始化每个变量。总是。铸造不是一种选择。如果get_values();可以返回不同的类型变量,那么当然必须检查该值。


    @kris代码的更简洁扩展

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function secure_iterable($var)
    {
        return is_iterable($var) ? $var : array();
    }

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

    特别是用于内部模板代码

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


    1
    2
    3
    foreach ($arr ? $arr : [] as $elem) {
        // Does something
    }

    这不检查它是否是数组,但是如果变量为NULL或空数组,则跳过循环。


    如果您使用PHP7,并且只希望处理未定义的错误,这是最干净的IMHO。

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

    如果在POLACH循环中设置数组为空,则出现此通知的异常情况。

    1
    2
    3
    4
    5
    6
    7
    if (is_array($values))
    {
        foreach ($values as $value)
        {
            $values = null;//WARNING!!!
        }
    }


    我不确定情况是否如此,但在迁移WordPress站点或迁移动态站点时,这个问题似乎会出现很多次。如果是这种情况,请确保要迁移到的宿主使用与旧站点相同的PHP版本。

    如果您没有迁移站点,而这只是一个问题,请尝试更新到php 5。这解决了一些问题。可能看起来是一个愚蠢的解决方案,但却为我做了这件事。


    这个解决方案怎么样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $type = gettype($your_iteratable);
    $types = array(
        'array',
        'object'
    );

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

    如果get_value()为空,那么将空数组定义为回退呢?我想不出最短的路。

    1
    2
    3
    4
    5
    $values = get_values() ?: [];

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

    似乎还与环境有关:

    我只在dev环境中有"invalid argument supplied foreach()"错误,但在prod中没有(我在服务器上工作,而不是本地主机)。

    尽管出现了错误,var_转储还是表明数组在那里很好(在两种情况下都是app和dev)。

    foreach ($array as $subarray)周围的if (is_array($array))解决了这个问题。

    很抱歉,我无法解释原因,但我花了一段时间才想出解决方案,我想最好把这作为一个观察来分享。


    我将使用空、isset和is_数组的组合作为

    1
    2
    3
    4
    5
    6
    7
    8
    $array = ['dog', 'cat',  'lion'];

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


    当您将数组传递给foreach循环时,使用is_array函数。

    1
    2
    3
    4
    5
    if (is_array($your_variable)) {
      foreach ($your_variable as $item) {
       //your code
    }
    }

    警告:为foreach()显示tweets提供的参数无效。转到"/wp content/plugins/display tweets php"。然后在第591行插入此代码,它将运行良好。

    1
    2
    3
    4
    5
    6
    if (is_array($tweets)){  
            foreach ( $tweets as $tweet )
        {
            ...
        }
    }

    我会和安迪做同样的事情,但我会使用"空"功能。

    像这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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
      }
    }