2013-11-22 4 views
1

У меня есть массив, мне нужно скопировать первый элемент в массиве и изменить его.PHP ссылочный массив вместо копирования

Это то, что я делаю:

echo $QuantityDiscounts[0]['price'] . '<br>'; 
echo $QuantityDiscounts[0]['from_quantity'] . '<br>'; 

$firstItem     = $QuantityDiscounts[0]; 
$firstItem['from_quantity'] = 999; 
$firstItem['price']   = 999; 

echo $QuantityDiscounts[0]['price'] . '<br>'; 
echo $QuantityDiscounts[0]['from_quantity'] . '<br>'; 

Это выход это дает мне:

4.870000 
10 
4.870000 
999 

При изменении значения скопированного массива он меняющегося исходный массив. То, что делает это еще более странным, это то, что это происходит только для элемента from_quantity. Как видите, элемент «цена» остается неизменным.

Я не могу понять, почему это происходит, поскольку вы можете видеть, что я не использую ссылки. Есть ли объяснение этому поведению, которое мне не хватает?

Некоторые подробнее:

Если я первый скопировать «from_quantity» в исходном массиве, так что он использует другой ключ такое поведение уходит.

$QuantityDiscounts[0]['test'] = $QuantityDiscounts[0]['from_quantity']; 

echo $QuantityDiscounts[0]['price'] . '<br>'; 
echo $QuantityDiscounts[0]['from_quantity'] . '<br>'; 
echo $QuantityDiscounts[0]['test'] . '<br>'; 

$firstItem = $QuantityDiscounts[0]; 
$firstItem['from_quantity'] = 999; 
$firstItem['test']   = 999; 
$firstItem['price']   = 999; 

echo $QuantityDiscounts[0]['price'] . '<br>'; 
echo $QuantityDiscounts[0]['from_quantity'] . '<br>'; 
echo $QuantityDiscounts[0]['test'] . '<br>'; 

Выходы:

4.870000 
10 
10 
4.870000 
999 
10 

** UPDATE ** - Спасибо за вашу помощь до сих пор

Вот функция, которая генерирует массив. Я вижу, что там используется ссылка, которая должна вызывать проблемы. Означает ли это, что я не могу копировать и изменять «from_quantity» без изменения оригинала?

protected function formatQuantityDiscounts($specific_prices, $price, $tax_rate, $ecotax_amount) 
{ 
    foreach ($specific_prices as $key => &$row) 
    { 
     $row['quantity'] = &$row['from_quantity']; 
     if ($row['price'] >= 0) // The price may be directly set 
     { 
      $cur_price = (Product::$_taxCalculationMethod == PS_TAX_EXC ? $row['price'] : $row['price'] * (1 + $tax_rate/100)) + (float)$ecotax_amount; 
      if ($row['reduction_type'] == 'amount') 
       $cur_price -= (Product::$_taxCalculationMethod == PS_TAX_INC ? $row['reduction'] : $row['reduction']/(1 + $tax_rate/100)); 
      else 
       $cur_price *= 1 - $row['reduction']; 
      $row['real_value'] = $price - $cur_price; 
     } 
     else 
     { 
      if ($row['reduction_type'] == 'amount') 
       $row['real_value'] = Product::$_taxCalculationMethod == PS_TAX_INC ? $row['reduction'] : $row['reduction']/(1 + $tax_rate/100); 
      else 
       $row['real_value'] = $row['reduction'] * 100; 
     } 
     $row['nextQuantity'] = (isset($specific_prices[$key + 1]) ? (int)$specific_prices[$key + 1]['from_quantity'] : -1); 
    } 
    return $specific_prices; 
} 
+2

Я только что сделал phpfiddle и попробовал, и это не ссылка для меня - http: // phpfiddle.org/main/code/b8g-03e Вы должны делать что-то еще. –

+1

какая версия php? пожалуйста, укажите полный код, который мы можем скопировать/вставить, чтобы проверить – Asenar

+0

Возможно, OP делает что-то вроде этого: http://phpfiddle.org/main/code/naj-0gu – Kaii

ответ

1

Если $QuantityDiscounts[0]['from_quantity'] уже IS ссылку, вы не должны ссылаться на него еще раз - он будет оставаться ссылки и ссылки будут скопированы на уступки, вместо фактического значения.

Этот код показывает, что я имею в виду:

$foo = 10; 

$QuantityDiscounts[0]['price'] = 4.870000; 
$QuantityDiscounts[0]['from_quantity'] =& $foo; 
$firstItem     = $QuantityDiscounts[0]; 
$firstItem['from_quantity'] = 999; 
$firstItem['price']   = 999; 

echo $QuantityDiscounts[0]['price'] . '<br>'; 
echo $QuantityDiscounts[0]['from_quantity'] . '<br>'; 

Выходы:

4.87 
999 (instead of the initial value 10 !) 

Чтобы получить реальную COPY вашего массива (и все его элементы), необходимо вручную разыменовать ребенка элементы. К сожалению, PHP не имеет встроенного метода для этого.

См. this QA on StackOverflow о том, как разделить элементы массива при копировании.

+0

Это, вероятно, не связано, но я напоминаю, что нужно использовать 'AddRange' в C#, потому что при копировании списка будет изменен оригинал. Возможно, в PHP есть аналогичная функция. –

+0

Спасибо, это как раз моя проблема. Я не понял, что массив уже содержит ссылку и что ссылка останется даже после копирования массива. – jd182

0

Наиболее правдоподобной причиной вашей проблемы является то, что ваша переменная указывает на объект, а не на массив. Приобретение объектов как массивов очень просто через интерфейс ArrayAccess, и поскольку он указывает на объект (и объекты всегда передаются как ссылки), значение изменяется. Clone перед внесением любых изменений.

Другой, вероятно, причина в том, что вы явно используете ссылки. В этом случае вы должны найти, где проблема, и исправить ее самостоятельно, так как у нас нет доступа к вашему приложению.

Смежные вопросы