2014-10-28 63 views
3

我来过的情况下,foreach中的值通过引用传递以修改元素,然后在代码的稍后阶段,相同的数组再循环做一些计算,但这次元素是按值传递的。问题在于PHP在第一个foreach中保留了对数组中最后一个元素的引用,然后将在下一个foreach开始时覆盖该元素,如果本地变量具有相同的名称。替代foreach通过引用

示例代码:

<?php 
$a = array("a" => "foo"); 
$b = array("b" => "bar"); 

$x = array($a, $b); 

foreach ($x as &$y) {} 

print_r($x); 

foreach ($x as $y) {} 

print_r($x); 
?> 

这将产生

 
Array 
(
    [0] => Array 
     (
      [a] => foo 
     ) 

    [1] => Array 
     (
      [b] => bar 
     ) 

) 
Array 
(
    [0] => Array 
     (
      [a] => foo 
     ) 

    [1] => Array 
     (
      [a] => foo 
     ) 

) 

这荒谬PHP手册

警告一个$值的参考和最后阵列被表示元素在foreach循环之后仍然存在。建议通过unset()销毁它。

事实上,使用unset($y)将解决此问题。但是这是非常脆弱的,你不能依赖于编程人员总是记住取消设置一个范围不明显的变量。所以我的问题是:是否有任何foreach的好替代方案 - 通过引用来消除以后需要取消设置变量?

+1

你给不给上为什么它是必要的任何线索的例子在这里使用参考。 – raina77ow 2014-10-28 11:03:45

+0

'$ a = array(“a”=>“foo”); $ b = array(“b”=>“bar”); $ x = array($ a,$ b);'你确定你不想使用'array_merge();'? – 2014-10-28 11:04:36

+1

@ raina77ow这真的很重要吗?代码只是指出了缺陷。所有你需要知道的是变量需要修改。 – jurgemaister 2014-10-28 11:05:55

回答

3

您可以使用array_walk()

array_walk($x, function(&$y) { 
    /* ... */ 
}); 

这使得基准$y本地的,这样不落的是自动处理的回调函数的范围。

+0

谢谢。这是我最终使用的。另外值得注意的是,对于外部变量在匿名函数中可用,必须使用['use()'](http://php.net/manual/en/functions.anonymous.php)。 – jurgemaister 2014-10-28 11:27:00

2

您可以使用关联(索引)的foreach:

foreach ($x as $index=>$y) 
{ 
if ($y=='remove') {unset($x[$index]);} 
} 

这样你就可以修改原始数组元素的轻松......

+0

@ php_coder_3809625不,他要求提供“替代foreach pass by reference”。这是一个有效的答案。 – 2014-10-28 11:14:54