魔术方法:
* 1.类中以双下划线开头的方法,这是由系统内置的,用户方法不要用双下划线开头;
* 2.魔术方法由系统在一定条件下自动触发调用,用户不能直接调用;
* 注意:将类中的私有成员前面添加单下划线是一个好习惯;
* 例如: private $_salary; private function _listUsers(){...}
* 使用魔术方法实现几个对象访问拦截器
* 所谓拦截器:就是对用户的一些错误或非法访问进行检测和控制。
* 之前我们学过__get($fieldName)和__set()这是二个最常用的拦截器
* 现在我们再学习一组: __isset($fieldName)和__unset($fieldName)
1. __isset():当在类外检测一个类属性是否存在时会自动调用
2. __unset():当在类外销毁一个类属性时会自动调用
<?php class Demo { private $name = 'peter'; private $email = 'peter@php.cn'; //当在类外使用isset()检测某个属性是否存在时自动调用 public function __isset($name) { //对访问进行过滤:如果属性名是'name',返回false,否则允许访问 //即除了'name'属性外的其它属性允许外部进行isset()检测 return ($name=='name') ? false : true; } } //实例化 Demo 类 $obj = new Demo; //检测$obj中是否有name属性,返回 echo isset($obj->name)?'存在':'不存在'; echo '<hr>'; //检测$obj中是否存在email属性,返回存在,因为类中__isset()返回true echo isset($obj->email)?'存在':'不存在'; //在外部使用unset()来销毁类属性
点击 "运行实例" 按钮查看在线实例
类方法重载: __call()和__callStatic()
1.call($name,$array): 当类外访问一个不存在的方法时自动调用
2.callStatic($name,$array):当类外访问一个不在静态上下文中的方法时自动调用
用途:
1.防止访问不存在的方法时报错;
2.其实最有用的应用场景是动态生成一个可访问的方法,实现方法的跨类调用
先创建一个数据库查询类: Query.php
<?php //数据库查询类 class Query { private $pdo = null; //数据库连接对象 private $stmt = null; //预处理语句对象 private $table = ''; //数据表名 private $field = ''; //字段列表 private $where = ''; //查询条件 private $order = ''; //排序规则 //构造方法: 初始化连接对象 public function __construct($pdo) { $this->pdo = $pdo; } //设置数据表名 public function table($table) { $this->table = $table; //***返回当前对象,便于链式调用后面的方法 return $this; } //设置字段列表 public function field($field) { $this->field = $field; //***返回当前对象,便于链式调用后面的方法 return $this; } //设置查询条件 public function where($where) { $this->where = $where; //***返回当前对象,便于链式调用后面的方法 return $this; } //设置排序规则 public function order($order) { $this->order = $order; //***返回当前对象,便于链式调用后面的方法 return $this; } //单条查询语句: 仅返回符合条件结果集中的第一条记录 public function find() { //简化查询参数 $table = $this->table; $field = $this->field; $where = $this->where; //设置SQL语句 $sql = "SELECT {$field} FROM {$table} {$where} LIMIT 1;"; // die($sql); //创建预处理语句对象 $this->stmt = $this->pdo->prepare($sql); //执行预处理查询 $this->stmt->execute(); //返回预处理查询的结果集(单条查询返回一维数组) return $this->stmt->fetch(PDO::FETCH_ASSOC); //***注: find是最终方法,负责执行SQL查询,不用返回当前对象$this } //多条查询语句 public static function select($db,$table,$field,$where,$order) { //设置SQL语句 $sql = "SELECT {$field} FROM {$table} {$where} {$order};"; // die($sql); //为了简化代码,这里不再使用PDO来处理,直接使用原生的MySQLi来完成查询 $res = mysqli_query($db, $sql); return mysqli_fetch_all($res); //***注: select是最终方法,负责执行SQL查询,不用返回当前对象$this } }
点击 "运行实例" 按钮查看在线实例
调用测试源码
<?php //导入数据库查询类 spl_autoload_register(function($className){ require './class/'.$className.'.php'; }); class Db { public $pdo = null; public function __construct($host='localhost',$user='root',$pass='root',$dbname='php') { try { $this->pdo = new PDO("mysql:host={$host};dbname={$dbname}",$user,$pass); } catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage(); } } //当访问一个不存在的动态方法时会自动触发 public function __call($name,$args) { $query = new Query($this->pdo); return call_user_func_array([$query,$name], $args); } //当访问一个不存在的静态方法时会自动触发,注意这个方法必须声明为public static public static function __callStatic($name,$args) { return call_user_func_array(['Query',$name], $args); } } //实例化Db $db = new Db('localhost','root','root','php');
点击 "运行实例" 按钮查看在线实例
任务一: 使用__call()实现动态方法的跨类调用
* 1. 从Db类中去动态的执行Query类中的方法
* 2. 返回符合条件的单条记录
* 3. 使用PDO预处理对象完成
<?php /**接上**/ //实例化Db $db = new Db('localhost','root','root','php'); //设置查询参数,因为是单条查询,无须设置排序规则$order $table = 'staff'; //表名 $field = 'name,age,salary '; //字段列表 $where = 'WHERE age < 20 '; //查询条件 //链式调用Query查询类中的find()方法来完成查询 $row = $db->table($table)->field($field)->where($where)->find(); //查看单条查询结果 echo '<pre>'.print_r($row,true).'</pre>';
点击 "运行实例" 按钮查看在线实例
任务二: 使用__callStatic()实现静态方法的跨类调用
* 1. 从Db类静态调用Query中的静态方法
* 2. 返回符合条件的多条记录
* 3. 使用PDO预处理对象完成
<?php /**同上接上**/ //设置查询参数,增加一个排序规则$order $table = 'staff'; //表名 $field = 'name,age,salary '; //字段列表 $where = 'WHERE age < 25 '; //查询条件 $order = 'ORDER BY age DESC'; //链式调用Query查询类中的select()方法来完成查询 //为简化代码,使用原生MySQLi来完成查询 $db = mysqli_connect('localhost', 'root', 'root', 'php'); $rows = Db::select($db,$table,$field,$where,$order); //查看单条查询结果 echo '<pre>'.print_r($rows,true).'</pre>';
点击 "运行实例" 按钮查看在线实例