给定以下代码:
DB::table('users')->get();
我想得到上面的数据库查询生成器将生成的原始SQL查询字符串。在本例中,它将是SELECT*FROM用户。
我该怎么做?
给定以下代码:
DB::table('users')->get();
我想得到上面的数据库查询生成器将生成的原始SQL查询字符串。在本例中,它将是SELECT*FROM用户。
我该怎么做?
当前回答
对于laravel 5.5.X
如果希望接收应用程序执行的每个SQL查询,可以使用listen方法。此方法对于记录查询或调试非常有用。您可以在服务提供商中注册查询侦听器:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
DB::listen(function ($query) {
// $query->sql
// $query->bindings
// $query->time
});
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
//
}
}
来源
其他回答
有一种获取查询字符串的方法。
到SQL()
在我们的情况下,
DB::table('users')->toSql();
回来
select * from users
是返回SQL查询字符串的确切解决方案。。希望这有帮助。。。
为了记录所有执行的查询,可以使用DB::enableQueryLog()icw DB::getQueryLog(()。输出具有以下结构。
[
[
"query" => "select * from "users" where name = ?"
"bindings" => ["John Doe"]
"time" => 0.34
],
...
]
此外,我在这里结合了一些答案,以便获得完美的函数,用编译的绑定解析sql。见下文。我甚至创建了一个实现此功能的自定义生成器类,例如User::where('name','JohnDoe')->parse();
function parse_sql(string $sql, array $bindings) : string
{
$compiled_bindings = array_map('compile_binding', $bindings);
return preg_replace_array("/\?/", $compiled_bindings, $sql);
}
function compile_binding($binding)
{
$grammar = new MySqlGrammar;
if (is_bool($binding))
{
return (int)$binding; //This line depends on the database implementation
}
if(is_string($binding))
{
return "'$binding'";
}
if ($binding instanceof DateTimeInterface)
{
return $binding->format($grammar->getDateFormat());
}
return $binding;
}
要将上次运行的查询输出到屏幕,可以使用以下命令:
\DB::enableQueryLog(); // Enable query log
// Your Eloquent query executed by using get()
dd(\DB::getQueryLog()); // Show results of log
我相信最近的查询将位于阵列的底部。
你会得到这样的东西:
array(1) {
[0]=>
array(3) {
["query"]=>
string(21) "select * from "users""
["bindings"]=>
array(0) {
}
["time"]=>
string(4) "0.92"
}
}
(感谢约书亚在下面的评论。)
将此代码添加到AppServiceProvider并获取日志文件
\DB::listen(function ($query) {
\Log::info(
$query->sql,
$query->bindings,
$query->time
);
});
以下是我使用的解决方案:
DB::listen(function ($sql, $bindings, $time) {
$bound = preg_replace_callback("/\?/", function($matches) use ($bindings) {
static $localBindings;
if (!isset($localBindings)) {
$localBindings = $bindings;
}
$val = array_shift($localBindings);
switch (gettype($val)) {
case "boolean":
$val = ($val === TRUE) ? 1 : 0; // mysql doesn't support BOOL data types, ints are widely used
// $val = ($val === TRUE) ? "'t'" : "'f'"; // todo: use this line instead of the above for postgres and others
break;
case "NULL":
$val = "NULL";
break;
case "string":
case "object":
$val = "'". addslashes($val). "'"; // correct escaping would depend on the RDBMS
break;
}
return $val;
}, $sql);
array_map(function($x) {
(new \Illuminate\Support\Debug\Dumper)->dump($x);
}, [$sql, $bindings, $bound]);
});
请阅读代码中的注释。我知道,它并不完美,但对于我的日常调试来说,它还可以。它试图以或多或少的可靠性构建绑定查询。但是,不要完全信任它,数据库引擎以不同的方式对值进行转义,而这个短函数并没有实现这些值。所以,仔细观察结果。