魔术方法:
* 1.类中以双下划线开头的方法,这是由系统内置的,用户方法不要用双下划线开头;
* 2.魔术方法由系统在一定条件下自动触发调用,用户不能直接调用;
* 注意:将类中的私有成员前面添加单下划线是一个好习惯;
* 例如:private $_salary; private function _listUsers(){...}
* 使用魔术方法实现几个对象访问拦截器
* 所谓拦截器:就是对用户的一些错误或非法访问进行检测和控制。
* 之前我们学过__get($fieldName)和__set()这是二个最常用的拦截器
* 现在我们再学习一组: __isset($fieldName)和__unset($fieldName)
1. __isset():当在类外检测一个类属性是否存在时会自动调用
2. __unset():当在类外销毁一个类属性时会自动调用
实例
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 '
';
//检测$obj中是否存在email属性,返回存在,因为类中__isset()返回true
echo isset($obj->email)?'存在':'不存在';
//在外部使用unset()来销毁类属性
运行实例 »
点击 "运行实例" 按钮查看在线实例
类方法重载: __call()和__callStatic()
1.call($name,$array): 当类外访问一个不存在的方法时自动调用
2.callStatic($name,$array):当类外访问一个不在静态上下文中的方法时自动调用
用途:
1.防止访问不存在的方法时报错;
2.其实最有用的应用场景是动态生成一个可访问的方法,实现方法的跨类调用
先创建一个数据库查询类: Query.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
}
}
运行实例 »
点击 "运行实例" 按钮查看在线实例
调用测试源码
实例
//导入数据库查询类
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预处理对象完成
实例
/**接上**/
//实例化Db
$db = new Db('localhost','root','root','php');
//设置查询参数,因为是单条查询,无须设置排序规则$order
$table = 'staff'; //表名
$field = 'name,age,salary '; //字段列表
$where = 'WHERE age
//链式调用Query查询类中的find()方法来完成查询
$row = $db->table($table)->field($field)->where($where)->find();
//查看单条查询结果
echo '
'.print_r($row,true).'';
运行实例 »
点击 "运行实例" 按钮查看在线实例
任务二: 使用__callStatic()实现静态方法的跨类调用
* 1. 从Db类静态调用Query中的静态方法
* 2. 返回符合条件的多条记录
* 3. 使用PDO预处理对象完成
实例
/**同上接上**/
//设置查询参数,增加一个排序规则$order
$table = 'staff'; //表名
$field = 'name,age,salary '; //字段列表
$where = 'WHERE age
$order = 'ORDER BY age DESC';
//链式调用Query查询类中的select()方法来完成查询
//为简化代码,使用原生MySQLi来完成查询
$db = mysqli_connect('localhost', 'root', 'root', 'php');
$rows = Db::select($db,$table,$field,$where,$order);
//查看单条查询结果
echo '
'.print_r($rows,true).'';
运行实例 »
点击 "运行实例" 按钮查看在线实例