0

I'm trying to add a field in an array and return it, but according to var_dump, no changes are made to the array. The instruction in the if-block is executed and the data seems correct.

function addLength($toAdd, $added){
   $result = $toAdd;
    foreach ($result as $row) {
        foreach ($added as $key => $value) {
            if($key == $row['id'] ){
                $row['length'] = $value;   
            }
        } 
    }
    var_dump($result);
    return $result;
}
Leonard
  • 3,012
  • 2
  • 31
  • 52
af_inb
  • 103
  • 1
  • 6
  • 1
    It will be really helpful if you show your current results and the desirable results! – Antonios Tsimourtos Mar 22 '17 at 16:28
  • The array shold have the field 'length' added but it doesn't nothing has changed. – af_inb Mar 22 '17 at 16:29
  • 1
    `foreach` creates copies of the data. If you change `$row` (the copy), the original array (`$result`) won't be affected. Try changing the foreach to use references instead: `foreach ($result as &$row)` (the added & sign). – M. Eriksson Mar 22 '17 at 16:31
  • your final $result no update and your $row will be update in this code. – Shafiqul Islam Mar 22 '17 at 16:33
  • if($key == $row['id'] ){ $result['length'] = $value; } it will be effect your result – Shafiqul Islam Mar 22 '17 at 16:33
  • Duplicate of http://stackoverflow.com/questions/9920619/changing-value-inside-foreach-loop-doesnt-change-value-in-the-array-being-itera See Answer from Michel; – Matt G Mar 22 '17 at 17:34
  • Possible Duplicate of http://stackoverflow.com/questions/9920619/changing-value-inside-foreach-loop-doesnt-change-value-in-the-array-being-itera See Answer from Michel; Possible Duplicate http://stackoverflow.com/questions/10121483/php-modify-current-object-in-foreach-loop; Possible Duplicate http://stackoverflow.com/questions/15024616/php-foreach-change-original-array-values – Matt G Mar 22 '17 at 17:44
  • 2
    Possible duplicate of [PHP - Modify current object in foreach loop](http://stackoverflow.com/questions/10121483/php-modify-current-object-in-foreach-loop) – Matt G Mar 22 '17 at 18:05

5 Answers5

5

When dealing with $row in the foreach loop you aren't dealing with the same variable that is in the array, but a copy. If you want to make lasting changes you need to use a reference.

function addLength($toAdd, $added){
   $result = $toAdd;
    foreach ($result as & $row) {
        foreach ($added as $key => $value) {
            if($key == $row['id'] ){
                $row['length'] = $value;   
            }
        } 
    }
    var_dump($result);
    return $result;
}

Please make sure to note that a reference will still exist after the foreach loop has completed. It will contain a reference to the last element of your $result array. To stop this you would need to manually unset the reference.

    function addLength($toAdd, $added){
   $result = $toAdd;
    foreach ($result as & $row) {
        foreach ($added as $key => $value) {
            if($key == $row['id'] ){
                $row['length'] = $value;   
            }
        } 
    }
    var_dump($row); // Outputs the last element of your $result array
    unset($row);
    var_dump($row); // Now undefined.

    var_dump($result);
    return $result;
}

Just as an FYI, you can optimise your code and get rid of the second foreach loop, it's just not necessary. This would do the same:

function addLength($toAdd, $added){
   $result = $toAdd;
    foreach ($result as & $row) {
        if ( array_key_exists($row['id'], $added) ) {
            $row['length'] = $added[$row['id']];
        }
    }
    var_dump($result);
    return $result;
}

Now rather than looping through $added for every item in $toAdd you just check to see if the data is there (by checking for the array key) and if it is, use it.

Styphon
  • 10,304
  • 9
  • 52
  • 86
  • @af_inb I've updated my answer to also include some information on optimising your code. I hope this helps :). – Styphon Mar 22 '17 at 16:50
2

foreach copies each element of the array into a variable, so your changes have no effect. Update the original array instead:

function addLength($toAdd, $added){
   $result = $toAdd;
    foreach ($result as $outerKey => $row) {
        foreach ($added as $key => $value) {
            if($key == $row['id'] ){
                $result[$outerKey]['length'] = $value;   
            }
        } 
    }
    var_dump($result);
    return $result;
}
Ben Hillier
  • 2,126
  • 1
  • 10
  • 15
1

i think you want to add this type change

function addLength($toAdd, $added){
 $result = $toAdd;
 foreach ($result as $first_key => $row) {
    foreach ($added as $key => $value) {
        if($key == $row['id'] ){
            $result[$first_key]['length'] = $value;   
        }
    } 
}
var_dump($result);
return $result;
}

if you do not add key value in index then you can use this code

 function addLength($toAdd, $added){
 $result = $toAdd;
 foreach ($result as $first_key => $row) {
    foreach ($added as $key => $value) {
        if($key == $row['id'] ){
            $result[]['length'] = $value;   
        }
    } 
}
var_dump($result);
return $result;
}
Shafiqul Islam
  • 5,570
  • 2
  • 34
  • 43
0

Change the line:

$row['length'] = $value;  

to:

$result[$row]['length'] = $value;

If that doesn't work, you will need to change the foreach ($result as $row) loop to:

foreach ($result as $row => $data)
Niraj Shah
  • 15,087
  • 3
  • 41
  • 60
  • Hence the last part of my answer to change the loop... No info on input parameters makes it difficult to provide accurate answer. – Niraj Shah Mar 22 '17 at 16:39
-1

Correct me if in wrong but ($result as $row) assigns $row to a copy of an element in $result. It is not referencing the original element in $result. Try foreach($result as &$row) If you do use a reference variable in a foreach loop remember to unset it after the loop with unset($row).