thinkphp5.0之Db::listen详解 - 唐轶俊博客

thinkphp5.0之Db::listen详解

第三方接口 2041浏览 评论

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

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

使用如下方法:

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类,我们在这个类找一下这个方法!

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

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

4、在看下面这2个方法

/**
 * 数据库调试 记录当前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方法,如果我们最开始已经传入了回调方法,也就是

self::$event

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

call_user_func_array

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

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

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
    ]);
}

效果图:

image.png

本文连接:http://www.phpbloger.com/article/36.html 文章都为原创,转载请注明出处!

相关文章