【问题标题】:PHP foreach and referencesPHP foreach 和参考
【发布时间】:2010-11-24 14:11:37
【问题描述】:

我试图在 PHP 的嵌套 foreach 循环中使用指针来修改值。 但是,以下行似乎不起作用:

// Assign a the attribs value to the array
$link_row['value'] = $args[ $u_value ];

变量 $args[ $u_value ];已填充并且可以毫无问题地输出,但是当我将它添加到 $link_row 引用时,它似乎没有设置..

  foreach ($unique_links as $link_id => &$link_attr)
  {
     foreach($link_attr as &$link_row)
     {
        foreach($link_row as $u_attr => &$u_value)
        {
           if ($u_attr == 'attribute_name') 
           {               

              // Assign a the attribs value to the array
              $link_row['value'] = $args[ $u_value ];

              // If one of the values for the unique key is blank,  
              // we can remove the entire 
              // set from being checked
              if ( !isset($args[ $u_value ]) ) 
              {
                 unset($unique_links[$link_id] );
              }
           }
        }
     }
  }

【问题讨论】:

  • 也许还没有给出可接受的答案?

标签: php arrays reference foreach


【解决方案1】:

foreach 中使用变量后,您必须始终取消设置变量。即使您有两个foreach(..) 语句一个接一个。即使您在另一个foreach(..) 中有一个foreach(..)没有例外!

foreach ($unique_links as $link_id => &$link_attr)
{
 foreach($link_attr as &$link_row)
 {
    foreach($link_row as $u_attr => &$u_value)
    {
       if ($u_attr == 'attribute_name') 
       {               

          // Assign a the attribs value to the array
          $link_row['value'] = $args[ $u_value ];

          // If one of the values for the unique key is blank,  
          // we can remove the entire 
          // set from being checked
          if ( !isset($args[ $u_value ]) ) 
          {
             unset($unique_links[$link_id] );
          }
       }
    }
    unset($u_value);  // <- this is important
 }
 unset($link_row);  // <- so is this
}
unset($lnk_attr);  // <- and so is this, even if you reached the end of your program or the end of a function or a method and even if your foreach is so deeply indented or on such a long line that you're not sure what code might follow it, because another developer (maybe even you) will come back and read the code and he might not see that you used a reference in a foreach

这是不久前搞砸了一个大项目的另一段有趣的代码:

foreach ($data as $id => &$line) {
    echo "This is line {$id}: '{$line}'\n";
    $line .= "\n";
}

echo "And here is the output, one line of data per line of screen:\n";

foreach ($data as $id => &$line) {
    echo $line;
}

事实上有人在第一个foreach(..) 之后没有unset($line) 确实弄乱了数组中的数据,因为&amp;$line 是一个引用,而第二个foreach(..) 在循环时为其分配了不同的值通过数据,它一直覆盖最后一行数据。

