Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Pointers behaving unexpectedly

Tags:

php

pointers

While working on a project which checks the if Laravel models are related to each other I noticed some (weird?) pointer behavior going on with PHP. Below is a minimal example to reproduce what I found.

<?php

$arr = ['a', 'b', ['c']];


foreach($arr as &$letter) {
    if (!is_array($letter)) {
        $letter = [$letter];    
    }
}

dump($arr);

foreach($arr as $letter) {
    dump($arr);
}

function dump(...$dump) {
    echo '<pre>';
    var_dump($dump);
    echo '</pre>';  
}

At first I expected the dumps in this response to all return the same data:

[ ['a'], ['b'], ['c'] ]

But that is not what happened, I got the following responses:

[ ['a'], ['b'], ['c'] ]
[ ['a'], ['b'], ['a'] ]
[ ['a'], ['b'], ['b'] ]
[ ['a'], ['b'], ['b'] ]

A running example can be found here.

Why do the pointers act this way? How can I update $letter in the first loop without having to do $arr[$key] = $letter?


Edit: As people seem to be misunderstanding why there is a second foreach loop, this is to show that the array is changing without being reassigned

like image 859
Dexter Avatar asked Nov 27 '25 18:11

Dexter


1 Answers

According to the PHP documentation:

Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().

$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
    $value = $value * 2;
}
// $arr is now array(2, 4, 6, 8)

// Without an `unset($value)`, `$value` is still a reference to the last item: `$arr[3]`

foreach ($arr as $key => $value) {
    // $arr[3] will be updated with each value from $arr...
    echo "{$key} => {$value} ";
    print_r($arr);
}
// ...until ultimately the second-to-last value is copied onto the last value

/* output:
   0 => 2 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 2 )
   1 => 4 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 4 )
   2 => 6 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 6 )
   3 => 6 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 6 ) */
like image 59
Dmytro Avatar answered Nov 29 '25 06:11

Dmytro



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!