Laravel 5:如何转储 SQL 查询?
Posted
技术标签:
【中文标题】Laravel 5:如何转储 SQL 查询?【英文标题】:Laravel 5: How to dump SQL query? 【发布时间】:2017-05-09 19:04:13 【问题描述】:Laravel 5 的内置解决方案
在 Laravel 5+ 中,我们可以使用 \DB::getQueryLog()
来检索所有已执行的查询。因为,查询日志是一项广泛的操作并会导致性能问题,因此它在 L5 中默认禁用,仅推荐用于开发环境。我们可以使用方法\DB::enableQueryLog()
启用查询日志记录,如 [Laravel 的文档][1] 中所述。
内置解决方案中的问题
DB::getQueryLog()
函数很棒,但有时我们希望以平面 SQL 格式转储它会很棒,因此我们可以将其复制/粘贴到我们最喜欢的 mysql 应用程序中,例如 phpMyAdmin
或 Sqlyog
来执行它并调试或优化它。
所以,我需要一个辅助函数来帮助我生成带有以下附加信息的转储:
转储调用了哪个文件和行号。 从查询中删除反引号。 平面查询,因此不需要手动更新绑定参数,我可以在phpMyAdmin
中复制/粘贴SQL
等来调试/优化查询。
【问题讨论】:
【参考方案1】:我一直在寻找简单的解决方案,而下面的解决方案对我有用。
DB::enableQueryLog();
User::find(1); //Any Eloquent query
// and then you can get query log
dd(DB::getQueryLog());
参考链接:
How to Get the Query Executed in Laravel 5? DB::getQueryLog() Returning Empty Array https://www.codegrepper.com/code-examples/php/dump+sql+query+laravel【讨论】:
【参考方案2】:对于 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 将转储查询。
【讨论】:
【参考方案3】:将此代码添加到您的路线文件的顶部。 Laravel 5.2 路由.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>";
);
【讨论】:
【参考方案4】: 转储在哪个文件和行号上 调用。我不明白你为什么需要这个,因为你总是知道你在哪里调用了转储函数,但没关系你有你的解决方案。
从查询中删除back-ticks
。
您无需删除 back-ticks
,因为查询也可以在 MySQL 中与它们一起使用。
您可以使用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
【讨论】:
通过删除back-ticks
,生成的SQL将易于阅读和调试,因为该函数的主要工作是调试。感谢vsprintf
功能,是的,它将帮助我减少代码。【参考方案5】:
自定义解决方案
第 1 步:启用查询日志记录
复制/粘贴路由文件顶部的以下代码块:
# 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();
转储所有已执行的查询使用:
dump_query( false );
【讨论】:
以上是关于Laravel 5:如何转储 SQL 查询?的主要内容,如果未能解决你的问题,请参考以下文章
如何修复 laravel 5.5 中的查询生成器错误 sql 注入 *
在 laravel 4 中即时克隆数据库或运行 sql 转储