给定以下代码:

DB::table('users')->get();

我想得到上面的数据库查询生成器将生成的原始SQL查询字符串。在本例中,它将是SELECT*FROM用户。

我该怎么做?


当前回答

如果您正在使用修补程序并希望记录形成的SQL查询,可以执行以下操作

$ php artisan tinker
Psy Shell v0.9.9 (PHP 7.3.5 — cli) by Justin Hileman
>>> DB::listen(function ($query) { dump($query->sql); dump($query->bindings); dump($query->time); });
=> null
>>> App\User::find(1)
"select * from `users` where `users`.`id` = ? limit 1"
array:1 [
  0 => 1
]
6.99
=> App\User {#3131
     id: 1,
     name: "admin",
     email: "admin@example.com",
     created_at: "2019-01-11 19:06:23",
     updated_at: "2019-01-11 19:06:23",
   }
>>>

其他回答

我通过监听查询日志并附加到日志数组来实现:

//create query
$query=DB::table(...)...->where(...)...->orderBy(...)...
$log=[];//array of log lines
...
//invoked on query execution if query log is enabled
DB::listen(function ($query)use(&$log){
    $log[]=$query;//enqueue query data to logs
});
//enable query log
DB::enableQueryLog();
$res=$query->get();//execute

在我看来,这将是初学者的最佳方法:

echo "<pre>";
print_r($query->toSql());
print_r($query->getBindings());

这里也描述了这一点。https://stackoverflow.com/a/59207557/9573341

以下是我使用的解决方案:

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]);
});

请阅读代码中的注释。我知道,它并不完美,但对于我的日常调试来说,它还可以。它试图以或多或少的可靠性构建绑定查询。但是,不要完全信任它,数据库引擎以不同的方式对值进行转义,而这个短函数并没有实现这些值。所以,仔细观察结果。

用于获取带有绑定的SQL查询的“可宏”替换。

在AppServiceProvider boot()方法中添加以下宏函数。\Illuminate\Database\Query\Builder::宏('toRawSql',function(){return array_reduce($this->getBindings(),函数($sql,$binding){return preg_replace('/\?/',is_numeric($binding)$绑定:“”$结合“'”,$sql,1);},$this->to SQL());});为Elquent Builder添加别名。(Laravel 5.4+)\Illuminate\Database\Elquent\Builder::宏('toRawSql',函数(){return($this->getQuery()->toRawSql());});然后照常调试。(Laravel 5.4+)例如,查询生成器\日志::debug(\DB::table('users')->limit(1)->toRawSql())例如,Elquent Builder\日志::debug(\App\User::limit(1)->toRawSql());

注意:从Laravel 5.1到5.3,由于Elquent Builder不使用Macroable特性,因此不能在RawSql中添加Elquent生成器的别名。遵循以下示例以实现相同的效果。

例如,Elquent Builder(Laravel 5.1-5.3)

\Log::debug(\App\User::limit(1)->getQuery()->toRawSql());

有很多信息已经得到了回答,我将发布我自己的发现,每当我需要在执行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;

希望这也有帮助。