实现__isset()和__unset()访问拦截操作
isset()和unset()访问非公开成员就会调用类中的__isset()和__unset()
<?php
class Demo{
public $name = 'tlilam';
protected $password = '123';
private $email = 'tlilam@php.cn';
// 当外部使用isset函数,检测类中非公开成员就会调用这个方法,在类内部检测成员是否存在,返回值
public function __isset($n){
return isset($this->$n);
}
public function __unset($n){
unset($this->$n);
}
}
$demo = new Demo();
// 公开成员可以直接使用isset函数
var_dump( isset($demo->name));
// isset()函数检测非公开成员,调用类中的__isset()方法
var_dump( isset($demo->password) );
var_dump( isset($demo->email) );
echo '<hr/>';
// 打印类的属性
print_r( $demo );
// 公开成员可以直接被删除
unset($demo->name);
print_r( $demo );
// unset()函数删除非公开成员,调用类中的__unset方法
unset($demo->email);
print_r( $demo );
__callStatic()事件委托,实现简单的数据表操作器
__call()、__callStatic()没有差别,只是一个是拦截普通方法,一个拦截静态方法
<?php
// 实际操作类
class Query{
protected $db;
protected $table;
protected $field = '*';
protected $limit;
protected $where;
// 构造方法: 调用connect方法连接数据库
public function __construct($dsn, $username, $password)
{
$this->connect($dsn, $username, $password);
}
// 使用PDO连接后赋值给属性db
protected function connect($dsn,$username,$password){
$this->db = new PDO($dsn,$username,$password);
// var_dump($this->db);
}
// 属性赋值并返回赋值后的实例
public function table($table){
$this->table = $table;
return $this;
}
public function field($field){
$this->field = $field;
return $this;
}
public function limit($limit){
$this->limit = $limit;
return $this;
}
public function where($id='id',$key=0,$operator='='){
$this->where = $id.$operator.'\''.$key.'\'';;
return $this;
}
// 得到SQL语句
public function getsql($v,$v1='',$v2=''){
switch($v){
case 'insert':
$string = sprintf('INSERT %s ( %s ) VALUES ( %s );', $this->table, $v1,$v2);
break;
case 'update':
$string = sprintf('UPDATE %s SET %s WHERE %s ;', $this->table, $v1,$this->where);
break;
case 'delete':
$string = sprintf('DELETE FROM %s WHERE %s;', $this->table, $this->where);
break;
case 'select':
$string = sprintf('SELECT %s FROM %s %s %s',$this->field, $this->table,
$this->where?"WHERE $this->where":null,
$this->limit?"LIMIT $this->limit ":'');
break;
}
return $string;
}
// 下面是真正的执行操作
// 查询操作
public function select(){
// return $this->getsql('select');
return $this->db->query( $this->getsql('select') )->fetchAll(PDO::FETCH_ASSOC);
}
// 插入操作
public function insert($inserts = []){
// 将键值取出拼接成SQL的字段名
$i1 = '`'. implode('`,`',array_keys($inserts)) . '`';
// 将值拼接成SQL的字段值
$i2 = '\''. implode('\',\'',$inserts) . '\'';
// 执行SQL插入
return $this->db->exec($this->getsql('insert',$i1,$i2));
}
// 更新操作
public function update($args=[]){
$string ='';
foreach($args as $key=>$value){
$string.= $key.'=\''.$value.'\',';
}
// return rtrim($string,',');
// return $this->getsql('update',rtrim($string,','));
return $this->db->exec( $this->getsql('update',rtrim($string,',')) );
}
// 删除操作,可以使用where,也可以在delete()放入ID值
public function delete( $id=null,$pk='id' ){
if( !$this->where ){
$this->where = $pk.'=\''.$id.'\'';
}
// return $this->getsql('delete');
return $this->db->exec( $this->getsql('delete') );
}
}
// 数据库类,方法委托
class DB{
// 进行静态方法拦截,进行事件委托给Query类
public static function __callStatic($name,$args=[]){
$dsn = 'mysql:host=localhost;dbname=phpedu';
$username='root';
$password='root';
$query = new Query($dsn,$username,$password);
// 使用回调方式,调用Query类
return call_user_func_array([$query,$name],$args);
}
}
// 实际使用
// 查询操作 返回关联数组结果集
$users = DB::table('users')->where('id','3','>')->select();
// $users = DB::table('users')->field('id,name,email')->where('id','3','>')->select();
// $users = DB::table('users')->field('id,name,email')->where('id','3','>')->limit(2)->select();
// 插入操作 返回插入记录条数
// $users = DB::table('users')->insert( ['name'=> '小燕子','email'=>'xyz@php.cn', 'password'=>sha1('123456')] );
// 删除操作 返回受影响行数
// $users = DB::table('users')->where('id',2)->delete( );
// $users = DB::table('users')->delete( 14 );
// 更新操作 返回受影响行数
// $users = DB::table('users')->where('id','10')->update(['name'=> '金锁3','email'=>'js3@php.cn', 'password'=>sha1('333')]);
// 打印执行结果
print_r($users);
__sleep()与__wakeup()实例使用
__sleep()是被序列化时调用,__wakeup()被反序列化时调用
<?php
// 自定义实例实现序列化时的__sleep()与__wakeup()功能
class DbConnection
{
// 连接参数
private $params = [];
// 连接对象
private $link = null;
// 初始化操作
public function __construct($dsn, $username, $password)
{
$this->params['dsn'] = $dsn;
$this->params['username'] = $username;
$this->params['password'] = $password;
$this->connect();
}
// 连接数据库赋值给属性link
public function connect()
{
// 实例化到属性link 后续操作在link操作
$this->link = new PDO(...array_values($this->params));
}
// 对象被序列化时调用,返回数组
public function __sleep():array
{
// 序列化前将密码进行字符混合加密
$this->params['password'] = base64_encode($this->params['password'].'tlilam');
// 必须返回数组,里面的元素是返回的属性名称
return ['params'];
}
// 对象被反序列化时调用,不需要返回值
public function __wakeUp()
{
// 进行解码,然后去除掉混入字符
$this->params['password'] = str_replace('tlilam','',base64_decode($this->params['password']));
$this->connect();
// 不需要返回值,进行操作即可
}
// 查询操作
public function select($sql)
{
return $this->link->query($sql)->fetchAll(PDO::FETCH_ASSOC);
}
}
// 参数赋值并且进行实例化
$dsn = 'mysql:host=localhost;dbname=phpedu';
$username='root';
$password='root';
$db = new DbConnection($dsn, $username, $password);
// 序列化实例$db
$str = serialize($db);
// 打印序列化后的字符串
echo $str;
// 反序列化对象字符串
$ss = unserialize($str);
// 打印反序列化后的ss是一个对象
print_r($ss);
// 测试反序列化后的SS执行select方法
print_r($ss->select('select * from users limit 3'));