Laravel 中输出 SQL 语句的到 log 日志

在AppServiceProvider.php中的boot方法中添加如下代码 即可

public function boot()
{
    \DB::listen(function($query) {
        $tmp = str_replace('?', '"'.'%s'.'"', $query->sql);
        $tmp = vsprintf($tmp, $query->bindings);
        $tmp = str_replace("\\","",$tmp);
         \Log::info(' execution time: '.$query->time.'ms; '.$tmp."\n\n\t");

      });
}

运行原生 SQL 查询 使用 ? 绑定参数时上边是可行的 但是使用命名绑定参数时参数没有填充到语句中

下边的解决了使用命名绑定 参数没有填充到sql语句的问题

            \DB::listen(function ($query) {
                $tmp = str_replace('?', '"'.'%s'.'"', $query->sql);
                $qBindings = [];
                foreach ($query->bindings as $key => $value) {
                    if (is_numeric($key)) {
                        $qBindings[] = $value;
                    } else {
                        $tmp = str_replace(':'.$key, '"'.$value.'"', $tmp);
                    }
                }
                $tmp = vsprintf($tmp, $qBindings);
                $tmp = str_replace("\\", "", $tmp);
                \Log::info(' execution time: '.$query->time.'ms; '.$tmp."\n\n\t");

            }
        );

执行与数据库相关的操作会在 storage\logs\laravel.log 文件中看到记录执行的sql语句
(5.1版本 请看回复区)

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由 Summer 于 6年前 加精
jaak
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 16

在实际的生产环境中很可能有很多php实例,是否考虑过将日志输出到一些日志服务中?

6年前 评论
jaak

@CJ 暂时木有呢,

6年前 评论

5.1报错

ErrorException in AppServiceProvider.php line 21:
Trying to get property of non-object
6年前 评论
jaak

@moext 试试这个

DB::listen(function ($sql, $bindings, $time) {
            Log::info('db listen', [
                'sql' => $sql,
                'bindings' => $bindings,
                'time' => $time
            ]);
        });
6年前 评论

@jaak 这个可以 竖大拇指.jpg

6年前 评论
jaak

@moext 5.1版本是这样

6年前 评论
free-andy

这里有一个坑,如果 $query->sql 字符串里面包含了 %字符, 会出现 vsprintf(): Too few arguments 错误, 我的做法是先把原字符串里面的 % 字符替换掉

6年前 评论
jaak

@FreeAndy 哦 明白 谢谢

6年前 评论

如何看执行时间呢?

5年前 评论

能获取到对应的数据连接信息吗

5年前 评论

多次运行如何把重复的sql语句不要打印出来

4年前 评论
liyang997837

这里有一个坑,如果 $query->sql 字符串里面包含了 % 字符,会出现 vsprintf (): Too few arguments 错误,如何处理?

4年前 评论
jaak (楼主) 4年前
jaak (楼主) 4年前

为什么这个服务提供者会在执行数据库查询语句的时候会自动执行,有介绍服务提供者的知识吗,网上查的都是一样的,没怎么看懂

3年前 评论

优化:作者解决方案中使用 vsprintf ($tmp = vsprintf($tmp, $qBindings))方法,不排除 sql 中会带有 % 的参数,如 '%Y-%m-%d', 这时候解析的话,php 就会报错 Unknown format specifier "Y"

解决方案如下:直接替换绑定的"?", 即:$sql = \Str::replaceFirst('?', "'{$value}'", $sql);

    if (config('app.debug')) {
        \Schema::defaultStringLength(191);
        \DB::listen(function ($query) {
            $sql = $query->sql;
            if (! \Arr::isAssoc($query->bindings)) {
                foreach ($query->bindings as $value) {
                    if ($value instanceof \DateTime) {
                        $value = $value->format('Y-m-d H:i:s');
                    }

                    $sql = \Str::replaceFirst('?', "'{$value}'", $sql);
                }
            }

            \Log::info(sprintf('[%s] %s ' . "\n" . '%s;' . "\n", $query->time, Request::getRequestUri(), $sql));
        });
    }
2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!