如何实现thinkphp中Db类的方法调用风格?

thinkphp中Db类调用静态方法后紧接着又可以调用非静态方法,这是什么情况?怎么实现的?例如:Db::table("table_name")->where("id=1... thinkphp中Db类调用静态方法后紧接着又可以调用非静态方法,这是什么情况?怎么实现的?
例如:Db::table("table_name")->where("id=10")->find();
我发现Db类中有@method Query where() 请问有什么必然联系吗?
展开
 我来答
软糖kimi
2018-10-04
知道答主
回答量:15
采纳率:0%
帮助的人:5.4万
展开全部

我们先来看下官网对listen的说明:如果开启数据库的调试模式的话,你可以对数据库执行的任何SQL操作进行监听。这无疑很方便我们进行增删改查的调试,以及通过执行的时间进行有效的sql优化,

友情提示:数据库监听要写在执行sql语句的前面,因为只有在调用Db::listen之后的SQL语句才会被监听,调用之前的语句不会被监听。至于为什么我们后面讲!

使用如下方法:

123456

Db::listen(function($sql, $time, $explain){    // 记录SQL    echo $sql. ' ['.$time.'s]';    // 查看性能分析结果    dump($explain);});

有很多小伙伴疑问该方法应该放在哪里?使用之后为什么没有效果,很可能就是提示上所说的那样了,那么接下来我们简单分析一下这个方法!

1、从Db::listen(),可以看出listen是Db中的一个静态方法,那么我们就去找db类

2、从Db类中没有找到该方法,但是我们从use think\db\Connection可以看出,引入了Connection类,我们在这个类找一下这个方法!

12345678910

/** * 监听SQL执行 * @access public * @param callable $callback 回调方法 * @return void */public function listen($callback){    self::$event[] = $callback;}

3、event 保存我们传入的回调方法

4、在看下面这2个方法

12345678910111213141516171819202122232425262728293031323334353637383940414243444546

/** * 数据库调试 记录当前SQL及分析性能 * @access protected * @param boolean $start 调试开始标记 true 开始 false 结束 * @param string  $sql 执行的SQL语句 留空自动获取 * @return void */protected function debug($start, $sql = ''){    if (!empty($this->config['debug'])) {        // 开启数据库调试模式        if ($start) {            Debug::remark('queryStartTime', 'time');        } else {            // 记录操作结束时间            Debug::remark('queryEndTime', 'time');            $runtime = Debug::getRangeTime('queryStartTime', 'queryEndTime');            $sql     = $sql ?: $this->getLastsql();            $log     = $sql . ' [ RunTime:' . $runtime . 's ]';            $result  = [];            // SQL性能分析            if ($this->config['sql_explain'] && 0 === stripos(trim($sql), 'select')) {                $result = $this->getExplain($sql);            }            // SQL监听            $this->trigger($sql, $runtime, $result);        }    }} protected function trigger($sql, $runtime, $explain = []){    if (!empty(self::$event)) {        foreach (self::$event as $callback) {            if (is_callable($callback)) {                call_user_func_array($callback, [$sql, $runtime, $explain]);            }        }    } else {        // 未注册监听则记录到日志中        Log::record('[ SQL ] ' . $sql . ' [ RunTime:' . $runtime . 's ]', 'sql');        if (!empty($explain)) {            Log::record('[ EXPLAIN : ' . var_export($explain, true) . ' ]', 'sql');        }    }}

5、当我们执行了sql语句,就会触发会调用debug方法将执行日志写入日志文件中,同事调用trigger方法,如果我们最开始已经传入了回调方法,也就是

1

self::$event

不为空,(说明我们在执行sql语句之前就已经设置了监听)我们将调用我们的回调函数!

1

call_user_func_array

总结:在执行sql语句之前我们需要先设置监听,这就是为什么要把Db::listen()写在执行sql语句的前面!

下面我们来看下实际的效果:

1234567891011121314

public function expo(){    Db::listen(function($sql, $time, $explain){        // 记录SQL        echo $sql. ' ['.$time.'s]';        // 查看性能分析结果        dump($explain);    });    //Get data based on columns,执行sql语句    foreach($channel as $v)        $list[$v['id']] =  GetData::getData('news',"channel_id = {$v['id']} and status = 2",'id,title,author,create_time,channel_id,file_path','order_by desc','0,5');    return view('expo',[        'list' => $list    ]);}

效果图:

匿名用户
2019-03-13
展开全部
<?php 

class Db {
private static $link
public static table($table) {
self::$link = 初始化db;
return $this;
}

public function where($params) {
//xxx代码
return $this;
}

public function find($params) {
//xxx代码
return $rows;
}
}

?>

关键在于返回$this指向当前的对象

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
miniappcy3tv95eaedrf
2019-03-21 · TA获得超过2363个赞
知道大有可为答主
回答量:1909
采纳率:92%
帮助的人:1087万
展开全部

Db类的  @method  只是用于IDE识别,不是实际代码运行需要的。

这个用法的实现步骤,在Db类中可以看到

class Db
{

    ...
    
    public static function connect($config = [], $name = false, $query = '')
    {
        ...
    }
    
    ...
    
    
    public static function __callStatic($method, $args)
    {
        return call_user_func_array([static::connect(), $method], $args);
    }
}

重点在上面列出的两个方法,__calllStatic  是魔术静态方法,在这个类上做任意方法的静态调用,会走这个方法,并把调用的方法名和参数传进来

类似于php 类的 __get   __set  __call 等 ,参考  php 魔术方法

然后在 __callStatic 里调用 connect 生成一个Query对象,并把方法名调用到query对象上,然后再返回这个query对象,这样就能进行链式操作了,Query对象中的大部分操作也是返回对象本身(用于链式操作)

至于注释中的  @method  只是告诉ide 哪些方法可以用,写代码的时候不会提示方法不存在

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
百度网友b1ed549
2019-07-03 · TA获得超过375个赞
知道小有建树答主
回答量:496
采纳率:88%
帮助的人:252万
展开全部
Db::table的静态方法会初始化一个类,然后再调用这个类里面的非静态方法,这样是没有问题的。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
匿名用户
2019-03-06
展开全部
Db::table("table_name") 返回的是一个对象,当然可以用对象的->语法了
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(4)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式