PHP序列化与反序列化学习
序列化与反序列化学习
把对象转换为字节序列的过程称为对象的序列化;把字节序列恢复为对象的过程称为对象的反序列化。
<?php
class UserInfo {
public $name = "admin";
public $age = 1;
public $blog = "file:///var/www/html/flag.php";
}
$data = new UserInfo();
echo serialize($data);
?>
页面显示:
O:8:"UserInfo":3:{s:4:"name";s:5:"admin";s:3:"age";i:1;s:4:"blog";s:29:"file:///var/www/html/flag.php";}
此处调用到了serialize函数,对数据进行了序列化并返回了一组字符串。
<?php
$sites = array('t1', 'tt2', 'ttt3');
$serialized_data = serialize($sites);
echo $serialized_data;
?>
输出:a:3:{i:0;s:2:"t1";i:1;s:3:"tt2";i:2;s:4:"ttt3";}
对这个序列化的输出进行分析:
a:3表示数组里面有三个分类。
i:0:表示第一个数组。
s:2:表示有两个字符
"t1":表示内容为't1'。
i:1:表示第二个数组。
s:3:"tt2":标识有三个字符,内容为'tt2'
反序列化: <?php $sites = array('t1', 'tt2', 'ttt3'); $serializeddata = serialize($sites); #echo $serializeddata; $unserializeddata = unserialize($serializeddata); printr($unserializeddata); ?>
此时又生成回:Array ( [0] => t1 [1] => tt2 [2] => ttt3 )
其中:o表示对象,a表示数组,s表示字符,i表示数字
类
在php中,一个类可以包含有属于自己的常量,变量(属性)以及函数(方法)
一段反序列化,序列化代码:(来自https://www.jianshu.com/p/8f498198fc3d)
<?php
class Test
{
public $handle1;
private $handle2;
protected $handle3;
public function __construct($handle1,$handle2,$handle3)
{
$this->handle1 = $handle1;
$this->handle2 = $handle2;
$this->handle3 = $handle3;
echo '__construct<br />';
}
public function __destruct()
{
echo $this->handle2.'<br />';
echo '__destruct<br />';
}
public function __wakeup()
{
echo '__wakeup<br />';
}
}
$obj = new Test("111","222","333");
$see = serialize($obj);
print 'Serialized: ' . $see . '<br />';
# %00Test%00v2 表示 private %00*%00v3 表示protected
$ss = 'O:4:"Test":3:{s:7:"handle1";s:3:"777";s:17:"%00Test%00handle2";s:3:"888";S:14:"%00*%00handle3";s:3:"999";}';
$obj2 = unserialize($ss);
var_dump($obj2);
?>
在这段php代码中:
$obj = new Test("111","222","333");
创建了类的实例,所以使用到了new的关键字。
在类中对于静态方法和静态属性的引用:
class Test{
public static $test = 1;
public static function test(){
}
}
此时我们不用实例化对象,直接使用Test::$test就能获取$test属性的值,Test::test()这样可以直接调用静态方法test。
范围解析操作符:可以用于访问静态成员,类常量,还可以用于覆盖类中的属性和方法,即::
<?php
class MyClass {
const CONST_VALUE = 'A constant value';
}
$classname = 'MyClass';
echo $classname::CONST_VALUE; // 自 PHP 5.3.0 起
echo '<br>';
echo MyClass::CONST_VALUE;
?>
此时我们就使用了变量静态地调用了类MyClass当中的常量,注意自 PHP 5.3.0 起,可以通过变量来引用类,但该变量的值不能是关键字。
结果:
A constant value
A constant value
使用子类覆盖父类:
<?php
class OtherClass extends MyClass
{
public static $my_static = 'static var';
public static function doubleColon() {
echo parent::CONST_VALUE . "\n";
echo self::$my_static . "\n";
}
}
$classname = 'OtherClass';
echo $classname::doubleColon(); // 自 PHP 5.3.0 起
OtherClass::doubleColon();
?>
此时PHP不会调用父类中已被覆盖的方法,是否调用父类的方法取决于子类。
调用父类方法:
<?php
class MyClass
{
protected function myFunc() {
echo "MyClass::myFunc()\n";
}
}
class OtherClass extends MyClass
{
// 覆盖了父类的定义
public function myFunc()
{
// 但还是可以调用父类中被覆盖的方法
parent::myFunc();
echo "OtherClass::myFunc()\n";
}
}
$class = new OtherClass();
$class->myFunc();
?>
输出:
MyClass::myFunc() OtherClass::myFunc()
其中-> 是对象成员访问符号。
例如:$this->name = $value
其中:$this是特定变量,它代表了他的类,通过->我们可以访问其类的成员,所以这段代码的意思就是:将当前类的name变量的值设置为 $value.
继承:类可以在声明中用 extends 关键字继承另一个类的方法和属性。PHP不支持多重继承,一个类只能继承一个基类。
class Father
{
public $aar;
public function bar ()
{
return 'father';
}
final public function testFinal ()
{
return 'father';
}
}
class Son extends father
{
public function bar ()
{
return 'son';
}
public function callFatherBar ()
{
return parent::bar();
}
//Cannot override final method Father::testFinal()
// public function testFinal()
// {
// }
//如果父类定义是设置了final 则父类方法均不能覆盖 final class Father
//属性无final的概念
}
echo (new Son())->bar();//son
echo (new Son())->callFatherBar();//father
前面写类方法获取属性我们使用的是::
这是在静态环境中,对于非静态的,我们使用$this->property即可。
属性的声明由关键词:public,protected或者private开头,后面加上变量。
即:
public $handle1;
private $handle2;
protected $handle3;
我们声明了三个不同属性的变量:
三个关键字控制 public 公有;protected 受保护;private 私有的
public:可以在任何地方被访问
protected:可以被自身或其子类和父类访问,表示方式是在变量名前加个%00*%00
private:只能被其定义所在的类访问,表示方式是在变量名前加上%00类名%00
还有关于常量的定义:
const constant = 'constant value';
构造函数
在PHP5中,可以在一个类中定义一个构造函数,具有构造函数的类,当每次创建新的对象的时候会先调用这个方法,以方便我们在使用对象前做一些初始化工作。
class Father
{
function __construct ()//不可为private
{
echo 'Father';
}
}
class Child extends Father
{ //当Child无构造函数时,自动调用父类的 Father
function __construct ()
{
echo 'Child';
}
function callFatherConstruct ()
{
parent::__construct();
}
}
$obj = new Child;//Child
$obj->callFatherConstruct();//Father
子类中定义了构造函数,不会隐式的调用父类的构造函数,需要用parent::__construct()调用,如果子类没有构造函数,父类的构造函数将和普通函数一样被子类继承。
参考链接:https://www.cnblogs.com/ValleyUp/p/11181141.html
magic函数
php类包含magic函数的特殊函数,magic函数命名是以符号 __ 开头的,例如 __ sleep, __ wakeup,__ construct, __ destruct等。
这些函数经常会被自动调用,construct当一个对象创建时被调用,destruct当一个对象销毁时被调用。
常用的魔术方法有:
serialize():检查类中是否存在一个魔术方法 __sleep(),优先调用此方法,然后执行序列化操作。
unserialize():检查是否存在一个 __wakeup() 方法,优先调用此方法
__construct():当一个对象创建时被调用
__destruct():当一个对象销毁时被调用
__call():当调用一个未定义(包括没有权限访问)的方法是调用此方法
__callStatic():处理静态方法调用
__get():当调用一个未定义的属性时访问此方法
__set(): 给一个未定义的属性赋值时调用
__isset():当在一个未定义的属性上调用isset()函数时调用此方法
__unset():当在一个未定义的属性上调用unset()函数时调用此方法
__sleep():常用于提交未提交的数据,或类似的清理操作,在对象被序列化之前运行
__wakeup():用于预先准备对象需要的资源,在对象被反序列化之后被调用
__toString():用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。此方法必须返回一个字符串
__invoke():当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。
__set_state(),:当调用var_export()时,这个静态 方法会被调用(自PHP 5.1.0起有效)。本方法的唯一参数是一个数组,其中包含按array(’property’ => value, …)格式排列的类属性。
__clone() :对象赋值时使用的引用赋值,使用clone方法复制一个对象时,对象会自动调用__clone魔术方法
当序列化字符串中,表示对象属性个数的值大于实际属性个数时,那么就会跳过wakeup方法的执行。
拿php一个代码为例,综合上面学习的进行理解:
<?php
class Connection //定义一个类,类名为Connection
{
protected $link; //定义一个变量属性,可以被自身或其子类和父类访问
private $server, $username, $password, $db; //定义了四个变量属性,只能被其定义所在的类访问。
public function __construct($server, $username, $password, $db) //定义一个方法,可以在任何地方被访问
{
$this->server = $server; //$this是特定变量,它代表了他的类connection,通过->我们可以访问其类的成员如server等,将当前类的server变量的值设置为 $server.
$this->username = $username; //同上,以下皆是。
$this->password = $password;
$this->db = $db;
$this->connect();
}
private function connect() //定义一个方法,只能被其定义所在的类访问
{
$this->link = mysql_connect($this->server, $this->username, $this->password); //当前的link,用来连接mysql数据库。
mysql_select_db($this->db, $this->link);
}
public function __sleep() //提交数据时,要进行的行为。
{
return array('server', 'username', 'password', 'db'); //提交的时候返回
}
public function __wakeup() //重新建立数据库连接
{
$this->connect();
}
}
?>
序列化得到字符串格式:
s:size:value:表示字符。
a:size:{键值;值;元素},
例如a:3:{i:0;s:2:"t1";i:1;s:3:"tt2";i:2;s:4:"ttt3";}
i:0,表示第一个数组,s:2表示有两个字符,"t1",表示字符为t1。
O:对象长度:对象类名称:成员变量数:{类型:字符个数长度:"具体值";类型:长度:"具体值";.......}
O:4:"Test":3:{s:7:"handle1";s:3:"111";s:13:"Testhandle2";s:3:"222";s:10:"*handle3";s:3:"333";}
O:1:"A":2:{s:6:" A var";i:1139586461;s:4:"var2";s:1:"b";}
反序列化能将类的成员变量还原,但是不能将类的方式还原。
解析顺序:
jsonencode/jsondecode
<?php
$a=array('a'=>'cuit','b'=>'syclover','c'=>'dog');
//序列化数组
$s=json_encode($a);
echo $s;
//反序列化
$o=json_decode($s);
?>
输出:{"a":"cuit","b":"syclover","c":"dog"}
e></p>
PHP序列化与反序列化学习的更多相关文章
- java中的序列化和反序列化学习笔记
须要序列化的Person类: package cn.itcast_07; import java.io.Serializable; /* * NotSerializableException:未序列化 ...
- Java序列化与反序列化学习(一)
一.序列化与反序列化概述 当两个进程在进行远程通信时,彼此可以发送各种类型的数据.无论是何种类型的数据,都会以二进制序列的形式在网络上传送.发送方需要把这个Java对象转换为字节序列,才能在网 ...
- JAVA对象序列化和反序列化学习
JAVA序列化就是将JAVA对象转化为字节序列的过程,而JAVA反序列化就是将字节序列转化为JAVA对象的过程. 这一过程是通过JAVA虚拟机独立完成,所以一个对象序列化后可以在任意时间和任意机器上反 ...
- C#序列化与反序列化学习笔记
本笔记摘抄自:https://www.cnblogs.com/maitian-lf/p/3670570.html,记录一下学习过程以备后续查用. 序列化是把一个内存中的对象的信息转化成一个可以持久化保 ...
- php序列化和反序列化学习
1.什么是序列化 序列化说通俗点就是把一个对象变成可以传输的字符串. 1.举个例子,不知道大家知不知道json格式,这就是一种序列化,有可能就是通过array序列化而来的.而反序列化就是把那串可以传输 ...
- Java序列化与反序列化学习(三):序列化机制与原理
Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的 过程.Java序列化API提供 ...
- Java序列化与反序列化学习(二):序列化接口说明
一.序列化类实现Serializable接口 Serializable接口没有方法,更像是个标记.有了这个标记的Class就能被序列化机制处理. ObjectOutputStream只能对Serial ...
- WebAPI调用笔记 ASP.NET CORE 学习之自定义异常处理 MySQL数据库查询优化建议 .NET操作XML文件之泛型集合的序列化与反序列化 Asp.Net Core 轻松学-多线程之Task快速上手 Asp.Net Core 轻松学-多线程之Task(补充)
WebAPI调用笔记 前言 即时通信项目中初次调用OA接口遇到了一些问题,因为本人从业后几乎一直做CS端项目,一个简单的WebAPI调用居然浪费了不少时间,特此记录. 接口描述 首先说明一下,基于 ...
- Java基础学习总结——Java对象的序列化和反序列化
一.序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化. 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上,通常存 ...
随机推荐
- keepalived的vrrp多播报文被禁,导致VIP同时位于多个机器上
keepalived的vrrp多播报文被禁,导致VIP同时位于多个机器上 查看man keepalived.conf,VRRP instances中给出了单播的设置方法,添加unicast_peer即 ...
- 第七篇Scrum冲刺博客--Interesting-Corps
第七篇Scrum冲刺博客 站立式会议 1.会议照片 2.队友完成情况 团队成员 昨日完成 今日计划 鲍鱼铭 各界面数据请求云函数设计及实现 代码交接及整体架构搭建 叶学涛 进行代码优化 和队友进行交接 ...
- 简述BFS与DFS
简述BFS与DFS 最近学习了数据结构课程以及应对蓝桥杯备考,所以花费了一点时间将比较重要的两个搜索BFS(宽度优先搜索)和DFS(深度优先搜索)大致思路以及代码整理出来,如有错误,还请各位大佬批评改 ...
- Windows & Linux 安装使用 Vim 编辑器 3分钟入门 - 精简归纳
Windows & Linux 安装使用 Vim 编辑器 3分钟入门 - 精简归纳 JERRY_Z. ~ 2020 / 8 / 25 转载请注明出处! 目录 Windows & Lin ...
- CF208E Blood Cousins 题解
一个奇奇怪怪的复杂度很垃圾的线段树合并解法 通过分析可以发现,要找$x$的$k$辈兄弟,只需要找到$x$的$k$辈祖先,然后查找以该祖先为根的子树中和$x$深度相同的节点个数$-1$即可.也就是说,询 ...
- Linux下如何知道是否有人在使坏?
在 Linux 下查看用户的行为,不仅仅是网管要做的事,也是开发人员所应该具备的基本技能之一.为什么呢?因为有时其他同事在做一些很消耗资源的事情,比如在编译大型程序,可能会导致服务器变得很慢,从而影响 ...
- e3mall商城的归纳总结3之后台商品节点、认识nginx
一 后台商品节点 大家都知道后台创建商品的时候需要选择商品的分类,而这个商品的分类就就像一棵树一样,一层包含一层又包含一层.因此这里用的框架是easyUiTree.该分类前端使用的是异步加载模式(指 ...
- Java拷贝——深拷贝与浅拷贝
深拷贝和浅拷贝 值类型 vs 引用类型 在Java中,像数组.类Class.枚举Enum.Integer包装类等等,就是典型的引用类型,所以操作时一般来说采用的也是引用传递的方式: 但是Java的语言 ...
- shader之间的数据传递
shader之间传递数据实在是太常用了. 下面我们总结几种shader之间传递数据的方法. Name based matching 最简单,也是最常用的一种传递方式是依靠名字进行匹配. 例如我们从ve ...
- 关于List的remove()方法
最近遇到一个小问题,我将其简化为下列代码,List的remove()方法在下列颜色注重的代码执行的源码也是不同的~ List<Integer> list=new ArrayList< ...