Passing/Returning references to object + changing object is not working

|▌冷眼眸甩不掉的悲伤 提交于 2020-01-04 05:17:09

问题


I am using an answer from How to get random value out of an array to write a function that returns a random item from the array. I modified it to pass by reference and return a reference.

Unfortunately, it doesn't appear to work. Any modifications to the returned object do not persist. What am I doing wrong?

I'm on PHP 5.4 if that makes a difference (Don't ask).

function &random_value(&$array, $default=null)
{
    $k = mt_rand(0, count($array) - 1);
    $return = isset($array[$k])? $array[$k]: $default;
    return $return;
}

Usage...

$companies = array();
$companies[] = array("name" => "Acme Co",  "employees"=> array( "John", "Jane" ));
$companies[] = array("name" => "Inotech",  "employees"=> array( "Bill", "Michael" ));

$x = &random_value($companies);
$x["employees"][] = "Donald";
var_dump($companies);

Output...

array(2) {
  [0] =>
  array(2) {
    'name' =>
    string(7) "Acme Co"
    'employees' =>
    array(2) {
      [0] =>
      string(4) "John"
      [1] =>
      string(4) "Jane"
    }
  }
  [1] =>
  array(2) {
    'name' =>
    string(7) "Inotech"
    'employees' =>
    array(2) {
      [0] =>
      string(4) "Bill"
      [1] =>
      string(7) "Michael"
    }
  }
}

I even copied and pasted the examples from the documentation and none of those worked either. They all output null.


回答1:


The ternary operator creates an implicit copy, which breaks the reference chain. Use an explicit if... else:

function &random_value(&$array, $default=null)
{
    $k = mt_rand(0, count($array) - 1);
    if (isset($array[$k])) {
        return $array[$k];
    } else {
        return $default;
    }
}

As to why, the docs now state:

Note: 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 in later PHP versions.

See also this bug where the ternary operator actually returns by reference in a foreach context, when it shouldn't.




回答2:


I'm having trouble wrapping my head around a better function aspect than @bishop as I have just consumed an enormous lunch, however this works:

$x =& $companies[array_rand($companies)];
$x["employees"][] = "Donald";
var_dump($companies);


来源:https://stackoverflow.com/questions/32702536/passing-returning-references-to-object-changing-object-is-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!