Answers:
要将最近运行的查询输出到屏幕,可以使用以下命令:
DB::enableQueryLog(); // Enable query log
// Your Eloquent query executed by using get()
dd(DB::getQueryLog()); // Show results of log
我相信最近的查询将在数组的底部。
您将拥有类似的内容:
array(1) {
[0]=>
array(3) {
["query"]=>
string(21) "select * from "users""
["bindings"]=>
array(0) {
}
["time"]=>
string(4) "0.92"
}
}
Log
类将其输出到应用程序的日志中: Log::debug(DB::getQueryLog())
DB::enableQueryLog();
DB::enableQueryLog(); dd(DB::getQueryLog());
但它只是返回[]
....
DB::connection('database')->getQueryLog()
toSql()
在QueryBuilder
实例上使用该方法。
DB::table('users')->toSql()
会返回:
从用户中选择*
这比连接事件侦听器容易,而且还可以让您在构建查询时随时查看查询的实际外观。
getBindings
方法。这将返回绑定,以便将其绑定到SQL语句。
$query = \DB::table('users')->where('id', 10); $sql = str_replace_array('?', $query->getBindings(), $query->toSql()); dd($sql);
DB::QueryLog()
只有在执行查询后才能工作$builder->get()
。如果要在执行查询之前获取查询,可以使用$builder->toSql()
方法。这是示例如何获取sql并将其绑定:
$query = str_replace(array('?'), array('\'%s\''), $builder->toSql());
$query = vsprintf($query, $builder->getBindings());
dump($query);
$result = $builder->get();
或者只是使您的查询错误,例如调用不存在的表或列,您将在异常XD中看到生成的查询
$query = vsprintf(str_replace(array('?'), array('\'%s\''), $builder->toSql()), $builder->getBindings());
LIKE
查询或格式化日期),则此功能将不起作用。您需要先使用双百分号将它们转义。
$builder->getBindings()
?
您可以听“ illuminate.query”事件。在查询之前,添加以下事件侦听器:
Event::listen('illuminate.query', function($query, $params, $time, $conn)
{
dd(array($query, $params, $time, $conn));
});
DB::table('users')->get();
这将打印出类似以下内容:
array(4) {
[0]=>
string(21) "select * from "users""
[1]=>
array(0) {
}
[2]=>
string(4) "0.94"
[3]=>
string(6) "sqlite"
}
use Illuminate\Support\Facades\Event;
如果您尝试使用不带Laravel的Illuminate获取日志,请使用:
\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 ) :
$prep = preg_replace("#\?#", is_numeric($binding) ? $binding : "'" . $binding . "'", $prep, 1);
endforeach;
$formattedQueries[] = $prep;
endforeach;
return $formattedQueries;
}
编辑
默认情况下,更新的版本似乎已禁用查询日志记录(以上返回空数组)。要重新打开,请在初始化Capsule Manager时获取连接实例并调用enableQueryLog
方法
$capsule::connection()->enableQueryLog();
再次编辑
考虑到实际问题,您实际上可以执行以下操作来转换当前的单个查询而不是所有先前的查询:
$sql = $query->toSql();
$bindings = $query->getBindings();
'US/Eastern'
。
quick function
。我相信底层代码将使用prepare(php.net/manual/en/mysqli.prepare.php)方法,这就是为什么仅?
需要的原因。您可以php.net/manual/en/function.is-numeric.php确定是否将输入封装在单引号内。
is_numeric
想法),它可以正常工作!我喜欢这个。谢谢。
有一种雄辩的方法来获取查询字符串。
toSql()
就我们而言
DB::table('users')->toSql();
返回
select * from users
是返回SQL查询字符串的确切解决方案。希望此对您有帮助...
->where('foo', '=', 'bar')
bar将不会在sql中显示
$data = User::toSql();
echo $data; //this will retrun select * from users. //here User is model
->toSql()
如果模型后有更多参数,则可以像添加操作一样追加。例如User::where('id', 1)->toSql()
如果您使用laravel 5.1和MySQL,则可以使用我提供的以下功能:
/*
* returns SQL with values in it
*/
function getSql($model)
{
$replace = function ($sql, $bindings)
{
$needle = '?';
foreach ($bindings as $replace){
$pos = strpos($sql, $needle);
if ($pos !== false) {
if (gettype($replace) === "string") {
$replace = ' "'.addslashes($replace).'" ';
}
$sql = substr_replace($sql, $replace, $pos, strlen($needle));
}
}
return $sql;
};
$sql = $replace($model->toSql(), $model->getBindings());
return $sql;
}
作为输入参数,您可以使用以下任意一个
照亮\数据库\口才\生成器
照亮\数据库\口才\关系\有很多
照亮\数据库\查询\生成器
首先,您需要通过调用以下命令来启用查询日志:
DB::enableQueryLog();
使用DB Facade查询后,您可以编写:
dd(DB::getQueryLog());
输出将如下所示:
array:1 [▼
0 => array:3 [▼
"query" => "select * from `users` left join `website_user` on `users`.`id` = `website_user`.`user_id` left join `region_user` on `users`.`id` = `region_user`.`user_id` left ▶"
"bindings" => array:5 [▶]
"time" => 3.79
]
]
这是我可以建议的任何一种最佳解决方案,用于调试有说服力的最后查询或最终查询,尽管对此也进行了讨论:
// 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);
只需您可以使用toSql()
方法进行以下操作,
$query = DB::table('users')->get();
echo $query->toSql();
如果它不起作用,则可以从laravel文档中进行设置。
另一种方法是
DB::getQueryLog()
但是,如果它返回一个空数组,则默认情况下它是禁用的,请访问this,
只需启用,DB::enableQueryLog()
它将起作用:)
有关更多信息,请访问Github Issue以了解更多信息。
希望能帮助到你 :)
一个“macroable”更换,以获得与绑定的SQL查询。
在方法中添加以下宏功能。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());
});
为雄辩的生成器添加别名。(Laravel 5.4+)
\Illuminate\Database\Eloquent\Builder::macro('toRawSql', function(){
return ($this->getQuery()->toRawSql());
});
然后照常调试。(Laravel 5.4+)
例如查询生成器
\Log::debug(\DB::table('users')->limit(1)->toRawSql())
例如雄辩的建造者
\Log::debug(\App\User::limit(1)->toRawSql());
注意:从Laravel 5.1到5.3,由于Eloquent Builder不使用
Macroable
特征,因此无法动态toRawSql
地向Eloquent Builder 添加别名。请按照下面的示例来实现相同的目的。
例如Eloquent Builder(Laravel 5.1-5.3)
\Log::debug(\App\User::limit(1)->getQuery()->toRawSql());
从幼虫5.2
开始。您可以DB::listen
用来获取执行的查询。
DB::listen(function ($query) {
// $query->sql
// $query->bindings
// $query->time
});
或者,如果要调试单个Builder
实例,则可以使用toSql
方法。
DB::table('posts')->toSql();
最简单的方法是故意犯错误。例如,我想查看以下关系的完整SQL查询:
public function jobs()
{
return $this->belongsToMany(Job::class, 'eqtype_jobs')
->withPivot(['created_at','updated_at','id'])
->orderBy('pivot_created_at','desc');
}
我只是要创建一个找不到的列,在这里我选择了created_at
,然后created_ats
通过添加尾随s
将其更改为:
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:选择
jobs
*,。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
内连接eqtype_jobs
上jobs
。id
=eqtype_jobs
。job_id
其中eqtype_jobs
。set_id
= 56为了通过pivot_created_at
递减限20偏移0)(查看:/home/said/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
现在,只需s
从created_at中删除多余的内容,然后在任何SQL编辑器(例如phpMyAdmin SQL编辑器)中测试此SQL!
注意:
该解决方案已通过Laravel 5.4进行了测试。
:id
DB::enableQueryLog();
$queries = DB::getQueryLog();
我认为,这将是初学者的最佳方法:
echo "<pre>";
print_r($query->toSql());
print_r($query->getBindings());
对于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()
{
//
}
}
如果您不是使用Laravel而是使用Eloquent软件包,则:
use \Illuminate\Database\Capsule\Manager as Capsule;
use \Illuminate\Events\Dispatcher;
use \Illuminate\Container\Container;
$capsule = new Capsule;
$capsule->addConnection([
// connection details
]);
// Set the event dispatcher used by Eloquent models... (optional)
$capsule->setEventDispatcher(new Dispatcher(new Container));
// Make this Capsule instance available globally via static methods... (optional)
$capsule->setAsGlobal();
// Setup the Eloquent ORM...(optional unless you've used setEventDispatcher())
$capsule->bootEloquent();
// Listen for Query Events for Debug
$events = new Dispatcher;
$events->listen('illuminate.query', function($query, $bindings, $time, $name)
{
// Format binding data for sql insertion
foreach ($bindings as $i => $binding) {
if ($binding instanceof \DateTime) {
$bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
} else if (is_string($binding)) {
$bindings[$i] = "'$binding'";`enter code here`
}
}
// Insert bindings into query
$query = str_replace(array('%', '?'), array('%%', '%s'), $query);
$query = vsprintf($query, $bindings);
// Debug SQL queries
echo 'SQL: [' . $query . ']';
});
$capsule->setEventDispatcher($events);
我创建了一些简单的函数来从某些查询中获取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()
完全没用 DB::listen
同样没用。当我说时$query->count()
,它显示了查询的一部分,但如果我这样做了$query->get()
,则无话可说。
似乎始终有效的唯一解决方案是有意在ORM参数中放入一些语法或其他错误,例如不存在的列/表名,在调试模式下在命令行上运行代码,这将吐出SQL错误最后用完整的frickin查询。否则,如果从Web服务器运行,则希望该错误出现在日志文件中。
如果您正在使用修补匠,并且想要记录形成的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",
}
>>>
尝试这个:
$results = DB::table('users')->toSql();
dd($results);
注意:get()已替换为toSql()以显示原始SQL查询。
我的操作方式是基于日志视图,只需要修改文件app/Providers/AppServiceProvider.php
:
app/Providers/AppServiceProvider.php
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
DB::listen(function ($query) {
$querySql = str_replace(['?'], ['\'%s\''], $query->sql);
$queryRawSql = vsprintf($querySql, $query->bindings);
Log::debug('[SQL EXEC]', [
"raw sql" => $queryRawSql,
"time" => $query->time,
]
);
});
}
$users = DB::table('users')
->select(DB::raw('count(*) as user_count, username '))
->where('uid', '>=', 10)
->limit(100)
->groupBy('username')
->get()
;
dd($users);
storage/logs/laravel-2019-10-27.log
:[2019-10-27 17:39:17] local.DEBUG: [SQL EXEC] {"raw sql":"select count(*) as user_count, username from `users` where `uid` >= '10' group by `username` limit 100","time":304.21}
echo User::where('status', 1)->toSql();