给定以下代码:

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

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

我该怎么做?


当前回答

下面是一个完美的例子:

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(()。

其他回答

你可以使用发条

Clockwork是一个用于PHP开发的Chrome扩展,通过一个新面板扩展了Developer Tools,该面板提供了用于调试和分析PHP应用程序的各种信息,包括请求、标头、获取和发布数据、cookie、会话数据、数据库查询、路由、应用程序运行时可视化等信息。

但也适用于firefox

最简单的方法是故意犯错误。例如,我想查看以下关系的完整SQL查询:

public function jobs()
{
    return $this->belongsToMany(Job::class, 'eqtype_jobs')
        ->withPivot(['created_at','updated_at','id'])
        ->orderBy('pivot_created_at','desc');
}

我只是想创建一个找不到的列,这里我选择了created_at,并通过添加尾随s将其更改为created_ats:

public function jobs()
{
    return $this->belongsToMany(Job::class, 'eqtype_jobs')
        ->withPivot(['created_ats','updated_at','id'])
        ->orderBy('pivot_created_at','desc');
}

因此,调试器将返回以下错误:

(4/4)ErrorException SQLSTATE[42S22]:未找到列:1054未知“字段列表”中的列“eqtype_jobs.created_ats”(SQL:selectjobs.*,eqtype_jobs.set_id作为pivot_set_id,eqtype_jobs.job_id作为pivot_job_id,eqtype_jobs.created_ats作为pivot_created_ats,eqtype_jobs.updated_at作为pivot_updated_at,eqtype_jobs.id作为内部作业的pivot_id在jobs.id上加入eqtype_jobs.job_id,其中eqtype_jobs.set_id=56在desc limit 20时按pivot_created排序偏移量0)(视图:/home/ssad/www/factory/resources/views/set/show.blade.php)

上面的错误消息返回带有错误的完整SQL查询

SQL: select  jobs.*, eqtype_jobs.set_id as pivot_set_id,  eqtype_jobs.job_id as pivot_job_id, eqtype_jobs.created_ats as pivot_created_ats, eqtype_jobs.updated_at as  pivot_updated_at, eqtype_jobs.id as pivot_id from jobs inner join eqtype_jobs on jobs.id = eqtype_jobs.job_id where  eqtype_jobs.set_id = 56 order by pivot_created_at desc limit 20 offset 0

现在,只需从created_at中删除多余的s,并在任何SQL编辑器(如phpMyAdmin SQL编辑器)中测试该SQL!

###通知:该溶液已经用Laravel 5.4进行了测试。

我创建了一些简单的函数来从一些查询中获取SQL和绑定。

/**
 * getSql
 *
 * Usage:
 * getSql( DB::table("users") )
 * 
 * Get the current SQL and bindings
 * 
 * @param  mixed  $query  Relation / Eloquent Builder / Query Builder
 * @return array          Array with sql and bindings or else false
 */
function getSql($query)
{
    if( $query instanceof Illuminate\Database\Eloquent\Relations\Relation )
    {
        $query = $query->getBaseQuery();
    }

    if( $query instanceof Illuminate\Database\Eloquent\Builder )
    {
        $query = $query->getQuery();
    }

    if( $query instanceof Illuminate\Database\Query\Builder )
    {
        return [ 'query' => $query->toSql(), 'bindings' => $query->getBindings() ];
    }

    return false;
}

/**
 * logQuery
 *
 * Get the SQL from a query in a closure
 *
 * Usage:
 * logQueries(function() {
 *     return User::first()->applications;
 * });
 * 
 * @param  closure $callback              function to call some queries in
 * @return Illuminate\Support\Collection  Collection of queries
 */
function logQueries(closure $callback) 
{
    // check if query logging is enabled
    $logging = DB::logging();

    // Get number of queries
    $numberOfQueries = count(DB::getQueryLog());

    // if logging not enabled, temporarily enable it
    if( !$logging ) DB::enableQueryLog();

    $query = $callback();

    $lastQuery = getSql($query);

    // Get querylog
    $queries = new Illuminate\Support\Collection( DB::getQueryLog() );

    // calculate the number of queries done in callback
    $queryCount = $queries->count() - $numberOfQueries;

    // Get last queries
    $lastQueries = $queries->take(-$queryCount);

    // disable query logging
    if( !$logging ) DB::disableQueryLog();

    // if callback returns a builder object, return the sql and bindings of it
    if( $lastQuery )
    {
        $lastQueries->push($lastQuery);
    }

    return $lastQueries;
}

用法:

getSql( DB::table('users') );
// returns 
// [
//     "sql" => "select * from `users`",
//     "bindings" => [],
// ]

getSql( $project->rooms() );
// returns
// [
//     "sql" => "select * from `rooms` where `rooms`.`project_id` = ? and `rooms`.`project_id` is not null",
//     "bindings" => [ 7 ],
// ]

从laravel 5.2开始。您可以使用DB::listen获取执行的查询。

DB::listen(function ($query) {
    // $query->sql
    // $query->bindings
    // $query->time
});

或者,如果要调试单个Builder实例,则可以使用toSql方法。

DB::table('posts')->toSql(); 

虽然我很喜欢这个框架,但我讨厌它像垃圾一样运行。

DB::enableQueryLog()完全无用。DB::听同样没用。当我说$query->count()时,它显示了部分查询,但如果我执行$query->get(),它就没有什么好说的了。

唯一一个似乎能持续工作的解决方案是,故意在ORM参数中添加一些语法或其他错误,例如不存在的列/表名,在调试模式下在命令行上运行代码,最后将通过完整的“frickin”查询吐出SQL错误。否则,如果从web服务器运行,则希望错误出现在日志文件中。