作业:
自己封装一个数据库常用操作类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); } }
点击 "运行实例" 按钮查看在线实例