众所周知在PHP中,引用的使用方式有三种,分别是:引用赋值 $a = &$b、引用传递 fn(&$a)、引用返回 function &$a(),前两种在PHP代码中很常见就不举栗子了,这里单独来讲讲引用返回

通过官方文档我们了解到,这是一种可以用来引用数组/对象内部元素的方式,具体demo如下:

function &get(&$data, $key)
{
    foreach (explode('.', $key) as $k) {
        if (isset($data[$k])) {
            $data = &$data[$k];
        }
    }
    
    return $data;
}

$data = ['a' => ['b' => ['c' => ['d' => 'lying']]]];
$val = &get($data, 'a.b.c');
$val['test'] = 'test';

var_dump($val, $data);

这里$val就是引用的$data内部多层嵌套下的c元素,改变$val的值就会改变$data['a']['b']['c']的值。如果想要取消引用,直接 unset 掉原引用的变量即可,因为这样只是断开了变量名和变量内容之间的绑定。这并不意味着变量内容被销毁了。

不过官方文档还说过:

引用返回用在当想用函数找到引用应该被绑定在哪一个变量上面时。 不要用返回引用来增加性能,引擎足够聪明来自己进行优化。 仅在有合理的技术原因时才返回引用!

通过这段话我们得知,其实返回 References 并不会提高性能,有时候反而降低性能,所以不要想当然的使用这个特性来“优化”程序。但我们可以了解一下这种用法,毕竟这也是返回值的一种使用方式。

ps:在一个对象的方法中,$this 永远是调用它的对象的引用。

当然引用更多是用在 foreach 迭代数组的情况,比如说:

$a = [['id' => 1, 'name' => 'test'], ['id' => 2, 'name' => 'fantasticbin']];

foreach ($a as &$v) {
    $v['age'] = 18;
}

var_dump($a);

这里可直接用引用来操作子元素,性能比通过 key 来调用元素更好。但是这种使用方式会有一个问题,那就是 foreach 结束后$v变量没有被释放掉,而是一直引用着迭代数组的最后一个元素,如果在后续的逻辑中再次操作$v,就会直接影响迭代数组的结果,比如在 foreach 后和 var_dump 之前增加这段:

$v = 'test';

我们可以看到id为2的这个子元素已经被改成了字符串test,这不是我们想要的结果。那如何避免发生这种情况呢?一方面可以在后续的代码中避免再使用$v,另一方面我们可以在foreach迭代数组后立即unset($v)就可以了。