博客列表 >编程: 使用方法重载与call_user_func_array()模拟TP框架的链式查询0904

编程: 使用方法重载与call_user_func_array()模拟TP框架的链式查询0904

郭稳重啊的博客
郭稳重啊的博客原创
2018年09月07日 12:38:52749浏览

0904作业

作业1:编程: 使用方法重载与call_user_func_array()模拟TP框架的链式查询

实例

<?php
/**
 * 数据库查询类
 */

class Query
{
    // 保存sql语句中的各个组成部分
    // SELECT 字段列表 FROM 表名 WHERE 条件
    private $sql = [];

    // 数据库的连接对象
    private $pdo = null;

    //构造方法: 连接数据库
    public function __construct()
    {
        // 连接数据库并返回pdo对象
        $this->pdo = new PDO('mysql:host=127.0.0.1;dbname=php','root','root');
    }
    // table()获取sql语句的表名
    public function table($table)
    {
        $this->sql['table'] = $table;
        return $this;  //返回当前类实例对象,便于链式调用该对象的其它方法
    }

    // fields()获取sql语句的字段列表
    public function fields($fields)
    {
        $this->sql['fields'] = $fields;
        return $this;
    }

    // where()获取sql语句的查询条件
    public function where($where)
    {
        $this->sql['where'] = $where;
        return $this;
    }

    //执行查询,是一个终级方法
    public function select()
    {
        //拼装SELECT查询语句
        $sql = "SELECT {$this->sql['fields']} FROM {$this->sql['table']} WHERE {$this->sql['where']}";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

}

运行实例 »

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

实例

<?php
/**
 * 方法重载的实战案例: 模拟ThinkPHP5.1中的数据库链式操作
 * 用方法重载实现方法跨类调用
 */
echo '<h3 style="text-align: center">编程1:方法重载的实战案例: 模拟ThinkPHP5.1中的数据库链式操作</h3 style>'.
// Db::table()->fields()->where()->select();
require 'Query.php';
// 数据库操作的入口类
class Db
{
    public static function __callStatic($name, $arguments)
    {
        //call_user_func_array([类名, 方法],[])//执行类中的静态方法static
        //call_user_func_array([对象, 方法],[])//执行对象方法
        return call_user_func_array([(new Query()),$name],$arguments);
    }
}

$result = Db::table('staff')
            ->fields('id,name,age,salary')
            ->where('age> 40 ')
            ->select();
//print_r($result);
// 用表格将查询结果格式化输出
$table = '<table border="1" cellpadding="5" cellspacing="0" width="60%" align="center">';
$table .= '<caption style="font-size: 1.5rem;margin:15px;">员工信息表</caption>';
$table .= '<tr bgcolor="#90ee90"><th>ID</th><th>姓名</th><th>年龄</th><th>工资</th></tr>';

foreach ($result as $staff) {
    $table .= '<tr align="center">';
    $table .= '<td>'.$staff['id'].'</td>';
    $table .= '<td>'.$staff['name'].'</td>';
    $table .= '<td>'.$staff['age'].'</td>';
    $table .= '<td>'.$staff['salary'].'</td>';
    $table .= '</tr>';
}

$table .= '</table>';
$num = '<p style="text-align: center"> 共计:  <span style="color:red">'.count($result).'</span>   条记录</p>';
echo '<h4 style="text-align: center">查询staff表的id,name,age,salary字段条件是 age> 40</h4 style>'.$table, $num;


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

`JWFXFXJ$~894EF7K0}0N`U.png


2. 问答: 后期静态绑定的原理与使用场景分析
(1).后期静态绑定的原理
答:
1.准确说,后期静态绑定工作原理是存储了在上一个“非转发调用”的类名。
  当进行静态方法调用时,该类名即为明确指定的那个(通常在 :: 运算符左侧部分,本题为two);
2.当进行非静态方法调用时,即为该对象所属的类。
  所谓的“转发调用”(forwarding call)指的是通过以下几种方式进行的静态调用:self::,parent::,static::
  以及 forward_static_call()。可用 get_called_class() 函数来得到被调用的方法所在的类名,
3.static:: 则指出了其范围。该功能从语言内部角度考虑被命名为“后期静态绑定”。
   后期绑定”的意思是说,static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的。
  也可以称之为“静态绑定”,因为它可以用于(但不限于)静态方法的调用。
4.通过官方说明我们知道后期静态绑定的范围是继承范围内,
   也就是我们看到static::A();时想要确定static是谁就从调用这个方法的类的继承链去找。

(2).使用场景分析:
问:若父类one创建一个静态方法A和静态方法B,但你想要用子类two去调用静态方法B,
     本意是想调用子类中已重写的静态方法A,并不想调用父类的方法A,但是在父类却不能正确识别出你的调用者是哪个?
答:
1.子类需要继承父类并将父类中静态方法A进行重写
2.然后需要将父类里面的静态方法B去调用父类的静态方法A,
  父类里面一个方法调用另一个方法时,如果被调用方法是普通方法,则默认使用$this作为调用者;
  如果被调用方法时静态方法,则默认使用类/self::作为调用者。
  这里显然是一个静态方法,所以需要使用self::作为调用者去调用静态方法A
3.后期[运行阶段]进行静态绑定/延迟静态绑定,当我们输出子类two的静态方法B时,但是发现业务逻辑说不当通,
  所以接下来我们需要将self::换成 static::,这里static:: 不再被解析为定义当前方法所在的类,
  而是在实际运行时所计算的,以这样输出的结果业务逻辑就正确了。



















































































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