2016-09-16 49 views
1

到目前爲止,我們一直在使用PHP 5.5,並且所有代碼都看起來流暢。由於將其升級到7,大部分foreach()似乎都有不一致的行爲。在PHP 7中處理foreach by-ref

對於例如:考慮下面的代碼段:

$array = array('a', 'b', 'c'); 
self::testForeach($array); 
. 
. 
. 
// $array is passed by reference 
public static function testForeach(&$array) { 

    foreach ($array as $key => $val) { 
    //produces a, b as an output in PHP 5 
    //produces a, b, c as an output in PHP 7 
    var_dump($val); 

    if ($val == 'b') { 
     //remove 'c' from the array 
     unset($array[2]); 
    } 
    } 
} 

行爲在PHP 5.5:

$陣列通過引用傳遞到testForeach()函數。因此,從循環中的$ array中刪除「c」將直接修改原始數組。因此,迭代的值將是a,b,而不是c,因爲它會從中間的數組中移除。

行爲在PHP 7:

$陣列通過引用傳遞到testForeach()函數。當$ array循環遍歷foreach()時,會複製一個副本,說$循環中正在迭代的$ arrayCopy(根據doc)。因此,從$ array中刪除「c」值將不起作用,並會循環$ arrayCopy中包含的所有值。 因此輸出 - a,b,c。

將foreach更改爲pass-by-ref對我來說不是一個解決方案,因爲我的項目中有太多的foreach,我無法grep和修改它們中的每一個。

是否有任何其他處理完成這種行爲在最新版本。任何可以突出顯示它們的工具/解析器?

任何提示/想法?

謝謝!

+0

在迭代它時不要修改數組。它在許多語言中有未定義的行爲。 PHP在兩個版本上都是正確的。迭代輸入數組並將項目複製到新數組中或在需要時跳過它們。 – axiac

+5

你有兩個選擇:1)不要升級到7並修復你的代碼2)升級到7並修復你的代碼 – PeeHaa

+0

@axiac如果我這樣做,有n個地方需要這種處理。我能不能有一個地方(庫等)限制foreach()不改變複製變量的地址(正在迭代),以便它在循環中立即被修改? – jitendrapurohit

回答

2

除了它似乎很奇怪,修改,同時遍歷數組,在PHP 7,你可以強制在迭代變量的引用:

$array = array('a', 'b', 'c'); 
foreach ($array as $key => &$val) { 
    var_dump($val); 
    if ($val == 'b') { 
    //remove 'c' from the array 
    unset($array[2]); 
    } 
} 

將返回兩個PHP 5和7:

string(1) "a" 
string(1) "b" 

請參閱3v4l.org的操作。

2

只有如果循環陣列通過引用:的foreach($數組作爲$密鑰=> & $ VAL){

AFAIK然後NO拷貝正在取得。 http://php.net/manual/en/control-structures.foreach.php

被警告:在這種情況下,$ VAL仍然是一個指向數組的最後一個元素,一個最好的做法是取消它。

foreach ($array as $key => &$val) { 


<?php 

$array = array(); 
testForeach($array); 

// $array is passed by reference 
function testForeach(&$array) 
{ 
    $array = array('a', 'b', 'c'); 
    foreach ($array as $key => &$val) { 
     //produces a, b as an output in PHP 5 
     //produces a, b, c as an output in PHP 7 
     var_dump($val); 

     if ($val == 'b') { 
      //remove 'c' from the array 
      unset($array[ 2 ]); 
     } 
    } 
    unset($val); 
}