理解 PHP 引用

全栈 shanhuhai 1591℃ 0评论

PHP 手册里的引用部分看得人一头雾水,所以按自己的理解写了一篇,并且写了一些有意思的示例代码,分享出来。

PHP 引用的解释

我们都知道 php 有引用这个功能,引用不同于指针,他相当于变量名的一个别名,可以想象成一个 linux 的文件名做一个软连接。

看下面代码

$damage = 100;
$harm = & $damage;

这时内存中的数据 100 有了两个名称 damageharm, 当我们调用 $damage$harm 这两个变量名其实访问的是同一个数据。

所以,以下的代码可以理解

$damage = 100;
$harm = & $damage;
echo $damage.PHP_EOL; // 输出 100
$harm = 200;
echo $damage.PHP_EOL; // 输出 200

200 赋值给 $harm 时,由于 $damage$harm 两个变量名对应同一个内存位置的数据,所以 $harm 的值变化 $damage 的值也同样会变化。

PHP 引用可以做什么

函数传递

通常我们将变量传递到函数中时,变量的值和函数内部对变量数据的处理就脱离了关系(这通常叫值传递)。
可以将变量以引用的形式传递到函数中,这样可以实现在函数内部改变外部变量的值。

看下面代码

$name = "狄仁杰";
function changeName(& $name){
   $name = "项羽";
}
changeName( $name );
echo $name.PHP_EOL; // 输出“项羽”

可以看到函数并没有返回值,但是变量 $name 的值变了。

返回引用

看下面代码

<?php
class Magic {

   private $map = [];

   public function & bind($key){
       return $this->map[$key]; 
   }

   public function set($key, $value){
       $this->map[$key] = $value;
   }
}

$name = "";

$magic = new Magic();
$name = & $magic->bind('name');

$magic->set('name', '花木兰');
echo $name."\n";  // 输出“花木兰”

$magic->set('name', '狄仁杰');
echo $name."\n"; // 输出“狄仁杰”

$name = "阿珂";
echo $magic->get('name')."\n"; // 输出“阿珂”

运行以上代码发现,我们并没有对变量$name 进行直接赋值,我们只是对对象内部的 $map 属性进行了设置,变量 $name 就做出了相应的改变, 有木有很神奇?

这是因为我们将数组$map 的一个元素name 作为引用返回给了外部变量$name, 这样就建立了变量 $name$this-&gt;map['name'] 之间的连接,当两者任何一方的值被改变时,另一者也会被改变 。
所以,最后的代码,当外部变量 $name 发生变化,对象内部的对应的数据就也发生了变化。

注意以上示例代码,返回引用时有两处都用了 &amp; 符号!。

unset 一个变量名

运行以下代码:

<?php
$damage = 100;
$harm = & $damage;
unset($damage);
echo $harm;

我们发现,将原变量名$damage unset 掉了,引用 $harm 依然可以用,这说明当一个变量有引用时,相当于它有了多个别名,只要还有一个别名没有被 unset 掉,变量所占的内存就不会被注销。

理解 global 关键字

当我们需要在函数内部调用外部变量,我们一般需要用到global 关键字,这里可以稍微考虑以下。

我们上面好像多次讨论到了函数内部对外部变量的处理, 这跟 global 是不是有什么关系?

没错,global的功能就是基于引用的机制来实现的。

<?php
$name = "狄仁杰";
function say(){
   global $name;
   echo $name."\n";
}

以上代码与下面代码等价

<?php
$name = "狄仁杰";
function say(){
   $name = & $GLOBALS['name'];
   echo $name."\n";
}

解释:所有的全局变量都在数组 $GLOBALS 中, global $name 相当于建立一个 变量$name$GLOBALS['name'] 的引用,当任何一方发生变化时,另一方也会变化,但是 unset 掉一方,对另一方也不会有影响。

转载请注明:大后端 » 理解 PHP 引用

喜欢 (2)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址