Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected behaviour in foreach using ternary operator and value by reference

Why the following code has the different output in PHP 5.5.* and PHP 7.*:

<?php
$foo = ['bar'=>[['item1'=>'value1']]];
foreach ($foo['bar'] ?: [] as $k => &$arr1) {
  $arr1['item1'] = 'value2';
}

var_dump($foo);

In PHP 5 value of $foo['bar'][0]['item1'] will be modified with the value2, but in PHP 7 it will not.

like image 903
sprutex Avatar asked Nov 25 '25 21:11

sprutex


1 Answers

From the documentation (emphasis mine): Please note that the ternary operator is an expression, and that it doesn't evaluate to a variable, but to the result of an expression. This is important to know if you want to return a variable by reference. The statement return $var == 42 ? $a : $b; in a return-by-reference function will therefore not work and a warning is issued.

With PHP 5, note how the innermost &array(1) is a reference:

array(1) {
  ["bar"]=>
  array(1) {
    [0]=>
    &array(1) {
      ["item1"]=>
      string(6) "value2"
    }
  }
}

But with PHP 7, it is not:

array(1) {
  ["bar"]=>
  array(1) {
    [0]=>
    array(1) {
      ["item1"]=>
      string(6) "value1"
    }
  }
}

If you remove ?: [], so the expression you're looping through is simply $foo['bar'], then the code behaves the same with both PHP 5 and 7, i.e. the innermost &array(1) is a reference.

TLDR: I can't say why this is, or where the difference is explained, but it seems clear that PHP 7 handles the conditional operator ?: differently than does PHP 5.

like image 185
kmoser Avatar answered Nov 28 '25 11:11

kmoser



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!