Laravel 5:如何转储SQL查询?

时间:2016-12-24 09:55:15

标签: mysql laravel logging dump

Laravel 5的内置解决方案

在Laravel 5+中,我们可以使用\DB::getQueryLog()来检索所有已执行的查询。由于查询日志记录是一项广泛的操作并导致性能问题,因此它在L5中默认禁用,仅建议仅用于开发环境。我们可以使用方法\DB::enableQueryLog()启用查询日志记录,如[Laravel' s文档] [1]中所述。

内置解决方案中的问题

DB::getQueryLog()函数很棒但有时我们希望如果我们以平面SQL格式转储它会很棒,所以我们可以在我们最喜欢的MySQL应用程序中复制/过去它,如phpMyAdmin或{ {1}}执行它并调试或优化它。

所以,我需要一个帮助我生成转储的辅助函数,其中包含以下附加信息:

  • 转储调用的文件和行号。
  • 从查询中删除后退。
  • 平面查询,因此不需要手动更新绑定参数,我可以复制/过去SqlyogSQL来调试/优化查询。

5 个答案:

答案 0 :(得分:3)

自定义解决方案

步骤1:启用查询记录

复制/过去路径文件顶部的以下代码块:

phpMyAdmin

第2步:添加辅助函数

# File: app/Http/routes.php
if (\App::environment( 'local' )) { 
   \DB::enableQueryLog();
}

}

如何使用?

转储上次执行的查询,在查询执行后立即使用:

if (!function_exists( 'dump_query' )) {
function dump_query( $last_query_only=true, $remove_back_ticks=true ) {

    // location and line
    $caller = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 1 );
    $info = count( $caller ) ? sprintf( "%s (%d)", $caller[0]['file'], $caller[0]['line'] ) : "*** Unable to parse location info. ***";

    // log of executed queries
    $logs = DB::getQueryLog();
    if ( empty($logs) || !is_array($logs) ) {
        $logs = "No SQL query found. *** Make sure you have enabled DB::enableQueryLog() ***";
    } else {
        $logs = $last_query_only ? array_pop($logs) : $logs;
    }

    // flatten bindings
    if (isset( $logs['query'] ) ) {
        $logs['query'] = $remove_back_ticks ? preg_replace( "/`/", "", $logs['query'] ) : $logs['query'];

        // updating bindings
        $bindings = $logs['bindings'];
        if ( !empty($bindings) ) {
            $logs['query'] = preg_replace_callback('/\?/', function ( $match ) use (&$bindings) {
                return "'". array_shift($bindings) . "'";
            }, $logs['query']);
        }
    }
    else foreach($logs as &$log) {
        $log['query'] = $remove_back_ticks ? preg_replace( "/`/", "", $log['query'] ) : $log['query'];

        // updating bindings
        $bindings = $log['bindings'];
        if (!empty( $bindings )) {
            $log['query'] = preg_replace_callback(
                '/\?/', function ( $match ) use ( &$bindings ) {
                return "'" . array_shift( $bindings ) . "'";
            }, $log['query']
            );
        }
    }

    // output
    $output = ["*FILE*" => $info,
               '*SQL*' => $logs
    ];

    dump( $output );
}

转储所有执行的查询使用:

dump_query();

答案 1 :(得分:2)

  • 转储所包含的文件和行号 调用。

我不明白为什么你需要这个,因为你总是知道你在哪里调用转储功能,但不要介意你有解决方案。

  • 从查询中删除back-ticks

您不需要删除back-ticks,因为查询在MySQL中也可以与它们一起使用。

  • 平面查询,因此不需要手动更新绑定参数,我可以在phpMyAdmin等中复制/通过SQL来调试/优化查询。

您可以将vsprintf用于绑定参数:

$queries = DB::getQueryLog();

foreach ($queries as $key => $query) {
    $queries[$key]['query'] = vsprintf(str_replace('?', '\'%s\'', $query['query']), $query['bindings']);
}

return $queries;

我建议你查看这个github repo squareboat/sql-doctor

答案 2 :(得分:0)

将此代码添加到路由文件的顶部。 Laravel 5.2 route.php Laravel 5.3+ web.php

<?php
// Display all SQL executed in Eloquent

Event::listen('Illuminate\Database\Events\QueryExecuted', function ($query) {
    var_dump($query->sql);
    var_dump($query->bindings);
    var_dump($query->time);
    echo "<br><br><br>";
});

答案 3 :(得分:0)

对于 Laravel 8 应用程序,将以下内容放入 AppServiceProvider.php 文件可能会很有用:

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    // [...]
    // Dump SQL queries on demand **ONLY IN DEV**
    if (env('APP_ENV') === 'local') {
        DB::enableQueryLog();
        Event::listen(RequestHandled::class, function ($event) {
            if ( $event->request->has('sql-debug') ) {
                $queries = DB::getQueryLog();
                Log::debug($queries);
                dump($queries);
            }
        });
    }

    // [...]
}

然后将 &sql-debug=1 附加到 url 将转储查询。

答案 4 :(得分:0)

我一直在寻找简单的解决方案,下面的解决方案对我有用。

DB::enableQueryLog();

User::find(1); //Any Eloquent query

// and then you can get query log

dd(DB::getQueryLog());

参考链接: