1.__get(),__set(),__isset(),__unset(),__call()等魔术方法详解
<?php /** * Created by PhpStorm. * User: Administrator * Date: 2019/10/10 * Time: 15:18 */ namespace _1008; class Demo { private $name; private $sex; protected $age; public function __construct($name,$sex,$age) { $this->name=$name; $this->sex=$sex; $this->age=$age; } /** * 访问类中的属性时,不存在,或者说无权,自动调用展示 * @param $name * @return mixed */ public function __get($name) { return $this->name; } /** * 对类中的私有属性或者受保护的属性进行设置的时候,自动进行调用 * @param $name 属性名 * @param $value 属性值 * @return mixed */ public function __set($name, $value) { return $this->$name=$value; } /**当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。 * @param $name * @return bool */ public function __isset($name) { return isset($this->$name); } public function __unset($name) { unset($this->$name); echo '删除成功!'; } public function __call($name, $arguments) { echo '方法:'.$name.'在类中不存在'.'<br>'.'参数为:'.'<pre/>'.print_r($arguments,true); } } $obj=new Demo('小明','男','20'); echo '__get()魔术方法结果:'.'<br>'; echo $obj->name; //结果 小明 echo '<hr>'; echo '__set()魔术方法结果:'.'<br>'; echo $obj->name='小花'; //结果 小花 echo '<hr>'; echo '__isset()魔术方法结果:'.'<br>'; var_dump(isset($obj->name)); //结果 bool(false) echo '<hr>'; echo '__unset()魔术方法结果:'.'<br>'; unset($obj->name); //结果 删除成功 echo '<hr>'; echo '__call()魔术方法结果:'.'<br>'; echo ($obj->add('666')); //结果 方法:add在类中不存在,参数为666 echo '<hr>';
总结:
__set: 类的外部对类的内部的成员进行写操作,类的成员无权限的情况下自动调用
__get: 当在类的外部访问类的属性,该属性不存在,或者无权限的情况下,自动进行调用
__isset: 判断类的类部,有无某个成员的存在.自动调用
__unset: 删除类的类部中的成员,自动调用
__call: 访问类中不存在或者无权限的方法.自动调用
__callStatic: 访问类中不存在或者无权限的静态方法,自动调用
方法重载,与链式调用实例
代码如下
Query类
<?php namespace Query; class Query { public $pdo = null; public $table; public $fields = '*'; public $where; public $limit; public function __construct($pdo) { $this->pdo = $pdo; } public function table($table) { $this->table = $table; return $this; } public function fields($fields) { $this->fields = empty($fields) ? '*' : $fields; return $this; } public function where($where = '') { $this->where = empty($where) ? $where : 'WHERE'.$where; return $this; } public function limit($limit) { $this->limit = empty($limit) ? $limit : ' LIMIT '. $limit; return $this; } public function select($debug='') { $sql = 'SELECT ' . $this->fields . ' FROM ' . $this->table . $this->where . $this->limit; $stmt = $this->pdo->prepare($sql); $stmt->execute(); if($debug===1)$stmt->debugDumpParams(); return $stmt->fetchAll(\PDO::FETCH_ASSOC); } }
DB类
<?php namespace Db; require './Query.php'; class DB { protected static $pdo = null; public static function connect() { $dsn='mysql:host=127.0.0.1;dbname=test'; self::$pdo = new \PDO($dsn, 'root', 'root'); } public static function __callStatic($name, $arguments) { self::connect(); $query = new \Query\Query(self::$pdo); return call_user_func_array([$query, $name],$arguments); } } //示例 $info = DB::table('test') ->fields('username') ->where('') ->limit(5) ->select(); echo '<pre/>'; var_dump($info);
实现原理总结:
__callStatic 魔术方法 可以使得在调用内中不存在的静态方法的时候,自动调用该静态方法
call_user_func_array 调用回调函数,并把一个数组参数作为回调函数的参数
1.DB::table('test')时, DB类中无table静态方法,调用__callStatic方法,
2.将pdo连接对象传入Query类中,实例化Query类,
3.通过call_user_func_array 回调 Query类中的table方法,传入对应参数
4.Query类通过传递的参数不断的给Query类的属性赋值,最终通过select方法构建SQL进行数据库查询,并返回查询结果