给定以下代码:
DB::table('users')->get();
我想得到上面的数据库查询生成器将生成的原始SQL查询字符串。在本例中,它将是SELECT*FROM用户。
我该怎么做?
给定以下代码:
DB::table('users')->get();
我想得到上面的数据库查询生成器将生成的原始SQL查询字符串。在本例中,它将是SELECT*FROM用户。
我该怎么做?
当前回答
为了记录所有执行的查询,可以使用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::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]);
});
请阅读代码中的注释。我知道,它并不完美,但对于我的日常调试来说,它还可以。它试图以或多或少的可靠性构建绑定查询。但是,不要完全信任它,数据库引擎以不同的方式对值进行转义,而这个短函数并没有实现这些值。所以,仔细观察结果。
你可以使用发条
Clockwork是一个用于PHP开发的Chrome扩展,通过一个新面板扩展了Developer Tools,该面板提供了用于调试和分析PHP应用程序的各种信息,包括请求、标头、获取和发布数据、cookie、会话数据、数据库查询、路由、应用程序运行时可视化等信息。
但也适用于firefox
有很多信息已经得到了回答,我将发布我自己的发现,每当我需要在执行sql查询之前输出它时,我都会使用这些发现。
考虑以下示例:
$user = DB::table('user')->where('id',1);
echo $user->toSql();
echo$user->toSql()=这将只输出原始查询,但不会显示传递的参数。
要输出带有传递参数的查询,我们可以使用laravel getBindings()和helper str_replace_array,如下所示:
$queryWithParam = str_replace_array('?',$user->getBindings(),$user->toSql());
echo $queryWithParam;
希望这也有帮助。
对QueryBuilder实例使用toSql()方法。
DB::table('users')->toSql()将返回:
从用户中选择*`
这比连接事件侦听器更容易,而且还允许您在构建查询时随时检查查询的实际外观。
注意:此方法适用于查询生成器或Elquent,但使用toSql()代替first()或get()。不能使用此方法同时运行查询和获取SQL。
将此代码添加到AppServiceProvider并获取日志文件
\DB::listen(function ($query) {
\Log::info(
$query->sql,
$query->bindings,
$query->time
);
});