1.序列化
名称 | 描述 |
---|---|
serialize() |
将一个值或一个数组进行序列化 |
unserialize() |
将一个序列化的值进行反序列化 |
__sleep() |
魔术方法,当序列化一个对象的时候自动调用 |
__wakeup |
魔术方法,当反序列化一个对象的时候自动调用 |
演示代码:
<?php
//序列化 可以是整数 字符串 数组
//整数
$mub = 10;
//进行序列化
$smub = serialize($mub);
echo $smub; //输出 i:10;
//进行反序列化
$umub = unserialize($smub);
echo $umub; //输出 10
echo '<hr>';
//字符串
$str = '中国万岁';
//序列化
$s_str = serialize($str);
echo $s_str; //输出 s:12:"中国万岁"; s表示string字符串 12表示长度 四个字符表示一个中文
//反序列化
$u_str = unserialize($s_str);
echo $u_str; //输出 中国万岁
echo '<hr>';
//数组
$arr = [80, 'hello', true, null, [12,34]];
//序列化
$s_arr = serialize($arr);
echo $s_arr;
//输出 a:5:{i:0;i:80;i:1;s:5:"hello";i:2;b:1;i:3;N;i:4;a:2:{i:0;i:12;i:1;i:34;}}
//反序列化
$u_arr = unserialize($s_arr);
print_r($u_arr);
//输出 Array
//(
// [0] => 80
// [1] => hello
// [2] => 1
// [3] =>
// [4] => Array
// (
// [0] => 12
// [1] => 34
// )
//
//)
序列化一个对象
```php
<?php
//创建对象
//抽象类
//abstract class Dad
//{
// protected $name = ‘michael’;
// private $salary = 8000;
//}
//
////工作类
//class Son extends Dad
//{
// public $sex = ‘男’;
// protected $age = 40;
// private $isMarried = false;
//// 静态属性
//protected static $nationality = ‘美国/USA’;
////创建一个方法
//public function __get($name)
//{
// return $this->$name;
//}
//}
//
//$son = new Son();
////将序列化后的值保存到文件中
//file_put_contents(‘obj_index.txt’,serialize($son));
注意:序列化后的对象是不带有方法的,只序列化值 所以在反序列化时要引入这个类
//将输出的值保存到文件中 值: O:3:”Son”:5:{s:3:”sex”;s:3:”男”;s:6:”age”;i:40;s:14:”SonisMarried”;b:0;s:7:”name”;s:7:”michael”;s:11:”Dadsalary”;i:8000;}
// 带*表示私有属性private 带类名 Son。/Dad 表示protected属性
将类保存到另一个文件中 引入进来
//强制引入
require ‘for_index.php’;
//然后引入序列化文件并反序列化
$obj = unserialize(file_get_contents(‘obj_index.txt’));
//var_dump($obj);
//输出 object(Son)#1 (5) { [“sex”]=> string(3) “男” [“age”:protected]=> int(40) [“isMarried”:”Son”:private]=> bool(false) [“name”:protected]=> string(7) “michael” [“salary”:”Dad”:private]=> int(8000) }
//访问一下
$son = new Son();
echo $son->sex; //输出 男
关于序列化后的值 解读 :
![QQ截图20200510165422.png](https://i.loli.net/2020/05/10/B4tSikgDnAVseOv.png)
## 1.2 魔术方法 序列化
```php
<?php
// __sleep() __wakeup()
//创建对象
//抽象类
abstract class Dad
{
protected $name = 'michael';
private $salary = 8000;
}
//工作类
class Son extends Dad
{
public $sex = '男';
protected $age = 40;
private $isMarried = false;
// 静态属性
protected static $nationality = '美国/USA';
//创建一个方法
public function __get($name)
{
return $this->$name;
}
//魔术方法 将在序列化所属类时 自动调用
public function __sleep()
{
// 只允许将以下值进行序列化
return['name','sex','isMarried'];
}
//魔术方法 将在反序列化所属类时自动调用
public function __wakeup()
{
// 改变原序列化的值
$this->name = 'kaiwen';
$this->sex = '女';
$this->isMarried = true;
}
}
$son = new Son();
//进行序列化
$s_son = serialize($son);
echo $s_son;
//输出 O:3:"Son":3:{s:7:"*name";s:7:"michael";s:3:"sex";s:3:"男";s:14:"SonisMarried";b:0
echo '<hr>';
//进行反序列化
var_dump(unserialize($s_son));
//输出 object(Son)#2 (5) { ["sex"]=> string(3) "女" ["age":protected]=> int(40) ["isMarried":"Son":private]=> bool(true) ["name":protected]=> string(6) "kaiwen" ["salary":"Dad":private]=> int(8000) }
1.3 利用序列化连接数据库
<?php
//创建 链接类
class Connection
{
protected $link;
private $params = [];
// 构造方法传参
public function __construct($dsn, $username, $password)
{
$this->params['dsn'] = $dsn;
$this->params['username'] = $username;
$this->params['password'] = $password;
// 转发
$this->connect();
}
// 创建链接
public function connect()
{
// 展开 返回数组中所有的值 不保留键名 array_values
$this->link = new PDO(...array_values($this->params));
}
// 序列化的时候返回连接参数
public function __sleep()
{
return ['params'];
}
// 反序列化时自动重新连接
public function __wakeup()
{
$this->connect();
}
// 创建 查询方法
public function select($sql)
{
return $this->link->query($sql)->fetchAll(PDO::FETCH_ASSOC);
}
}
//传参
$db = new Connection('mysql:host=localhost;dbname=php11.edu','php11.edu','php11.edu');
//查询并打印
print_r($db->select('SELECT * FROM `staffs` LIMIT 5'));
//输出Array ( [0] => Array ( [id] => 1 [name] => 侯亮平 [age] => 40 [sex] => 1 [position] => 反贪局长 [mobile] => 13576543210 [hiredate] => 851356800 ) [1] => Array ( [id] => 2 [name] => 祁同伟 [age] => 46 [sex] => 1 [position] => 公安厅长 [mobile] => 13023456110 [hiredate] => 1420041600 ) [2] => Array ( [id] => 3 [name] => 高育良 [age] => 57 [sex] => 1 [position] => 政法书记 [mobile] => 15678789933 [hiredate] => 981734400 ) [3] => Array ( [id] => 4 [name] => 李达康 [age] => 51 [sex] => 1 [position] => 市委书记 [mobile] => 13088856110 [hiredate] => 1336838400 ) [4] => Array ( [id] => 5 [name] => 沙瑞金 [age] => 56 [sex] => 1 [position] => 省委书记 [mobile] => 18956490987 [hiredate] => 1179158400 ) )
echo '<hr>';
//序列化一下
$str = serialize($db);
echo $str;
//输出 {s:18:"Connectionparams";a:3:{s:3:"dsn";s:37:"mysql:host=localhost;dbname=php11.edu";s:8:"username";s:9:"php11.edu";s:8:"password";s:9:"php11.edu";}}
echo '<hr>';
//反序列化
$obj = unserialize($str);
//会重新返回一个对象,所以要重新链接才能查询 使用__wakeup
//查询
print_r($db->select('SELECT * FROM `staffs` LIMIT 2'));
//输出 Array ( [0] => Array ( [id] => 1 [name] => 侯亮平 [age] => 40 [sex] => 1 [position] => 反贪局长 [mobile] => 13576543210 [hiredate] => 851356800 ) [1] => Array ( [id] => 2 [name] => 祁同伟 [age] => 46 [sex] => 1 [position] => 公安厅长 [mobile] => 13023456110 [hiredate] => 1420041600 ) )
2. 对象的复制与__clone
克隆
对象是引用类型,将对象作为值,复制给其他变量时,遵循’引用传递’的规则
<?php
//创建一个类
class User
{
public $name = 'michael';
public $age = 40 ;
// 创建魔术方法 该类被克隆是时调用
public function __clone()
{
// 改一下age值 当被克隆时 返回这个值
$this->age = 80;
}
}
//先看一下引用
$user1 = new User();
//引用 等于起别名
$user2 = $user1 ;
//改一下值
$user2->name = 'kaiwen';
echo $user1->name; //输出 kaiwen
//克隆 等于克隆一个新对象
$user3 = clone $user1;
echo $user3->name,'---',$user3->age;
// 输出 kaiwen---80
3. __tostring()
把对象当成字符串打印时自动调用
<?php
// __tostring() 当所在类被打印时自动调用
//创建 类
class User
{
public function __toString()
{
// 返回方法名
return __METHOD__;
}
}
$user = new User();
//直接打印类会报错,使用魔术方法后可以正常打印
echo $user;
//使用魔术方法后 正常输出 User::__toString
echo '<hr>';
4. 异常类
Exception
: 三个属性 十个方法
属性 异常类外部不可访问 内部子类可以访问
|属性名|描述|
|-|-|
|protected string $message ;|异常消息内容|
|protected int $code ;|异常代码|
|protected string $file ;|抛出异常的文件名|
|protected int $line ;|抛出异常在该文件中的行号|
方法 final 最终方法 不允许被重写 不允许用户自定义
|方法名|描述|
|-|-|
|public __construct ([ string $message = "" [, int $code = 0 [, Throwable $previous = NULL ]]] )
| — 异常构造函数|
|final public getMessage ( void ) : string
| — 获取异常消息内容|
|final public getPrevious ( void ) : Throwable
| — 返回异常链中的前一个异常|
|final public getCode ( void ) : int
| — 获取异常代码|
|final public getFile ( void ) : string
| — 创建异常时的程序文件名称|
|final public getLine ( void ) : int
| — 获取创建的异常所在文件中的行号|
|final public getTrace ( void ) : array
| — 获取异常追踪信息|
|final public getTraceAsString ( void ) : string
| — 获取字符串类型的异常追踪信息|
|public __toString ( void ) : string
| — 将异常对象转换为字符串|
|final private __clone ( void ) : void
| — 异常克隆|
public __toString
可以在子类中对这个方法进行自定义 这样就可以自定义出错的提示信息返回格式 美化private __clone ( void ) : void
私有方法 禁止在外部克隆
演示代码
<?php
//异常类的典型应用
//自定义异常语句
class ErrException extends Exception
{
public function __toString()
{
return '邮箱格式错误';
}
}
//检测一个值是否正确
$email = '123qq.com';
try {
if (filter_var($email,FILTER_VALIDATE_EMAIL) === false){
throw new ErrException($email);
}
} catch (ErrException $e){
echo $e;
}
5. 匿名类
<?php
//匿名类
//创建一个类
class User
{
public function name($name)
{
return 'hello' . $name;
}
}
//常规访问
$user = new User();
echo $user->name('中国');
//如果这个对象只调用一次
echo (new User())->name('中国');
//如果这个类只用一次
echo(new class {
public function Demo($name){
return 'ddd'.$name;
}
})->Demo('撒旦');
6. 总结
个人感觉匿名类用处不大,简单了解一下ok,加入这个类真的只用一次 不如直接用匿名函数解决