Laravel的toSql()方法是否掩盖了ids? (列值被问号代替)

时间:2015-09-03 09:55:25

标签: laravel eloquent

我正在尝试调试我在测试套件中执行的一些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`

那个问号在那里做什么?我已经测试了查询,它按预期工作。是因为我正在选择第一个()用户吗?

4 个答案:

答案 0 :(得分:11)

Laravel使用Prepared Statements。它们是一种编写SQL语句而不直接将变量删除到SQL字符串中的方法。您看到的?是信息的占位符或绑定,稍后将被PDO替换并自动清理。有关预准备语句http://php.net/manual/en/pdo.prepared-statements.php

的更多信息,请参阅PHP文档

要查看将替换为查询字符串的数据,您可以在查询中调用getBindings()函数,如下所示。

$query = User::first()->jobs();

dd($query->toSql(), $query->getBindings());

绑定数组的替换顺序与?在SQL语句中出现的顺序相同。

答案 1 :(得分:4)

除了@wader的答案之外,还有一种“宏” 的方式来获取带有绑定的原始SQL查询。

  1. 使用 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());
    });
    
  2. 向Eloquent Builder添加别名。

    \Illuminate\Database\Eloquent\Builder::macro('toRawSql', function(){
        return ($this->getQuery()->toRawSql());
    });
    
  3. 然后照常调试。

    \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标签有助于您更准确地读取结果。