我正在尝试调试我在测试套件中执行的一些SQL查询。使用以下调试代码:
\Log::debug(User::first()->jobs()->toSql());
打印出来的SQL是:
`select * from `jobs` where `jobs`.`deleted_at` is null and `jobs`.`managed_by_id` = ? and `jobs`.`managed_by_id` is not null`
那个问号在那里做什么?我已经测试了查询,它按预期工作。是因为我正在选择第一个()用户吗?
答案 0 :(得分:11)
Laravel使用Prepared Statements。它们是一种编写SQL语句而不直接将变量删除到SQL字符串中的方法。您看到的?
是信息的占位符或绑定,稍后将被PDO替换并自动清理。有关预准备语句http://php.net/manual/en/pdo.prepared-statements.php
要查看将替换为查询字符串的数据,您可以在查询中调用getBindings()
函数,如下所示。
$query = User::first()->jobs();
dd($query->toSql(), $query->getBindings());
绑定数组的替换顺序与?
在SQL语句中出现的顺序相同。
答案 1 :(得分:4)
除了@wader的答案之外,还有一种“宏” 的方式来获取带有绑定的原始SQL查询。
使用 AppServiceProvider
boot()
方法添加以下宏功能。
\Illuminate\Database\Query\Builder::macro('toRawSql', function(){
return array_reduce($this->getBindings(), function($sql, $binding){
return preg_replace('/\?/', is_numeric($binding) ? $binding : "'".$binding."'" , $sql, 1);
}, $this->toSql());
});
向Eloquent Builder添加别名。
\Illuminate\Database\Eloquent\Builder::macro('toRawSql', function(){
return ($this->getQuery()->toRawSql());
});
然后照常调试。
\Log::debug(User::first()->jobs()->toRawSql());
注意:从Laravel 5.1到5.3,由于Eloquent Builder并未使用
Macroable
特性,因此无法将toRawSql
的别名即时添加到Eloquent Builder。请按照下面的示例来实现相同的目的。
例如雄辩的生成器( Laravel 5.1-5.3 )
\Log::debug(User::first()->jobs()->getQuery()->toRawSql());
答案 2 :(得分:2)
只需重申@giovannipds很好的答案...我正在这样做:
vsprintf(str_replace(['?'], ['\'%s\''], $query->toSql()), $query->getBindings())
答案 3 :(得分:0)
使用以下代码在Laravel中打印 RAW SQL :
echo "<pre>";
print_r($query->toSql());
print_r($query->getBindings());
添加PRE标签有助于您更准确地读取结果。