原生sql打印有三种,分别是使用debugbar插件、使用局部SQL打印方法、使用事件监听器全局设置SQL原生态打印,本次讲的是第三种,事件监听打印原生Sql,每个laravel版本不太一样,如下:
Laravel LTS 5.1版本
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));
}
}
接着在控制器中输入测试代码来测试下:
public function test() {
$users = \DB::table('users')->where('id','<','10')->get();
dd($users);
}
从浏览器器访问可显示出打印的用户信息,再在后台 /storage/logs/laravel.log日志中可看到原生的sql语句。
Laravel LTS 5.2版本之后(至少到5.5是可以)
一、创建监听器
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); //$event->sql是获取参数值为?的sql语句
$log = vsprintf($sql, $event->bindings); //$event->bindings是获取到绑定的参数数组
//与 sprintf() 不同,vsprintf() 中的参数位于数组中,数组元素将被插入到主字符串中的百分号(%)符号处。
Log::info($log);
}
}
上面我们用到了 Log 门面,请注意在类开头引用,或者使用
\Log::info()
代替之。
可以看到,相对于 5.1 中的做法,本文中所诉的有不少变化。
首先,5.2 中不再有 illuminate.query
等形式的框架事件标识,所以我们在注册事件及其监听器时需要使用真实的事件类名。
其次,5.2 中事件监听器的 handle
方法只支持接收一个参数,此例中是一个\ Illuminate\Database\Events\QueryExecuted
类型的对象,该对象中包含查询时的 SQL、查询参数及查询时间等量,对于我们记录日志而言十分方便。
如此打印原生SQL就成功了, 对我们测试定会有大大大帮助。
原文转载链接:https://www.blog8090.com/laravel-lts-yuan-sheng-sqlda-yin-zhi-sqljian-ting-fang-fa-er/