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

$values = get_values();

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

当你给foreach提供不是数组的数据时,你会得到一个警告:

警告:在[…]中为foreach()提供的参数无效

假设不可能重构get_values()函数以总是返回一个数组(向后兼容,没有可用的源代码,无论其他原因),我想知道哪种是避免这些警告的最干净和最有效的方法:

将$值转换为数组 初始化数组的$values 用if包foreach 其他(请建议)


当前回答

为foreach()提供的显示tweet的无效参数警告。 进入/wp-content/plugins/display-tweets-php。 然后把这段代码插入591行,它就能正常运行了。

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

其他回答

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

$values = get_values() ?: [];

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

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

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

例如,将一个布尔值强制转换为数组(array)bool,将不会得到一个空数组,而是得到一个包含布尔值为int类型的元素的数组:[0=>0]或[0=>1]。

我编写了一个快速测试来呈现这个问题。 (这里有一个备份测试,以防第一个测试url失败。)

包括测试:null, false, true,类,数组和未定义。


在foreach中使用输入之前一定要测试它。建议:

Quick type checking: $array = is_array($var) or is_object($var) ? $var : [] ; Type hinting arrays in methods before using a foreach and specifying return types Wrapping foreach within if Using try{}catch(){} blocks Designing proper code / testing before production releases 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 !). Always extract your helper methods into the global namespace in a way to reduce duplicate code

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

/**
 * 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中。

编辑:增加可遍历检查

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

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

从PHP >= 7.1.0开始使用is_iterable

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

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