博客列表 >使用回调函数call_user_func_array()实现数据库链式操作的原理一2019年3月4日22点10分

使用回调函数call_user_func_array()实现数据库链式操作的原理一2019年3月4日22点10分

澜海的博客
澜海的博客原创
2019年03月09日 17:44:181023浏览

作业:

自己封装一个数据库常用操作类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);

    }
}

运行实例 »

点击 "运行实例" 按钮查看在线实例


声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议