[翻译] 快速导出 Laravel 的查询语句

Eloquent 是处理关系模型的神兵利器。你可以用它设计模型,缓加载子记录。

例如,假设你需要获取一个用户:

User::where('name', 'Eric')->first();

然后在视图中可能有以下操作:

@foreach ($user->posts as $post)

因为 posts 在初始加载时没有包含 User Eloquent,所以需要为每一条记录再执行一次查询,以取出关联的 User 。

解决方案如下:

User::where('name', 'Eric')->with('posts')->first();

为了对查询效率保持警觉,你可能会在本地开发环境启用 Laravel Debugbar 或者 Laravel database profiler 这两个重型工具,它们会打印所有的查询语句,并且在超出控制时给你提醒。

不过,在 Reddit 的 Laravel 频道上,用户 magkopian 共享了另一种 快速的解决方案,以查看页面上所有运行的查询。

在 AppServiceProvider.php 的 boot 方法中添加如下内容:

use DB;
use Event;

//..

public function boot()
{
    if (env('APP_ENV') === 'local') {
        DB::connection()->enableQueryLog();
        Event::listen('kernel.handled', function ($request, $response) {
            if ( $request->has('sql-debug') ) {
                $queries = DB::getQueryLog();
                dd($queries);
            }
        });
    }
}

现在,你在开发时往任何 URL 后追加 ?sql-debug=1 ,就可以打印出所有查询。

让我们再做个小小的改进,使用帮助函数 dump 替换掉 dd ,以获得格式更友好的输出:
file

看起来似乎不那么优雅,但是当我想看看特定页面究竟发生了什么,又不想安装专用的包的时候,这个技巧很好的解决了问题。

本作品采用《CC 协议》,转载必须注明作者和本文链接
Night gathers, and now my watch begins.
本帖由 Summer 于 7年前 加精
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 14
monkey

已集成进我的开发基础框架中 :+1:

7年前 评论
lijinma

lumen 中使用 Http Kernel 不太一样,没有扔 kernel.handled 事件

7年前 评论
lijinma

因为 Lumen 没有对应的事件,可以用这样的方式来做:

public function boot()
{
    if (app()->environment('local')) {
        \DB::connection()->enableQueryLog();
        if (app('request')->has('sql-debug')) {
            \DB::listen(function ($query) {
                dump($query->sql, $query->bindings);
            });
        }
    }
}

当然你需要开启 facade:

$app->withFacades();

这个很好用,我已经应用到项目里面了。。棒棒的。

7年前 评论
lijinma
DB::connection()->enableQueryLog();

有一个问题,就是会写大量的日志, 比较蛋疼。
用 \DB::listen 比较好

7年前 评论

感觉很牛逼.收藏先!

7年前 评论

5.4 The kernel.handled event is now an object based event using the Illuminate\Foundation\Http\Events\RequestHandled class.

7年前 评论

也可以參考使用:https://packagist.org/packages/recca0120/l...
提供的除錯工具即可以看到 Queries

7年前 评论
lijinma

@lijinma 上面的代码,去掉这一句吧

       \DB::connection()->enableQueryLog();
7年前 评论

file为什么不行呢

file

7年前 评论

用 laravel-debugbar 扩展包不就好了吗

7年前 评论

我是这样来做的,监听 QueryExecuted 这个事件

'Illuminate\Database\Events\QueryExecuted' => [
            'App\Listeners\QueryListener',
        ],
class QueryListener
{
    public function handle(QueryExecuted $query)
    {
        if (config('app.env', 'production') !== 'production') {
            $log = '';
            $sql = $query->sql;
            $bindings = $query->bindings;

            foreach (explode('?', $sql) as $key => $s) {
                if (isset($bindings[$key])) {
                    if (is_numeric($bindings[$key])) {
                        $log .= $s . $bindings[$key];
                    } else {
                        $log .= $s . "'" . $bindings[$key] . "'";
                    }
                } else {
                    $log .= $s;
                }
            }

            Log::info('[' . $query->time . ']: ' . $log);
        }
    }
}

遇到困惑的地方直接去看日志

7年前 评论

@Hanccc 不是输出的原因

7年前 评论

@权 不用dd()很有可能会把输出隐藏在标签内,这是个可能的原因

7年前 评论

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