给定以下代码:

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()
    {
        //
    }
}

来源

其他回答

为了记录所有执行的查询,可以使用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;
}

这是我可以向任何人建议的调试雄辩的最后一个查询或最终查询的最佳解决方案,尽管这也已经讨论过了:

// query builder
$query = DB::table('table_name')->where('id', 1);

// binding replaced
$sql = str_replace_array('?', $query->getBindings(), $query->toSql());

// for laravel 5.8^
$sql = Str::replaceArray('?', $query->getBindings(), $query->toSql());

// print
dd($sql);

下面是一个完美的例子:

https://laravel.com/docs/5.8/database#listening-用于查询事件

打开app\Providers\AppServiceProvider.php并将以下内容添加到Boot()函数中:

DB::listen(function ($query) {
    var_dump([
        $query->sql,
        $query->bindings,
        $query->time
    ]);
});

因此,您不需要在每个函数中放置DB::enableQuerylog()和DB::getQuerylog(()。

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