21. 监听查询事件,打印 Query Log

监听查询事件, 打印query log

在开发环境, 打印出每次请求的SQL, 方便做sql分析优化。

  1. 首先新增一个log channel 单独保存 query log, 这里就叫做 query

    vim config/logging.php
    
    'channels' => [
            ……………………
    
            'daily' => [
                'driver' => 'daily',
                'path' => env('LOG_PATH', storage_path('logs/')) . 'laravel.log',
                'level' => env('LOG_LEVEL', 'debug'),
                'days' => env('LOG_MAX_FILES', 14),
            ],
        
            'query' => [
                'driver' => 'daily',
                'path' => env('LOG_PATH', storage_path('logs/')) . 'query.log',
                'level' => env('LOG_LEVEL', 'debug'),
                'days' => env('LOG_MAX_FILES', 3),
            ],
    
            ………………
        ],
    
  2. 在 app/Providers/AppServiceProvider.php:boot()中增加代码

    public function boot()
    {
      //仅在 local 环境生效(取值于.env文件中的APP_ENV)。
      if (app()->environment('local')) {
        
        //加入这一行代码是为了配合自定义函数 getLastSql() 简化打印最后一条sql,当然也可以直接查看sql日志。
        DB::connection()->enableQueryLog();
        // DB::connection('mysql_other')->enableQueryLog();//如果有多个库,需要执行多次
        
        //自动记录sql日志
        DB::listen(static function ($query) {
          $sql = str_replace(['%', '?'], ['%%', '%s'], $query->sql);
          if ($query->bindings) {
            $sql = sprintf($sql, ...array_map(static function ($val) {
              return is_string($val) ? "'{$val}'" : $val;
            }, $query->bindings));
            #这里指定 channel 为 query
            $log = "ConnectionName: {$query->connectionName}; Use Time {$query->time}; SQL:";
            $log .= PHP_EOL . $sql;
            Log::channel('query')->info($log);
          }
        });
      }
    }
    
  3. 然后测试,要确保 php的用户对 env(‘LOG_PATH’, storage_path(‘logs/’)) 有写入权限

    [2022-09-05 07:24:07] local.INFO: ConnectionName: mysql; Use Time 14.86; SQL:
    select * from `user` where `account` = 'admin' limit 1  
    [2022-09-05 07:24:19] local.INFO: ConnectionName: mysql; Use Time 6.65; SQL:
    select * from `user` where `id` = '1' limit 1  
    [2022-09-05 07:24:20] local.INFO: ConnectionName: mysql; Use Time 0.73; SQL:
    select * from `user` where `id` = '1' limit 1  
    [2022-09-05 07:24:20] local.INFO: ConnectionName: mysql; Use Time 3.49; SQL:
    select * from `user` where `id` = 3 and `username` = '张三子' and `account` = 'zhangsan' and `mobile` = '' and `email` = ''  
    [2022-09-05 07:24:25] local.INFO: ConnectionName: mysql; Use Time 7; SQL:
    select * from `user` where `id` = '1' limit 1  
    [2022-09-05 07:24:25] local.INFO: ConnectionName: mysql; Use Time 0.89; SQL:
    select * from `user` where `id` = '1' limit 1  
    
  4. 自定义函数打印最后一条sql

    if (!function_exists('getLastSql')) {
        
        /**
         * 调试方法:打印最后一条SQL
         * @param string $connection
         * @return string
         */
        function getLastSql(string $connection = ''): string
        {
            $queryLogs = DB::connection($connection)->getQueryLog();
            $query = $queryLogs ? array_pop($queryLogs) : [];
            $sql = $query ? str_replace(['%', '?'], ['%%', '%s'], $query['query']) : '';
            if (!empty($query['bindings'])) {
                $sql = sprintf($sql, ...array_map(static function ($val) {
                    return is_string($val) ? "'{$val}'" : $val;
                }, $query['bindings']));
            }
            return $sql;
        }   
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值