【讨论】:

    【解决方案2】:

    由于我看不到您的数组,我不知道哪些是整数,哪些是关联的,等等。

    据我所知,没有理由引用 $u_value。它不会造成任何伤害,但无论哪种方式都没有区别。

    更重要的是,任何时候你的第二个 if 条件为真,在你在线到达它之前你都会遇到错误

     $link_row['value'] = $args[ $u_value ];
    

    也许你想使用

    $link_row['value'] = isset($args[$u_value]) ? $args[ $u_value ] : "NOT PRESENT";
    

    你提到的那行似乎工作得很好。

    我的代码:

        $args = array(100,200,300,400,500);
        $unique_links = array (array(   'a' => array('attribute_name' => 1,'x' => 2, 'y' => 3, 'z' =>4), 
                                        'b' => array('attribute_name' => 3,'x' => 2, 'y' => 3, 'z' =>4),
                                        'c' => array('attribute_name' => 0,'x' => 2, 'y' => 3, 'z' =>4),
                                        'd' => array('attribute_name' => 7,'x' => 2, 'y' => 3, 'z' =>4),
                                        'e' => array('attribute_name' => 1,'x' => 2, 'y' => 3, 'z' =>4)
    
                                        ));                                 
        echo_r($unique_links);
        foreach ($unique_links as $link_id => &$link_attr)
        {
            foreach($link_attr as &$link_row)
            {
                foreach($link_row as $u_attr => $u_value)
                {
                    echo "&nbsp&nbsp&nbsp&nbsp $u_attr is $u_value <br />";
                    if ($u_attr == 'attribute_name')
                    {
    
                        // Assign a the attribs value to the array
                        $link_row['value'] = isset($args[$u_value]) ? $args[ $u_value ] : "NOT PRESENT";
    
                        // If one of the values for the unique key is blank, we can remove the entire
                        // set from being checked
                        if ( !isset($args[ $u_value ]) )
                        {
                            //echo "want to kill: $link_id <br />";
                            //unset($unique_links[$link_id] );
                        }
                    }
                }
                echo "<br />";
            }
        }
        echo_r($unique_links);
    

    我的输出:

    Array
    (
    [0] => Array
        (
            [a] => Array
                (
                    [attribute_name] => 1
                    [x] => 2
                    [y] => 3
                    [z] => 4
                )
    
            [b] => Array
                (
                    [attribute_name] => 3
                    [x] => 2
                    [y] => 3
                    [z] => 4
                )
    
            [c] => Array
                (
                    [attribute_name] => 0
                    [x] => 2
                    [y] => 3
                    [z] => 4
                )
    
            [d] => Array
                (
                    [attribute_name] => 7
                    [x] => 2
                    [y] => 3
                    [z] => 4
                )
    
            [e] => Array
                (
                    [attribute_name] => 1
                    [x] => 2
                    [y] => 3
                    [z] => 4
                )
    
        )
    
    )
    
     attribute_name is 1
     x is 2
     y is 3
     z is 4
     value is 200
    
     attribute_name is 3
     x is 2
     y is 3
     z is 4
     value is 400
    
     attribute_name is 0
     x is 2
     y is 3
     z is 4
     value is 100
    
     attribute_name is 7
     x is 2
     y is 3
     z is 4
     value is NOT PRESENT
    
     attribute_name is 1
     x is 2
     y is 3
     z is 4
     value is 200
    
    Array
    (
    [0] => Array
        (
            [a] => Array
                (
                    [attribute_name] => 1
                    [x] => 2
                    [y] => 3
                    [z] => 4
                    [value] => 200
                )
    
            [b] => Array
                (
                    [attribute_name] => 3
                    [x] => 2
                    [y] => 3
                    [z] => 4
                    [value] => 400
                )
    
            [c] => Array
                (
                    [attribute_name] => 0
                    [x] => 2
                    [y] => 3
                    [z] => 4
                    [value] => 100
                )
    
            [d] => Array
                (
                    [attribute_name] => 7
                    [x] => 2
                    [y] => 3
                    [z] => 4
                    [value] => NOT PRESENT
                )
    
            [e] => Array
                (
                    [attribute_name] => 1
                    [x] => 2
                    [y] => 3
                    [z] => 4
                    [value] => 200
                )
    
        )
    
    )
    

    我注释掉 unnset 因为它似乎会杀死整个数组,而不仅仅是你想要的部分。我猜这是由于杀死了您当前正在迭代的部分而导致的一些奇怪行为。

    【讨论】:

    • 感谢您花时间查看...似乎问题在于未设置本身对其进行了更多研究。未设置似乎扼杀了我实际添加的价值..
    • 为了澄清(不一定是 OP;对于读者也是如此): PHP 在通过 foreach 作为参考时不会复制值。因此,对 &$value 所做的任何更改都会影响原始数组的值。通过使用“unset($unique_links[$link_id]);”,发起 foreach 语句的键/值对被破坏。因此,所有引用的值都指向不再存在的数据。
    【解决方案3】:

    我认为您可能会覆盖循环中的值。要对此进行测试,您可以执行以下操作

    $link_row['value'] = $args[ $u_value ];
    

    改成

    $link_row[] = $args[ $u_value ];
    

    然后在循环之外添加这个

    echo "Link Row Value(s):<pre>".print_r($link_row,true)."</pre><br />\n";
    

    这将显示所有正在转换/设置为 $link_row['value'] 的值,如果您看到多个索引,则这些值将被覆盖

    【讨论】:

    • 我认为这不是问题。为了使 $link_row['value'] 被写入两次,在同一个数组中必须有两个名为 'attribute_name' 的键
    猜你喜欢
    • 2012-07-24
    • 2012-03-01
    • 2022-08-13
    • 1970-01-01
    • 2011-08-01
    • 1970-01-01
    • 2016-06-25
    • 2014-06-30
    • 1970-01-01
    相关资源
    最近更新 更多