对象序列化与实战案例
1、案例演示对象序列化
<?php
// 对象序列化与__sleep(), __wakeup()
// 1. 序列化
echo serialize(100). '<br>';
echo serialize('php.cn'). '<br>';
echo serialize([80, 'hello', true, null, [12,34]]). '<br>';
echo '<hr>';
// 2. 序列化一个对象呢?
abstract class Dad
{
protected $name = '胡八一';
private $salary = 7788;
}
class Son extends Dad
{
public $sex = '男';
protected $age = 40;
private $isMarried = false;
protected static $nationality = '中国/CHINA';
public function __get($name)
{
return $this->$name;
}
public function __sleep(): array
{
return ['name', 'sex', 'isMarried'];
}
public function __wakeup()
{
$this->age = 35;
$this->sex = '保密';
}
}
$son = new Son();
// file_put_contents('obj_seria.txt', serialize($son));
// $str = file_get_contents('obj_seria.txt');
// echo $str;
// $obj = unserialize($str);
// echo '<hr>';
// var_dump($obj);
// echo '<hr>';
echo serialize($son);
echo '<hr>';
$str = serialize($son);
var_dump(unserialize($str));
2、案例演示sleep(), wakeup()
<?php
// __sleep(), __wakeup()
// 创建数据库连接类,
// 1. 实例化的时候, 自动连接,并创建连接对象
// 2. 外部对连接对象序列化时, 获取到连接参数
// 3. 反序列化的时候, 自动重新连接数据库
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()
{
$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=phpedu', 'root','root');
print_r($db->select('select * from users limit 3'));
echo '<hr>';
$str = serialize($db);
echo $str , '<br>';
// 反序列化, 会重新返回一下新对象,所以要重新连接才能查询
$obj = unserialize($str);
print_r($obj->select('select * from users limit 3'));
3、对象复制与__clone
<?php
// 对象复制与__clone
// 对象是引用类型,将对象做为值, 赋值给其它变量的时候, 遵循"引用传递"的规则
class User
{
public $name = '朱老师';
public $points = 1000;
public function __clone()
{
$this->points = 0;
}
}
$user1 = new User();
// 引用
$user2 = $user1;
// $user2 就是 $user1的别名
$user2->name = '王老师';
echo $user1->name;
echo '<hr>';
// clone 克隆出一个全新对象
$user3 = clone $user1;
echo $user3->name, '----', $user3->points;
4、自定义异常类, 处理用户登录与验证, 模拟就可以不用表单了
<?php
// __toString():把对象当成字符串打印的时候调用
class User
{
public function __toString()
{
return __METHOD__;
}
}
$user = new User();
echo $user;
echo '<hr>';
// 异常类的典型应用
try {
// 这里的是用户代码,可能会出错
throw new Exception('验证失败');
} catch (Exception $e) {
echo $e->getMessage();
}
echo '<hr>';
try {
$db = new PDO('mysql:host=localhost;dbname=phpedu', 'root', 'root');
} catch (Exception $e) {
echo $e->getMessage();
}
echo '<hr>';
// 自已创建一个针对数据库操作的异常类
class DbException extends Exception
{
public function __toString()
{
return <<< DBE
<style>
table {border-collapse: collapse;border:1px solid black;text-align: center;}
td {border:1px solid black;padding: 5px;}
tr:first-of-type {background-color:#eee;}
tr:last-of-type td {color: coral;}
</style>
<table>
<tr><td>代码</td><td>信息</td><td>文件</td><td>行号</td></tr>
<tr><td>$this->code</td><td>$this->message</td><td>$this->file</td><td>$this->line</td></tr>
</table>
DBE;
}
}
try {
$db = new PDO('mysql:host=localhost;dbname=phpedu', 'root', 'root');
throw new DbException('连接成功', 29);
} catch (DbException $e) {
echo $e;
}
5、案例演示匿名类?
<?php
// 匿名类
class Demo
{
public function hello($name)
{
return 'Hello ' . $name;
}
}
// 1. 传统
$demo = new Demo();
echo $demo->hello('小树小站') , '<hr>';
// 2. 如果这个对象只用一次, 可以将实例化与成员访问二合一
echo (new Demo())->hello('小树小站') , '<hr>';
// 3. 如果这个类只用一次, 索性将类, 类的实例化,成员访问三合一
echo (new class
{
public function hello($name)
{
return 'Hello ' . $name;
}
})->hello('小树小站') , '<hr>';
// 用在什么地方?
// 经典场景1: 实现接口部分功能, 仅用在当前项目中
interface iDb
{
public function __construct(...$params);
}
// 你的项目是使用PDO操作数据库, 但是当前测试脚本使用的是mysqli做一些简单查询, 可以使用匿名类实现这个接口
// 用mysqli做一次查询
$res = (new class ('mysql:host=localhost;dbname=phpedu', 'root', 'root') implements iDb {
private $db = null;
public function __construct(...$params)
{
$this->db = new PDO($params[0],$params[1],$params[2]);
}
public function select($where="")
{
$where = empty($where) ? '' : ' WHERE ' . $where;
return $this->db
->query('SELECT id,name,email FROM users ' . $where . ' LIMIT 4')
->fetchAll(PDO::FETCH_ASSOC);
}
}
)->select();
printf('<pre>%s</pre>', print_r($res, true));
// 经典场景2: 用在函数/方法的参数中
function get(object $user, string $name)
{
return $user->write($name);
}
echo get(new class (){
public function write($name)
{
return 'Hello Hello ' . $name;
}
}, 'zhangsan');
课程学习小结
本次课程老师从浅显易懂的实例出发,详解介绍了对象序列化与实战案例相关内容,通过回看视频及讲义代码,尽力理解老师列举的步步递进的层次关系与应用场景, 并通过修改实现部分代码对照差异之处,感觉收获较大。