PHP开发过程的那些坑(一) ——对象拷贝
PHP开发过程的那些坑(一)——对象拷贝
(原创内容,转载请注明来源,谢谢)
坑:
做单元测试的过程中,想要运用@dataProvider方式分别传两个不同的对象过去。一开始不清楚对象拷贝存在深拷贝和浅拷贝的事情,直接使用等号进行拷贝,导致结果不是想要的结果,调试了很久以后,发现此问题。
举例:
Class Test{
public $a;
public $b;
public function __construct($a, $b){
$this->a = $a;
$this->b = $b;
}
}
$test1 = new Test(1,2);
$test2 = $test1;
$test2->a =2;
此时,$test1和$test2的结果都是2,即$test1的属性$a的值也被改了。不是我想要的结果。
分析:
对象拷贝分为深拷贝和浅拷贝:
深拷贝:赋值时值完全复制,完全的copy,对其中一个作出改变,不会影响另一个。
浅拷贝:赋值时,引用赋值,相当于取了一个别名。对其中一个修改,会影响另一个。使用等号拷贝两个对象,就属于浅拷贝。
改进措施:
1、使用PHP的clone函数
将上述$test2 =$test 1
改为$test2 = clone $test1
后,再对$test2->a
进行复制——$test2->a = 2
,则$test1->a
的值还是1,没有被改动。
2、举一反三,经过查资料,如果使用clone函数,对象中的普通的属性可以实现深拷贝。但是,如果对象的属性中还有对象,即出现类组合的情况,则对此种情况的属性仍是浅拷贝。为了解决此问题,有三种方案:
2.1 方案一
重写类的魔术方法——克隆函数__clone()
在上述Test类中,加一个属性,如下:
Public $obj;//此属性用于存放类的示例
为了深拷贝$obj,则需在上述Test类中,加一个方法,如下:
publicfunction __clone(){
$this->obj= clone $this->obj;
}
但是,在实际工程中,此方法往往不容易实现,因为经常需要涉及的类是框架公共文件、公共接口、其他人或者其他项目的文件等,不易或者没有条件改动里面的源码。因此,下面两个方案更佳。
2.2 方案二
采用序列化和反序列化。
classOther{
public$x;
publicfunction __construct($x){
$this->x = $x;
}
}
class Test{
public $a;
public $b;
public $obj;
public function __construct($a, $b,$obj){
$this->a = $a;
$this->b = $b;
$this->obj = newOther(10);
}
}
$test1 = newTest(1,2);
$test2 = serialize($test1);
$test2 =unserialize($test2);
反序列化后,可以对$test进行操作,不会影响到$test1。
如果安装了PHP的igbinary模块,还可以使用igbinary_serialize和igbinary_unserialize的方式进行序列化和反序列化,对于数据量大的情况下,该方法效率更高,处理速度更快。
2.3 方案三
json_encode和json_decode。
方法和上述类似,可以用此方法将$test1进行转换后赋值给$test2。
——written by linhxx 2017.06.23
- Javascript 的addEventListener()及attachEvent()区别分析
- 设计模式-用接口来实现filter!梭梭就是干!
- OpenDaylight实现轮询策略的负载均衡服务
- 微服务业务开发三个难题-拆分、事务、查询(上)
- 总结了一些指针易出错的常见问题(五)
- 微服务业务开发三个难题-拆分、事务、查询(下)
- C语言之控制台读取上下左右方向键指令
- C程序之修改Windows的控制台大小
- VS2010/MFC编程(对话框:模态对话框及其弹出过程)
- 设计模式-抽象类,只是想为你做更多
- 设计模式-搞个接口,留有余地,让你我不再尴尬
- vs2010点调试,显示系统找不到指定的文件
- C++之类和对象的使用(三)
- C++之类和对象的使用(二)
- php概述
- php教程
- php环境搭建
- PHP书写格式
- php变量
- php常量
- PHP注释
- php数组
- php字符串 string
- PHP整型 integer
- PHP浮点型 float
- php布尔型
- php数据类型之数组
- php数据类型之对象
- php数据类型之null
- php数据类型之间的转换
- php运算符
- php表达式
- PHP循环控制
- PHP流程控制
- php函数
- php全局变量
- PHP魔术变量
- php命名空间
- php 日期
- PHP包含文件
- php文件
- PHP 文件上传
- php Cookies
- php Sessions
- php email
- php安全email
- php错误处理
- PHP异常处理
- php过滤器
- PHP 高级过滤器
- php json
- php 表单
- PHP MySQL 简介
- PHP 连接 MySQL
- php创建数据库
- php 创建表
- php mysq 插入数据
- PHP MySQL 插入多条数据
- PHP MySQL 预处理语句
- php mysql 读取数据
- php mysql where
- PHP MySQL Order By
- PHP MySQL Update
- PHP MySQL Delete
- php ODBC
- mysql用户创建+密码修改+删除用户+角色分配 的正确姿势 实践笔记
- Centos7 安装 Nginx 的正确姿势 并设置开机自启 实践笔记
- js函数大全(2)
- HTML之打开/另存为/打印/刷新/查看原文件等按钮的代码
- Centos7 安装 Keepalived+Nginx 双机热备HA 的正确姿势 并开机自启 实践笔记
- 从 findbugs-maven-plugin 到 spotbugs-maven-plugin 帮你找到代码中的bug
- nmap常用命令检查主机在线与在线主机端口开放情况
- 想做测试工程师的可以看看
- nginx 实现Web应用程序的负载均衡
- 线上遇到nginx Cors跨域请求OPTIONS方法405 Method Not Allowed问题
- 常见Linux命令的正确打开姿势 实践笔记 更新中
- 用gogs轻松搭建个人的git服务器
- Centos7 activemq启动失败 解决 的正确姿势 实践笔记
- 所谓并发编程,所谓有其三
- Redis 中的 3 种特殊数据类型