PHP的变量赋值
这个标题估计很多人会不屑一顾,变量赋值?excuse me?我们学开发的第一课就会了好不好。但是,就是这样基础的东西,反而会让很多人蒙圈,比如,值和引用的关系。今天,我们就来具体讲讲。
首先,定义变量和赋值这个不用多说了吧
$a = 1;
$b = '2';
$c = [4, 5, 6];
$d = new stdClass();
四个变量,分别定义了整型、字符串、数组的对象。这也是我们天天要打交道的四种类型。
然后,变量给变量赋值。
$a1 = $a;
$b1 = $b;
$c1 = $c;
$d1 = $d;
请注意,前三个的赋值都是正常的赋值,也就是对具体内容的拷贝。当我们修改$a1的时候$a不会有变化。$a1是新开的内存空间保存了我们的值。也就是说,他们的值是一样的,但内存地址不一样。是两个没啥关系的长得很像的人而已。
但是$d1和$d就不是了,这两货不仅值是一样的,内存地址也是一样的。这种情况就是我们所说的引用赋值。当$d1发生变化时,$d2也会产生变化。
可以这么说:引用赋值就是为原变量建立了一个Windows下的快捷方式或者Linux中的软链接。
用具体的例子来说明,首先是普通值的赋值:
// 普通赋值
$v = '1';
$c = $v;
$c = '2';
echo $v, PHP_EOL; // '1'
// 数组也是普通赋值
$arr1 = [1,2,3];
$arr2 = $arr1;
$arr2[1] = 5;
print_r($arr1); // [1, 2, 3]
$c不会对$v的值产生影响。$arr2修改了下标1,也就是第二个数字为5,当然也不会对$arr1产生影响。
那么对象形式的引用赋值呢?
// 对象都是引用赋值
class A {
public $name = '我是A';
}
$a = new A();
$b = $a;
echo $a->name, PHP_EOL; // '我是A'
echo $b->name, PHP_EOL; // '我是A'
$b->name = '我是B';
echo $a->name, PHP_EOL; // '我是B'
果然不出所料,$b修改了name属性的内容后,$a里面的name也变成了$b所修改的内容。
在这种情况下,如果对象想要不是引用传递的,一是使用__clone(),也就是原型模式来进行自己的拷贝。二是从外面重新new一个呗。
// 使用克隆解决引用传递问题
class Child{
public $name = '我是A1的下级';
}
class A1 {
public $name = '我是A';
public $child;
function __construct(){
$this->child = new Child();
}
function __clone(){
$this->name = $this->name;
// new 或者用Child的克隆都可以
// $this->child = new Child();
$this->child = clone $this->child;
}
}
$a1 = new A1();
echo $a1->name, PHP_EOL; // 输出a1原始的内容
echo $a1->child->name, PHP_EOL;
$b1 = $a1;
echo $b1->name, PHP_EOL; // b1现在也是a1的内容
echo $b1->child->name, PHP_EOL;
$b1->name = '我是B1'; // b1修改内容
$b1->child->name = '我是B1的下级';
echo $a1->name, PHP_EOL; // a1变成b1的内容了
echo $a1->child->name, PHP_EOL;
// 使用__clone
$b2 = clone $b1; // b2克隆b1
$b2->name = '我是B2'; // b2修改内容
$b2->child->name = '我是B2的下级';
echo $b1->name, PHP_EOL; // b1不会变成b2修改的内容
echo $b1->child->name, PHP_EOL;
echo $b2->name, PHP_EOL; // b2修改的内容没问题,b1、b2不是一个货了
echo $b2->child->name, PHP_EOL;
对象的引用这一块确实会容易让人蒙圈。特别是更加复杂的对象,内部的属性还有各种引用其他对象的时候。这种情况下一定要仔细确认引用赋值会不会带来问题,如果有问题,就使用新对象或者克隆技术进行引用问题的处理。
最后,轻松一下,引用变量的赋值就和我们给方法传引用参数一样的,使用一个&符号就可以啦!
// 引用赋值
$b = &$v;
$b = '3';
echo $v, PHP_EOL;
今天我们更深入的学习和了解了一下PHP中的赋值问题,特别是普通赋值和引用赋值的问题。下回看代码和框架的时候可以注意注意别人是怎么灵活使用这两种赋值的哈,自己也能试试能不能运用这两种方式改造下自己曾经写过的BUG哦!
参考文档:
https://www.php.net/manual/zh/language.variables.basics.php
https://www.php.net/manual/zh/language.oop5.cloning.php
关注公众号:【硬核项目经理】获取最新文章
添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料
知乎、公众号、抖音、头条搜索【硬核项目经理】
B站ID:482780532
PHP的变量赋值的更多相关文章
- makefile之变量赋值
makefile中变量赋值有4种方法: = , := , += , ?= = :直接赋值 变量 = 值 := :位置相关赋值 如果右值为一个值,那么它和=没区别,如果右值为变量,那么左边变 ...
- sql server存储过程中SELECT 与 SET 对变量赋值的区别
SQL Server 中对已经定义的变量赋值的方式用两种,分别是 SET 和 SELECT. 对于这两种方式的区别,SQL Server 联机丛书中已经有详细的说明,但很多时候我们 并没有注意,其实这 ...
- mysql中变量赋值
http://www.cnblogs.com/qixuejia/archive/2010/12/21/1913203.html sql server中变量要先申明后赋值: 局部变量用一个@标识,全局变 ...
- Python基础0:变量 赋值 表达式和运算符
变量: 前面我们在使用print()输出内容的时候,如果内容很长,后面要再次输出的时候,就需重新在输入一遍. 如果给输出的内容起个简单的别名.这样我们用简短的别名来代替长内容,下次要输出的时候就直接使 ...
- shell变量赋值 不能有空格的原因
典型例子: a=date echo $a 成立 a =date echo $a 不成立 其实原因很简单 shell在解释命令时的原则是第一个符号标记只能是程序或者命令,有空格的时候第 ...
- paip.提升效率--批量变量赋值 “多元”赋值
paip.提升效率--批量变量赋值 "多元"赋值 ##石麻是批量变量赋值. 为一组变量赋值. 例子 1 <?php $my_array = array("Dog&q ...
- jquery ajax给外部变量赋值 async: false
开发过程中用到检查是否存在手机号问题. //验证手机号是否注册 var bl = false; $.ajax({ type: ...
- SqlServer中使用Select语句给变量赋值的时候需要注意的一个问题
我们知道在SqlServer中可以用Select语句给变量赋值,比如如下语句就为int类型的变量@id赋值 ; select @id=id from ( as id union all as id u ...
- const变量赋值报错分析
const变量赋值报错分析 const变量赋值报错 从变量到常量的赋值是合法C++的语法约定的, 如从char 到const char顺畅: 但从char **到 const char **编译器就会 ...
- oracle 变量赋值
在oracle 中使用 select 字段 into 变量 from 表 where 条件 这种方法给变量赋值时和MSSQL的行为有比较大区别. 在MSSQL中如果在该表中未检索到任何行,则变量的值保 ...
随机推荐
- Python断言及常用断言函数总结
Python断言 Python assert 语句,又称断言语句,可以看做是功能缩小版的 if 语句,它用于判断某个表达式的值,如果值为真,则程序可以继续往下执行:反之,Python 解释器会报 As ...
- Servelt&&JSP进阶
Servlet与JSP进阶 来自mkw的视频课程的总结 1.前言 内容包括 掌握Java Web核心特性,Servlet核心对象以及JSP九大内置对象.主要有以下的内容: 请求结构 && ...
- 大数的快速幂模 Python实现
要求 实现模幂算法,通过服务器的检验. 访问http://2**.207.12.156:9012/step_04服务器会给你10个问题,每个问题包含三个数(a,b,c),请给出a^b%c的值.返回值写 ...
- Java角度制向弧度制转化
1.第一次写博客啊写博客啊写啊写0.0..0. 2.输入正多边形的边长·边数·求正多边形的面积 3.超级简单,可是在转弧度制那里有点懵,刚开始学Java,所以难免走弯路 4.代码如下: 1 publi ...
- C#多线程---Event类实现线程同步
一.简介 我们使用类(.net Framework中的类,如 AutoResetEvent, Semaphore类等)的方法来实现线程同步的时候,其实内部是调用操作系统的内核对象来实现的线程同步. S ...
- Spring详解(十)加载配置文件
在项目中有些参数经常需要修改,或者后期可能会有改动时,那我们最好把这些参数放到properties文件中,在源代码中读取properties里面的配置,这样后期只需要改动properties文件即可, ...
- C# 读取保存xml文件
直接读取xml文件中的内容 XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(result); XmlNode root = xmlDoc. ...
- Int 2e 与 Sysenter区别
参考:张银奎<软件调试>第八章 Int 2e: Windows将2e号向量专门用作系统调用,在启动早起初始化中断描述表时便注册好了适合的服务例程.因此当NtDll中的NtReadFile发 ...
- 【转】时冲的CSDN:Linux系统各个目录的作用
请各位移步原文链接:时冲的CSDN 以下仅用于个人梳理,排版方便阅读记忆(原文更优): from my typora: 文章目录 Linux文件系统 LINUX有四种基本文件系统类型: 1.普通文件: ...
- 并发编程之:Lock
大家好,我是小黑,一个在互联网苟且偷生的农民工. 在之前的文章中,为了保证在并发情况下多线程共享数据的线程安全,我们会使用synchronized关键字来修饰方法或者代码块,以及在生产者消费者模式中同 ...