其它常用魔术方法与实战
一、sleep()与weakup()
__sleep()
用serialize关键字序列化时被自动调用的魔术方法__wakeup()
用unserialize关键字反序列化时被自动调用的魔术方法
案例1:
<?php
//序列化
//echo serialize('孙悟空');
//echo serialize([1,2,3,true,null]);
class User
{
public $name = '遥控飞机';
public $price = 4000;
public $num = 3;
//序列化时自动调用__sleep()魔术方法
public function __sleep():array
{
return ['name','price','num'];
}
//反序列化时自动调用
public function __wakeup()
{
$this->price = 1000;
}
}
$user = new User();
echo serialize($user),'<br>';
//序列化数据的目的是将数据进行传输保存
file_put_contents('obj.txt',serialize($user));
$str = file_get_contents('obj.txt');
echo gettype($str).'<br>';
//反序列化
$obj = unserialize($str);
echo gettype($obj).'<br>';
echo $obj->name . ':价格:' . $obj->price . ',数量:' , $obj->num;
案例2:
<?php
//__sleep()和__wakeup()实战
//自定义数据库连接类
//功能
//1.类实例化,自动连接数据库,一定会生成一个:连接对象
//2.将这个连接对象序列化,获取到连接参数
//3.反序列化,自动重新连接数据库
//连接类
class Connection
{
//数据库连接参数
private $params = [];
//连接对象
private $link;
//构造方法
public function __construct($dsn,$username,$password)
{
//1.连接参数的初始化
$this->params['dsn'] = $dsn;
$this->params['username'] = $username;
$this->params['password'] = $password;
$this->connect();
//2.连接数据库
//$this->link = new PDO(...$this->params);
}
//连接数据库
public function connect()
{
//array_values()把关联数组转换为索引数组
$this->link = new PDO(...array_values($this->params));
}
//将这个连接对象序列化,获取到连接参数
public function __sleep():array
{
return ['params'];
}
//反序列化,自动重新连接数据库
public function __wakeup()
{
$this->connect();
}
public function select($sql)
{
return $this->link->query($sql)->fetchAll(PDO::FETCH_ASSOC);
}
}
$dsn = 'mysql:host=localhost;dbname=tp5';
$username = 'root';
$password = 'wang1111';
$db = new Connection($dsn,$username,$password);
//var_dump($db);
$str = serialize($db);
echo $str.'<hr>';
//print_r(unserialize($str));
print_r($db->select('SELECT * FROM user LIMIT 3'));
echo '<hr>';
//3.反序列化,自动重新连接数据库
$link = unserialize($str);
print_r($link);
二、__toString()
__toString()
方法用于一个类被当成字符串输出时自动调用该魔术方法
<?php
//tostring()
class User
{
public function __toString()
{
return 'Hello';
}
}
//将这个类的实例,当成字符串打印
$user = new User();
echo $user;
class DbException extends PDOException
{
public function __toString()
{
return <<< DBE
<table border="1px">
<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=tp5','root','wang11112');
}catch(PDOException $e){
$error = new DbException('连接错误',1001);
echo $error;
}
三、匿名类
匿名类可以创建一次性的简单对象
可以传递参数到匿名类的构造器,也可以扩展(extend)其他类、实现接口(implement interface),以及像其他普通的类一样使用
<?php
//匿名类的应用场景
//1.实现接口的部分功能
interface iDb
{
public function __construct(...$params);
}
//当前这个接口中的数据连接操作应该支持PDO,mysqli
//mysqlu实现
class My_mysqli implements iDb
{
private $db = null;
public function __construct(...$params)
{
$this->db = new mysqli($params[0],$params[1],$params[2],$params[3]);
echo '数据库连接成功';
}
public function select()
{
return $this->db->query('SELECT * FROM user LIMIT 2')->fetch_all(MYSQLI_ASSOC);
}
}
$mysqli = new My_mysqli('localhost','root','wang1111','tp5');
print_r($mysqli->select());
echo '<hr>';
//匿名类实现
$users = ( new class ('localhost','root','wang1111','tp5') implements iDb{
private $db = null;
public function __construct(...$params)
{
$this->db = new mysqli($params[0],$params[1],$params[2],$params[3]);
echo '数据库连接成功';
}
public function select()
{
return $this->db->query('SELECT * FROM user LIMIT 2')->fetch_all(MYSQLI_ASSOC);
}
})->select();
print_r($users);
echo '<hr>';
//用pdo来实现
class My_pdo implements iDb
{
private $db = null;
public function __construct(...$params)
{
$this->db = new PDO($params[0],$params[1],$params[2]);
echo '数据库连接成功';
}
public function select()
{
return $this->db->query('SELECT * FROM user LIMIT 1')->fetchAll(PDO::FETCH_ASSOC);
}
}
$mypdo = new My_pdo('mysql:host=localhost;dbname=tp5','root','wang1111');
print_r($mypdo->select());
echo '<hr>';
//用匿名类来实现
$users2 = ( new class ('mysql:host=localhost;dbname=tp5','root','wang1111') implements iDb{
private $db = null;
public function __construct(...$params)
{
$this->db = new PDO($params[0],$params[1],$params[2]);
echo '数据库连接成功';
}
public function select()
{
return $this->db->query('SELECT * FROM user LIMIT 2')->fetchAll(PDO::FETCH_ASSOC);
}
})->select();
print_r($users2);
echo '<hr>';
四、学习总结
序列化时自动调用
__sleep()
魔术方法反序列化时自动调用
__wakeup()
魔术方法当echo一个实例化的类时,自动调用
__toString()
魔术方法匿名类,没有名称的类,通常赋值给一个变量