给定以下代码:
DB::table('users')->get();
我想得到上面的数据库查询生成器将生成的原始SQL查询字符串。在本例中,它将是SELECT*FROM用户。
我该怎么做?
给定以下代码:
DB::table('users')->get();
我想得到上面的数据库查询生成器将生成的原始SQL查询字符串。在本例中,它将是SELECT*FROM用户。
我该怎么做?
当前回答
我创建了一些简单的函数来从一些查询中获取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 ],
// ]
其他回答
打印上次查询
DB::enableQueryLog();
$query = DB::getQueryLog();
$lastQuery = end($query);
print_r($lastQuery);
如果您试图使用Illuminate而不使用Laravel获取日志,请使用:
\Illuminate\Database\Capsule\Manager::getQueryLog();
你也可以像这样设置一个快速功能:
function logger()
{
$queries = \Illuminate\Database\Capsule\Manager::getQueryLog();
$formattedQueries = [];
foreach ($queries as $query) :
$prep = $query['query'];
foreach ($query['bindings'] as $binding) :
if (is_bool($binding)) {
$val = $binding === true ? 'TRUE' : 'FALSE';
} else if (is_numeric($binding)) {
$val = $binding;
} else {
$val = "'$binding'";
}
$prep = preg_replace("#\?#", $val, $prep, 1);
endforeach;
$formattedQueries[] = $prep;
endforeach;
return $formattedQueries;
}
EDIT
更新的版本似乎在默认情况下禁用了查询日志记录(上面返回了一个空数组)。要重新启用,在初始化Capsule Manager时,获取连接的实例并调用enableQueryLog方法
$capsule::connection()->enableQueryLog();
再次编辑
考虑到实际问题,您实际上可以执行以下操作来转换当前的单个查询,而不是之前的所有查询:
$sql = $query->toSql();
$bindings = $query->getBindings();
Use:
$data = DB::select('select * from users where id = :id', ['id' => 1]);
print_r($data);
输出如下:
Array ( [0] => stdClass Object ( [id] => 1 [name] => parisa [last] => naderi [username] => png [password] => 2132 [role] => 0 ) )
第一个选项
当然,有一些方法可以只输出一个查询,并在phpMyAdmin或其他工具中对其进行调试,以了解查询的执行方式。
一种将查询与变量(也称为绑定)一起转储的好方法,您可以将以下函数添加为项目中的公共助手
function queryToSQL($query, $logQuery = true)
{
$addSlashes = str_replace('?', "'?'", $query->toSql());
$sql = str_replace('%', '#', $addSlashes);
$sql = str_replace('?', '%s', $sql);
$sql = vsprintf($sql, $query->getBindings());
$sql = str_replace('#', '%', $sql);
if ($logQuery) {
Log::debug($sql);
}
return $sql;
}
第二个选项
这是另一种方法,而不是转储每个查询,您可以使用Telescope,该工具可以让您更深入地了解可能在后台启动的所有查询,以及每个查询花费的时间以及显示的所有绑定
第三种选择
Laravel Debugbar是一个非常棒的插件,它可以帮助您在小的底部栏下调试所有内容,但这仅适用于基于UI的活动,对于API或命令,调试方式被忽略了,Telescope成为了一个很好的助手
最简单的方法是故意犯错误。例如,我想查看以下关系的完整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进行了测试。