Search code examples
phparrayspass-by-reference

PHP is right behavior?


Is this right behavior for php?

tested on PHP Version 7.1.28 and PHP Version 7.2.13 Why list changed? It's bug of PHP or I don't know something?

$label_list = explode(',', '1111, 22222, 33333');
foreach($label_list as &$label_item) {
    $label_item = trim(mb_strtolower($label_item));
}

var_dump($label_list); // source list
foreach ($label_list as $label_item) {
    var_dump($label_list); //? wtf list
}

result data:

array(3) {
  [0]=> string(4) "1111"
  [1]=> string(5) "22222"
  [2]=> &string(5) "33333"
}
array(3) {
  [0]=> string(4) "1111"
  [1]=> string(5) "22222"
  [2]=> &string(4) "1111"
}
array(3) {
  [0]=> string(4) "1111"
  [1]=> string(5) "22222"
  [2]=> &string(5) "22222"
}
array(3) {
  [0]=> string(4) "1111"
  [1]=> string(5) "22222"
  [2]=> &string(5) "22222"
}

Why data in array changes? no changes inside cycle. Any explain?


Solution

  • There is no bug.
    You used the same variable in both loops, but the first time you did it by reference and you did not unset it after the loop. That means the next time you change the variable you change the source array.
    Unset after you use by reference.

    $label_list = explode(',', '111, 222, 333');
    foreach($label_list as &$label_item) {
        $label_item = trim(mb_strtolower($label_item));
    }
    unset($label_item); // unset the by reference variable
    var_dump($label_list); // source list
    foreach ($label_list as $label_item) {
        var_dump($label_list); //? wtf list
    }
    

    Outputs:

    array(3) {
      [0]=>
      string(3) "111"
      [1]=>
      string(3) "222"
      [2]=>
      string(3) "333"
    }
    array(3) {
      [0]=>
      string(3) "111"
      [1]=>
      string(3) "222"
      [2]=>
      string(3) "333"
    }
    array(3) {
      [0]=>
      string(3) "111"
      [1]=>
      string(3) "222"
      [2]=>
      string(3) "333"
    }
    array(3) {
      [0]=>
      string(3) "111"
      [1]=>
      string(3) "222"
      [2]=>
      string(3) "333"
    }
    

    https://3v4l.org/MjlcU

    If you look at your own output you see & at the last item.
    That means it's by reference.