Laravel 各版本- 原生SQL打印之SQL监听 --方法
Posted 高洛峰
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Laravel 各版本- 原生SQL打印之SQL监听 --方法相关的知识,希望对你有一定的参考价值。
在框架中使用封装后的各种数据库类,对于很多人来说就是一把
双刃剑
(使用很方便,但是错在哪除非用得很熟,不然还真不好调试);很早之前博主已经写过一篇关于如何在laravel中输出原生的SQL语句的方法1.使用debugbar插件
(见),2.使用局部SQL打印方法
(见),3.使用事件监听器全局设置SQL原生态打印
,前两篇丢丢哥已经写了,本篇就来完成这最后一种打印原生态SQL语句的方法.
本次使用的是事件监听来完成的一个自动全局SQL打印的方法(比第一种debugbar轻便,比第二种手动要方便),也是一个很实用的技巧了
Laravel LTS 5.1版本
一、创建SQL监听器
php artisan make:listener QueryListener --event=illuminate.query
生成文件于 app/Listeners/QueryListener.php
然后删除 app/Listeners/QueryListener.php
顶部的 use App\Events\illuminate.query;
, 这是自动生成的。
二、注册SQL监听事件
打开 app/Providers/EventServiceProvider.php
,在 $listen
中添加 illuminate.query
事件的监听器为 QueryListener
头部引入 use App\Listeners\QueryListener;
protected $listen = [
'illuminate.query' => [
QueryListener::class,
],
];
三、编写SQL打印逻辑代码
编辑app/Listeners/QueryListener.php
文件
/** * 日志打印方法. * * @param illuminate.query $event * @return void */
public function handle($sql, $params) { // dd($sql);
// dd($params);
// 如果env中属于本地开发则进入该判断
if (env('APP_ENV', 'production') == 'local') { foreach ($params as $index => $param) { if ($param instanceof \DateTime) { $params[$index] = $param->format('Y-m-d H:i:s');
}
} $sql = str_replace("?", "'%s'", $sql);
array_unshift($params, $sql); // dd($params);
\Log::info('SQL语句输出------------>'.call_user_func_array('sprintf', $params));
}
}
下面我们来看看我dd()打印的三个变量
1.dd($sql);
得到的是一个没有传入变量的sql语句
dd($params);
得到的是变量的一个数组
3.将$sql加入到数组第一个 dd($params);
结果是sql语句和变量一起存在了数组里
所以基本上我们知道这个SQL输出是怎么过来的了
下面把dd()
都注释 来看我们的输出情况,首先博主把/storage/logs/laravel.log,给清空了(方便演示)
在控制器中 我们准备好了几个DB类的SQL语句等会来看看日志里的SQL语句打印情况
public function testData()
{ $users = \DB::table('users')->where('id','<','10')->get();
// $users = \DB::table('users')->forPage(1,5)->get();
// $users = \DB::table('users')->orderBy('id', 'asc')->get();
// $users = \DB::table('users')->where('status','1')->skip(0)->take(5)->get();
dd($users);
}
这里是页面情况
这里是日志情况
然后我们把上面的所有的SQL语句都执行一遍,看看日志里面的情况
看!是不是所有的sql语句都记录了?是不是比之前的打印SQL方法要方便的多?其实如果需求不多,但是偶尔有需求,handle()里面的判断可以再加一层判断 比如我们在env里设置一个值SQL_DUMP = true;
在headle()最外层就判断这个值了,当为真的时候才打印,否则不打印SQL语句..
Laravel LTS 5.2,5.3版本
一、创建监听器
php artisan make:listener QueryListener --event=Illuminate\\Database\\Events\\QueryExecuted
生成文件于 app/Listeners/QueryListener.php
二、注册事件
打开 app/Providers/EventServiceProvider.php
,在 $listen
中添加 Illuminate\Database\Events\QueryExecuted
事件的监听器为QueryListener
命名空间中 use App\Listeners\QueryListener;
protected $listen = [
'Illuminate\Database\Events\QueryExecuted' => [ 'App\Listeners\QueryListener',
],
];
三、添加逻辑
光有一个空的监听器是不够的,我们需要自己实现如何把 $sql 记录到日志中。为此,对 QueryListener 进行改造,完善其 handle 方法如下:
/** * 日志打印方法. * * @param illuminate.query $event * @return void */
public function handle(QueryExecuted $event) { if (env('APP_ENV', 'production') == 'local') { $sql = str_replace("?", "'%s'", $event->sql); $log = vsprintf($sql, $event->bindings);
Log::info($log);
}
}
上面我们用到了 Log 门面,请注意在类开头引用,或者使用
\Log::info()
代替之。
可以看到,相对于 5.1 中的做法,本文中所诉的有不少变化。
首先,5.2 中不再有 illuminate.query
等形式的框架事件标识,所以我们在注册事件及其监听器时需要使用真实的事件类名。
其次,5.2 中事件监听器的 handle
方法只支持接收一个参数,此例中是一个\ Illuminate\Database\Events\QueryExecuted
类型的对象,该对象中包含查询时的 SQL、查询参数及查询时间等量,对于我们记录日志而言十分方便。
希望我的博客对你们有所帮助,你的认可就是我最大的动力。
本文转自 IT兄弟会 大牛博客,原文可点击左下角 阅读原文 查看
以上是关于Laravel 各版本- 原生SQL打印之SQL监听 --方法的主要内容,如果未能解决你的问题,请参考以下文章