Laravel 各版本- 原生SQL打印之SQL监听 --方法

Posted 高洛峰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Laravel 各版本- 原生SQL打印之SQL监听 --方法相关的知识,希望对你有一定的参考价值。

在框架中使用封装后的各种数据库类,对于很多人来说就是一把双刃剑(使用很方便,但是错在哪除非用得很熟,不然还真不好调试);很早之前博主已经写过一篇关于如何在laravel中输出原生的SQL语句的方法1.使用debugbar插件(见),2.使用局部SQL打印方法(见),3.使用事件监听器全局设置SQL原生态打印,前两篇丢丢哥已经写了,本篇就来完成这最后一种打印原生态SQL语句的方法.

本次使用的是事件监听来完成的一个自动全局SQL打印的方法(比第一种debugbar轻便,比第二种手动要方便),也是一个很实用的技巧了

Laravel 各版本- 原生SQL打印之SQL监听 --方法(二)

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语句

Laravel 各版本- 原生SQL打印之SQL监听 --方法(二)

  1. dd($params);得到的是变量的一个数组

Laravel 各版本- 原生SQL打印之SQL监听 --方法(二)

3.将$sql加入到数组第一个 dd($params);结果是sql语句和变量一起存在了数组里

Laravel 各版本- 原生SQL打印之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);
    }

这里是页面情况

Laravel 各版本- 原生SQL打印之SQL监听 --方法(二)

这里是日志情况

Laravel 各版本- 原生SQL打印之SQL监听 --方法(二)

然后我们把上面的所有的SQL语句都执行一遍,看看日志里面的情况

Laravel 各版本- 原生SQL打印之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监听 --方法(二)

Laravel 各版本- 原生SQL打印之SQL监听 --方法(二)   

以上是关于Laravel 各版本- 原生SQL打印之SQL监听 --方法的主要内容,如果未能解决你的问题,请参考以下文章

Laravel5.1 数据库--DB运行原生SQL

Laravel5打印所有运行SQL

Laravel打印执行的SQL语句

Laravel打印执行的SQL语句

laravel打印查询的sql

laravel ORM怎么打印出执行sql语句