记录运行时 SQL 语句(针对 5.2 版本)
在开发过程中,我们有时候可能希望记录下程序执行的每一条 SQL,在 Laravel 中我们可以利用事件及其监听器很方便的实现这一需求。
本站之前曾发布过一篇相关的文章,不过是针对 5.1 及更老的版本,而在 Laravel5.2 中不再适用。所以就有了此文。
第一步:创建监听器
php artisan make:listener QueryListener --event=Illuminate\\Database\\Events\\QueryExecuted
生成文件于 app/Listeners/QueryListener.php
第二步:注册事件
打开 app/Providers/EventServiceProvider.php
,在 $listen
中添加 illuminate.query
事件的监听器为 QueryListener
:
protected $listen = [
'Illuminate\Database\Events\QueryExecuted' => [
'App\Listeners\QueryListener',
],
];
当然在类前面你需要
use App\Listeners\QueryListener;
不然就报类不存在了。
第三步:添加逻辑
光有一个空的监听器是不够的,我们需要自己实现如何把 $sql 记录到日志中。为此,对 QueryListener 进行改造,完善其 handle 方法如下:
<?php
namespace App\Listeners;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Log;
class QueryListener
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param QueryExecuted $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() 代替之。
至此大功告成,在调试模式下程序所执行的 SQL 都会被一一记录在案,方便我们调试。形式如下:
[2016-07-29 18:08:15] local.INFO: select * from `app_articles` where `app_articles`.`id` = '40' limit 1
可以看到,相对于 5.1 中的做法,本文中所诉的有不少变化。
首先,5.2 中不再有 illuminate.query 等形式的框架事件标识,所以我们在注册事件及其监听器时需要使用真实的事件类名。
其次,5.2 中事件监听器的 handle 方法只支持接收一个参数,此例中是一个 \ Illuminate\Database\Events\QueryExecuted 类型的对象,该对象中包含查询时的 SQL、查询参数及查询时间等量,对于我们记录日志而言十分方便。