记录运行时 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、查询参数及查询时间等量,对于我们记录日志而言十分方便。

results matching ""

    No results matching ""