遍历多维数组

4
我正在尝试获取物品ID,然后获取该物品ID内的所有选项名称/选项值。因此,最终结果应该是:ID:123,颜色:蓝色,大小:6。ID:456,颜色:黄色,大小:8。然而,我只得到了正确的物品ID,但选项名称/选项值并没有正确传递,要么为空,要么只有一个随机字母。
这是我的代码,它不能正常工作:
foreach($itemlist as $item)
{
   echo $item['ID'];

   foreach($item as $option)
   { 
       echo $option['option_name'];
       echo $option['option_value'];
   }
 }

如果想要查看$itemlist的样子,可以参考以下内容:

Array
(
    [1] => Array
        (
            [ID] => 123
            [QTY] => 1
            [MODEL] => sdfsd
            [IMAGE] => 
            [1] => Array
                (
                    [option_name] => 颜色
                    [option_value] => 蓝色
                    [option_price] => 0.0000
                )
[2] => Array ( [option_name] => 尺寸 [option_value] => 6 [option_price] => 0.0000 )
[price] => 0 )
[2] => Array ( [ID] => 456 [QTY] => 0 [MODEL] => gsdfgd [IMAGE] => [1] => Array ( [option_name] => 颜色 [option_value] => 黄色 [option_price] => 0.0000 )
[2] => Array ( [option_name] => 尺寸 [option_value] => 8 [option_price] => 0.0000 )
[price] => 0 )
)
3个回答

10

基本上,您正在循环遍历$item数组,它看起来像这样:

array(7) {
   ["ID"]=>string(6) "123"
   ["QTY"]=>string(1) "1"
   ["MODEL"]=>string(11) "sdfsd"
   ["IMAGE"]=>string(0) ""
   [1]=>
       array(3) {
           ["option_name"]=>string(8) "Color"
           ["option_value"]=>string(10) "Blue"
           ["option_price"]=>string(6) "0.0000"
      }

因此,在第一次迭代中,$option 将是 123,尝试访问 '123'['option_name'] 会发出警告。你实际想要做的是这样的:

foreach($item[1] as $key => $option)
{
    if ($key !== 'option_price')
    {
        echo $option;
    }
}
//or:
echo $item['ID'], $item[1]['option_name'], $item['option_value'];

这就是为什么你的代码没有产生期望的结果。
如果子数组并不总是以 1 作为键,请尝试:

foreach($item as $foo)
{
    if (is_array($foo))
    {
        echo $foo['option_name'], $foo['option_value'];
        break;//we have what we needed, no need to continue looping.
    }
}

这是获取所有选项的最通用方法(无论有多少选项)

foreach($itemlist as $item)
{
    echo $item['ID'];
    foreach($item as $sub)
    {
        if (is_array($sub))
        {
            foreach($sub as $key => $option)
            {
                echo $key, ' => ', $option;
            }
        }
    }
}

但是由于你的选项数组看起来都具有数字索引,因此你也可以尝试这样做:

foreach($itemlist as $item)
{
    echo $item['ID'];
    for ($i=1;isset($item[$i]);$i++)
    {
        foreach($item[$i] as $key => $option)
        {
            echo $key, ' => ', $option;
        }
    }
}

你可以用以下代码替换for循环:

$i=0;//or $i = 1
while(isset($item[++$i]))// or isset($item[$i++]), if $i is 1

我需要所有的选项,但是我不确定会有多少个。可能有两个,可能有四个等等。有没有办法循环遍历所有选项?你的代码可以工作,但只返回第一个选项集,我需要所有的选项,在我的例子中是1和2,颜色和尺寸。 - user1155594
@user1155594:增加了一个完整的例子,展示如何解决这个问题。如果你确定子数组中的选项值始终会被分配给键 1,那么你可以省略foreach($item as $sub),直接使用foreach($item[1] as $key => $option),不需要任何break;语句,这样就不必嵌套三个循环... - Elias Van Ootegem
你的第三个代码示例是有效的,但是由于使用了break语句,它只会给出颜色,而不是颜色和尺寸。如果我去掉break语句,它会给我整个数组中每个id的颜色/尺寸,而不仅仅是id为123的。 - user1155594
听起来你好像把 break 放错位置了。最后一段代码包含了三个嵌套循环。break 应该放在第三个循环的外面,在 if (is_array()) 分支内部,而这个分支又在第二个循环的内部。 - Elias Van Ootegem
@user1155594:哦,现在我明白了...抱歉:去掉break。确实有两个子数组($item[1]$item[2]),每个都描述了一个特定的选项。如果这些数组始终是数字,您可以使用for循环,甚至是while(isset($item[$i++]))。我将编辑您的问题,以更好地格式化所讨论的数组。 - Elias Van Ootegem

1
这是因为你的数组包含了这些键可能存在的可能性,而不是保证存在。有几种不同的方法可以采取,比如检查键是否为数字(似乎只有数字键才有正确的键数组设置)。但是由于我不知道你的数据集,可能最好的通用方法是在尝试使用它们之前检查键是否已设置。所以...
foreach($itemlist as $item) {

 foreach($item as $key => $value) {

      if(is_array($value) && array_key_exists('option_name', $value) {

           //--- Your option array is available in here via $value['option_x']

      }

 }

}

1
你可以尝试类似以下的代码:

array_walk_recursive($itemlist, function($value, $key) {
    if (in_array($key, array("ID", "option_name", "option_value")))
        echo "$key: $value\n";
});

请注意,这需要 PHP >= 5.3,并在每次迭代中构建数组 [ID,option_name,option_value],由于 lambda 函数是对象,所以速度不是非常快,上次我检查过。 - Elias Van Ootegem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接