PHP的变量赋值

PHP的变量赋值

这个标题估计很多人会不屑一顾,变量赋值?excuse me?我们学开发的第一课就会了好不好。但是,就是这样基础的东西,反而会让很多人蒙圈,比如,值和引用的关系。今天,我们就来具体讲讲。

首先,定义变量和赋值这个不用多说了吧

1$a = 1;
2$b = '2';
3$c = [4, 5, 6];
4$d = new stdClass();

四个变量,分别定义了整型、字符串、数组的对象。这也是我们天天要打交道的四种类型。

然后,变量给变量赋值。

1$a1 = $a;
2$b1 = $b;
3$c1 = $c;
4$d1 = $d;

请注意,前三个的赋值都是正常的赋值,也就是对具体内容的拷贝。当我们修改$a1的时候a不会有变化。a1是新开的内存空间保存了我们的值。也就是说,他们的值是一样的,但内存地址不一样。是两个没啥关系的长得很像的人而已。

但是d1和d就不是了,这两货不仅值是一样的,内存地址也是一样的。这种情况就是我们所说的引用赋值。当d1发生变化时,d2也会产生变化。

可以这么说:引用赋值就是为原变量建立了一个Windows下的快捷方式或者Linux中的软链接。

用具体的例子来说明,首先是普通值的赋值:

 1// 普通赋值
 2$v = '1';
 3$c = $v;
 4$c = '2';
 5echo $v, PHP_EOL; // '1'
 6
 7// 数组也是普通赋值
 8$arr1 = [1,2,3];
 9$arr2 = $arr1;
10$arr2[1] = 5;
11print_r($arr1); // [1, 2, 3]

c不会对v的值产生影响。arr2修改了下标1,也就是第二个数字为5,当然也不会对arr1产生影响。

那么对象形式的引用赋值呢?

 1// 对象都是引用赋值
 2class A {
 3    public $name = '我是A';
 4}
 5
 6$a = new A();
 7$b = $a;
 8
 9echo $a->name, PHP_EOL; // '我是A'
10echo $b->name, PHP_EOL; // '我是A'
11
12$b->name = '我是B';
13echo $a->name, PHP_EOL; // '我是B'

果然不出所料,b修改了name属性的内容后,a里面的name也变成了b所修改的内容。

在这种情况下,如果对象想要不是引用传递的,一是使用__clone(),也就是原型模式来进行自己的拷贝。二是从外面重新new一个呗。

 1// 使用克隆解决引用传递问题
 2class Child{
 3    public $name = '我是A1的下级';
 4}
 5class A1 {
 6    public $name = '我是A';
 7    public $child;
 8
 9    function __construct(){
10        $this->child = new Child();
11    }
12
13    function __clone(){
14        $this->name = $this->name;
15        // new 或者用Child的克隆都可以
16        // $this->child = new Child();
17        $this->child = clone $this->child;
18    }
19}
20
21$a1 = new A1();
22
23echo $a1->name, PHP_EOL; // 输出a1原始的内容
24echo $a1->child->name, PHP_EOL;
25
26$b1 = $a1;
27echo $b1->name, PHP_EOL; // b1现在也是a1的内容
28echo $b1->child->name, PHP_EOL;
29
30$b1->name = '我是B1'; // b1修改内容
31$b1->child->name = '我是B1的下级';
32echo $a1->name, PHP_EOL; // a1变成b1的内容了
33echo $a1->child->name, PHP_EOL;
34
35// 使用__clone
36$b2 = clone $b1; // b2克隆b1
37$b2->name = '我是B2'; // b2修改内容
38$b2->child->name = '我是B2的下级';
39echo $b1->name, PHP_EOL; // b1不会变成b2修改的内容
40echo $b1->child->name, PHP_EOL;
41echo $b2->name, PHP_EOL; // b2修改的内容没问题,b1、b2不是一个货了
42echo $b2->child->name, PHP_EOL;

对象的引用这一块确实会容易让人蒙圈。特别是更加复杂的对象,内部的属性还有各种引用其他对象的时候。这种情况下一定要仔细确认引用赋值会不会带来问题,如果有问题,就使用新对象或者克隆技术进行引用问题的处理。

最后,轻松一下,引用变量的赋值就和我们给方法传引用参数一样的,使用一个&符号就可以啦!

1// 引用赋值
2$b = &$v;
3$b = '3';
4echo $v, PHP_EOL;

今天我们更深入的学习和了解了一下PHP中的赋值问题,特别是普通赋值和引用赋值的问题。下回看代码和框架的时候可以注意注意别人是怎么灵活使用这两种赋值的哈,自己也能试试能不能运用这两种方式改造下自己曾经写过的BUG哦!

测试代码: https://github.com/zhangyue0503/dev-blog/blob/master/php/201910/source/PHP%E7%9A%84%E5%8F%98%E9%87%8F%E8%B5%8B%E5%80%BC.php

参考文档: https://www.php.net/manual/zh/language.variables.basics.php https://www.php.net/manual/zh/language.oop5.cloning.php

本文分享自微信公众号 - 硬核项目经理(fullstackpm),作者:ZyBlog

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • PHP中的那些魔术方法(一)

    在PHP中,有一堆魔术方法,服务于类和对象。PHP虽然也是纯种的面向对象语言,但是之前的PHP还真不是,所以有一些面向对象的标准实现并不完善,比如重载。但是,我...

    硬核项目经理
  • PHP设计模式之模板方法模式

    模板方法模式,也是我们经常会在不经意间有会用到的模式之一。这个模式是对继承的最好诠释。当子类中有重复的动作时,将他们提取出来,放在父类中进行统一的处理,这就是模...

    硬核项目经理
  • PHP的那些魔术方法(二)

    上文中介绍了非常常用并且也是面试时的热门魔术方法,而这篇文章中的所介绍的或许并不是那么常用,但绝对是加分项。当你能准确地说出这些方法及作用的时候,相信对方更能对...

    硬核项目经理
  • 数据库之mariadb整体概述

    一、数据库的安装方式及其安装步骤 1、安装方式 rpm包安装,yum安装,二进制包安装,编译安装 2、安装步骤 (本文是使用二进制包安装) 1)下载m...

    小小科
  • 网站搭建-django-学习成绩管理-02-数据库创建

    系统:Windows 7 语言版本:Anaconda3-4.3.0.1-Windows-x86_64 编辑器:pycharm-community-2016.3....

    zishendianxia
  • 这是一个用markdown来测试的文章

    小贝壳
  • python技巧分享(十三)

    songleo
  • tp3.1.2缓存,日志,调试,模板,标签,视图

    1.模板 默认在tpl目录下 默认后缀是.html,可以通过TMPL_TEMPLATE_SUFFIX来配置 如果启用分组,那么模板可能在tpl/分组名/目...

    苦咖啡
  • python __name__ == ‘__main__’详细解释

    学习过C语言或者Java语言的盆友应该都知道程序运行必然有主程序入口main函数,而python却不同,即便没有主程序入口,程序一样可以自上而下对代码块依次运行...

    猿说编程[Python和C]
  • git报unable to auto-detect email address错误

    找到工程目录的.git文件夹,打开之后找到config文件,在最后边加上一句话 [user]     email = your email     name =...

    似水的流年

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动