php foreach 数组和对象并重新定义它们的值

php foreach with arrays and objects and redefining their value

我正在尝试通过数组中的对象数组进行 foreach。我没有收到错误,但它似乎没有存储我试图建立的新值。我在这里找到了很多与这个问题密切相关的答案,但我不明白,我希望有人能更清楚地说明这一点。

本质上,这会将 kg 转换为 lbs。

    $kg_conv = 2.20462262;
    $weights = array($data['progress']->weight, $data['progress']->squats,
    $data['progress']->bench, $data['progress']->deadlift); 

    foreach ($weights as $value) {
        $value = $value * $kg_conv;
    }

数组中的值没有变化。根据我的阅读,我应该使用 $data['progress'] 并对其进行迭代,但我不明白如何只引用其中的一些元素而不是所有元素。我还尝试通过将对象存储在 $progress 而不是 $data['progress'] 中来减少一些冗余,但仍然没有成功。

更新:以下方法无效

1

    foreach ($weights as &$value) {
        $value = $value * $kg_conv;
    }

2

    foreach ($weights as $key => &$value) {
        $value = $value * $kg_conv;
    }

3

    foreach ($weights as $key => $value) {
        $weights[$key] = $value * $kg_conv;
    }

为了能够在循环内直接修改数组元素,在$value之前加上&。在这种情况下,该值将通过引用分配。在您的示例代码中应如下所示:

foreach ($weights as &$value) {
    $value = $value * $kg_conv;
}

但是只有在可以引用迭代数组(即如果它是一个变量)时才可以引用 $value。 您还可以使用索引直接访问数组值。这段代码也工作得很好:

foreach ($weights as $key => $value) {
    $weights[$key] = $value * $kg_conv;
}

更多信息:http://php.net/manual/en/control-structures.foreach.php

$value 仅包含数组元素的副本。

您可以像这样通过 reference 传递对象:

foreach ($weights as &$value) {
    $value = $value * $kg_conv;
}

注意 $value 之前的 &

在 Whosebug 上查看 References Explained in the php documentation or What's the difference between passing by reference vs. passing by value?

编辑 2:

但请注意,这只会更改 $weights 数组中的值,不会更改存储在 $data['progress'] 中的对象,因为它的值已被 复制进入 $weights。为此,您可以通过以下方式在构造数据数组时引用对象属性(这一步在我的测试用例代码中被注释掉了):

$weights = array(&$data['progress']->weight, &$data['progress']->squats,
    &$data['progress']->bench, &$data['progress']->deadlift);

再次注意 & 运算符。

但是 的解决方案可能更符合您的要求。

编辑:

在您发表评论后,我创建了以下测试用例,效果很好:

<?php
class foo {
    public $test = 5;
    public $test2 = 10;
}

$obj = new foo();
$obj2 = new foo();
$obj2->test = 3; 

$data =  array('progress' => $obj, 'p2' => $obj2);

// this copies the values into the new array
$weights = array($data['progress']->test, $data['progress']->test2);

// this makes a reference to the values, the original object will be modified
// $weights = array(&$data['progress']->test, &$data['progress']->test2);

var_dump($weights);

$kg_conv = 2.20462262;

foreach ($weights as &$value) {
    $value = $value * $kg_conv;
}
var_dump($weights);

结果是:

array(2) {
  [0]=>
  int(5)
  [1]=>
  int(10)
}
array(2) {
  [0]=>
  float(11.0231131)
  [1]=>
  &float(22.0462262)
}

PHP foreach manual 非常详细地描述了这个主题。为了总结为什么您没有看到预期的结果,这里有一个简短的解释。

假设您有一个数组 $arr = ['one', 'two', 'three']。当您在此数组上执行 foreach 循环时,PHP 将在内部创建您的数组的 副本

foreach ($arr as $key => $value) {
    $value = 'something'; // You are modifying the copy, not the original!
}

要修改原始数组,您有两种选择。

使用$key变量访问原始数组中给定键处的元素:

$arr[$key] = 'something'; // Will change the original array

告诉PHP对$value中的原始元素使用reference:

foreach ($arr as $key => &$value) {
    $value = 'something'; // $value is reference, it WILL change items in $arr
}

两种方法都有效;但是,第二个内存效率更高,因为 PHP 在循环遍历数组时不必复制数组 - 它只是引用原始数组。

它不起作用,因为你不修改数据数组,你只修改从这个数组制作的副本,这是内存中的另一个数组

解决方案:(也适用于对象的字段)

$kg_conv = 2.20462262;
$weights = ['weight', 'squats','bench', 'deadlift']; 

foreach ($data['progress'] as $key=>&$value) {
  if ( in_array($key,$weights)
    $value = $value * $kg_conv;
}