作业:
自己封装一个数据库常用操作类Query.php
并在自己的代码中进行调用(建议采用链式调用)
仔细消化今晚的数据库链式操作的原理,
重点理解, call_user_func_array()方法的精妙之处
我来研究一下PHP对象链式操作实现原理,什么是链式操作呢?使用jQuery的同学印象应该会很深刻.在jQuery中,我们经常会这样的来操作DOM元素:
$("p").css("color").addClass("selected");
连贯操作看起来的确很酷,也非常的方便代码的阅读.那么在PHP里面是否可以实现呢?答案是肯定的,
在PHP中,我们经常要使用很多函数:
$str = 'abs123 ';
echo strlen(trim($str));
上面代码的作用就是去除字符串两边的空格,然后输出其长度,那么使用链式编程就可以这样来:
$str = 'abs123 ';
echo $str->trim()->strlen();
是不是看着更加的舒服呢?这里主要是利用了PHP面向对象里面方法重载与call_user_func_array()回调函数来配合实现模拟ThinkPHP 的链式调用。
TP中的样例如:
Db::table('think_user')
->where('id',1)
->field('id,name,email')
->select()
DB为数据库操作入口,通过链式调用完成查询
实现原理:当函数调用一个不存在或没有权限的静态方法时调用,通过___callStatic()方法重载 通过设置完成跨类
调用实现链式重载。
实现步骤:
1、建立DB类 类方法:__callStatic()//实现Db::table() 不存在时重载
2、__callStatic( )中的call_user_func_array([对象名,方法],参数) 回调跨类的Query类及方法
3、Query类设置PDO数据连接,
4、通过Query类中的table( ) 、fields( )、where( )、链式方法获取查询参数
5、最终通过select( )方法完成查询
<?php
// 方法重载的应用: 数据库查询的链式操作
// 下面以模拟ThinkPHP5.1框架中的数据库查询构造器为案例,来演示方法重载的精妙之处
require 'Query.php';
class Db
{
// 数据库连接对象
protected static $pdo = null;
// 数据库连接方法, 每次查询时再连接, 实现真正的惰性连接,节省系统开销
public static function connection()
{
// 为简化,这里直接使用字面量参数连接数据库,真实项目中应该将参数放在配置文件中
self::$pdo = new PDO('mysql:host=localhost;dbname=php','root','root');
}
// 这是查询类操作的入口, 通过静态魔术方法进行跳转,实现对象方法的跨类调用
public static function __callStatic($name, $arguments)
{
// 创建pdo对象,并连接数据库
self::connection();
// 实例化查询类,将连接对象做为参数
$query = new Query(self::$pdo);
// 执行查询类Query中的对象方法, 注意参数是数组,我只需要第一个参数:表名, 所以加了索引键名
return call_user_func_array([$query,$name],[$arguments[0]]);
}
}
// 客户端的链式调用
// 以Db类做入整数数据库操作的入口, SQL语句的各个部分用对象方法提供
// 链式操作是现代PHP框架的基础,非常有用
$staffs = Db::table('staff')
->field('id,name,position,mobile')
->where('id > 5')
->limit(5)
->select();
// 遍历查询结果
foreach ($staffs as $staff) {
print_r($staff); echo '<br>';
}点击 "运行实例" 按钮查看在线实例
链式调用外部类文件Query 功能 链式调用的各个方法实现和参数获取
<?php
// 数据库查询类
class Query
{
// 连接对象
public $pdo = null;
// 数据表名
public $table = '';
// 字段列表
public $field = '';
// 查询条件
public $where = '';
// 显示数量
public $limit = 0;
// 构造方法,初始化连接对象
public function __construct($pdo)
{
// 连接对象是对象方法的共享属性
$this->pdo = $pdo;
}
// 调用表名
public function table($tablName)
{
$this->table = $tablName;
// 返回当前对象,便于链式调用该对象的其它方法
return $this;
}
// 设置查询字段
public function field($fields)
{
$this->field = $fields;
return $this; //当前Query类的实例对象
}
// 设置查询条件
public function where($where)
{
$this->where = $where;
return $this;
}
// 设置显示数量
public function limit($limit)
{
$this->limit = $limit;
return $this;
}
// 创建SQL查询语句对象,并返回查询结果
public function select()
{
// 查询条件分开设置, 可以确保链式方法独立
$fields = empty($this->field) ? '*' : $this->field;
$where = empty($this->where) ? '' : ' WHERE '.$this->where;
$limit = empty($this->limit) ? '' : ' LIMIT '.$this->limit;
// 接装SQL语句
$sql = 'SELECT '.$fields.' FROM '.$this->table. $where . $limit;
// 预处理查询
$stmt = $this->pdo->prepare($sql);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
}点击 "运行实例" 按钮查看在线实例
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号