Search code examples
phpreference

Why does this reference passing not work as expected?


Consider the following code:

class FOO {
  public $v = [];

  function &refv1() {
     return $this->v[1];
  }
  function refv2(&$ref) {
    $ref = &$this->v[2];
  }
}
$FOO = new FOO();

//this works
$acc = &$FOO->refv1();
$acc = '5';
echo $FOO->v[1]; // 5

// this does not work
$bcc = null;
$FOO->refv2($bcc);
$bcc = '10';
echo $FOO->v[2]; // not set!

It's basically the same, but in the first place I return a reference and in the second case I pass it and set it to a ref inside the function. Why doesn't this work, and how can I set a passed reference as an accessor to an array like in the first function?

ANSWER and EXPLANATION:

PHP is very inconsistent in its syntax. You'd might expect that something like

$c = &f();
function &f() {
  return $a[b];
}

is the same as $c = &$a[b]; but it is in fact something like

$a[b] = &$temp;
$c = &$temp;

So, the second function has to be written like this to behave like the first one:

function refv2(&$ref) {
  $ref = $this->v[2];
  $this->v[2] = &$ref;
}

Solution

  • I think your intention is to write this:

    class FOO {
      public $v = [];
    
      function &refv1() {
         return $this->v[1];
      }
      function refv2(&$ref) {
        $this->v[2] = &$ref;
      }
    }
    $FOO = new FOO();
    
    //this works
    $acc = &$FOO->refv1();
    $acc = '5';
    echo $FOO->v[1]; // 5
    
    // this does not work
    $bcc = null;
    $FOO->refv2($bcc);
    $bcc = '10';
    echo $FOO->v[2]; // 10
    

    What went wrong with your code? Basically you got $this->v[2] and $ref the wrong way around in the refv2() method. The right side is assigned to the left side, not the other way around. In your code $this->v[2] is never assigned an value.