我们先来看下官网对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
public function listen($callback){ self::$event[] = $callback;}
3、event 保存我们传入的回调方法
4、在看下面这2个方法
12345678910111213141516171819202122232425262728293031323334353637383940414243444546
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 ]);}
效果图: