Blogger Information
Blog 11
fans 0
comment 0
visits 8540
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
使用回调函数call_user_func_array()实现数据库链式操作的原理一2019年3月4日22点10分
澜海的博客
Original
1026 people have browsed it

作业:

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

    }
}

运行实例 »

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


Correction status:qualified

Teacher's comments:
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post