Answers:
默认情况下,Laravel 5中禁用了查询日志:https : //github.com/laravel/framework/commit/e0abfe5c49d225567cb4dfd56df9ef05cc297448
您将需要通过调用以下命令来启用查询日志:
DB::enableQueryLog();
或注册一个事件监听器:
DB::listen(
function ($sql, $bindings, $time) {
// $sql - select * from `ncv_users` where `ncv_users`.`id` = ? limit 1
// $bindings - [5]
// $time(in milliseconds) - 0.38
}
);
如果您有多个数据库连接,则必须指定要记录的连接
启用查询日志my_connection
:
DB::connection('my_connection')->enableQueryLog();
获取以下查询日志my_connection
:
print_r(
DB::connection('my_connection')->getQueryLog()
);
对于HTTP请求生命周期,可以在handle
某些BeforeAnyDbQueryMiddleware
中间件的方法中启用查询日志,然后terminate
在同一中间件的方法中检索执行的查询。
class BeforeAnyDbQueryMiddleware
{
public function handle($request, Closure $next)
{
DB::enableQueryLog();
return $next($request);
}
public function terminate($request, $response)
{
// Store or dump the log data...
dd(
DB::getQueryLog()
);
}
}
中间件链不会针对工匠命令运行,因此对于CLI执行,您可以在artisan.start
事件侦听器中启用查询日志。
例如,您可以将其放入bootstrap/app.php
文件中
$app['events']->listen('artisan.start', function(){
\DB::enableQueryLog();
});
Laravel将所有查询保留在内存中。因此,在某些情况下,例如插入大量行或长时间运行带有大量查询的作业时,这可能导致应用程序使用过多的内存。
在大多数情况下,您仅需要查询日志进行调试,如果是这种情况,我建议您仅将其用于开发。
if (App::environment('local')) {
// The environment is local
DB::enableQueryLog();
}
参考资料
\DB::connection('myconnection')->enableQueryLog(); print_r(\DB::connection('myconnection')->getQueryLog());
DB::listen
回调函数具有不同的签名。它更像是这样: DB::listen(function($query) { $sql = $query->sql; $bindings = $query->bindings; $time = $query->time; ... });
如果您真正关心的只是用于快速调试目的的实际查询(最后一个运行):
DB::enableQueryLog();
# your laravel query builder goes here
$laQuery = DB::getQueryLog();
$lcWhatYouWant = $laQuery[0]['query']; # <-------
# optionally disable the query log:
DB::disableQueryLog();
做一个print_r()
上$laQuery[0]
得到充分的查询,包括绑定。($lcWhatYouWant
上面的变量会将变量替换为??
)
如果您使用的不是主要的mysql连接,则需要改用以下这些:
DB::connection("mysql2")->enableQueryLog();
DB::connection("mysql2")->getQueryLog();
(连接名称为“ mysql2”)
把它放在routes.php文件上:
\Event::listen('Illuminate\Database\Events\QueryExecuted', function ($query) {
echo'<pre>';
var_dump($query->sql);
var_dump($query->bindings);
var_dump($query->time);
echo'</pre>';
});
由msurguy提交,此页面中的源代码。您将在注释中找到laravel 5.2的此修复代码。
显然在Laravel 5.2中,闭包DB::listen
仅接收一个参数。
因此,如果要DB::listen
在Laravel 5.2中使用,则应执行以下操作:
DB::listen(
function ($sql) {
// $sql is an object with the properties:
// sql: The query
// bindings: the sql query variables
// time: The execution time for the query
// connectionName: The name of the connection
// To save the executed queries to file:
// Process the sql and the bindings:
foreach ($sql->bindings as $i => $binding) {
if ($binding instanceof \DateTime) {
$sql->bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
} else {
if (is_string($binding)) {
$sql->bindings[$i] = "'$binding'";
}
}
}
// Insert bindings into query
$query = str_replace(array('%', '?'), array('%%', '%s'), $sql->sql);
$query = vsprintf($query, $sql->bindings);
// Save the query to file
$logFile = fopen(
storage_path('logs' . DIRECTORY_SEPARATOR . date('Y-m-d') . '_query.log'),
'a+'
);
fwrite($logFile, date('Y-m-d H:i:s') . ': ' . $query . PHP_EOL);
fclose($logFile);
}
);
对于laravel 5.8,您只需添加dd或dump即可。
例如:
DB::table('users')->where('votes', '>', 100)->dd();
要么
DB::table('users')->where('votes', '>', 100)->dump();
使用toSql()
而不是get()
像这样:
$users = User::orderBy('name', 'asc')->toSql();
echo $users;
// Outputs the string:
'select * from `users` order by `name` asc'
在继续使用Laravel 5.2进行“ 表观”时,DB :: listen中的闭包仅收到一个参数...上面的响应:您可以将此代码放入Middleware脚本中,并在路由中使用它。
另外:
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$log = new Logger('sql');
$log->pushHandler(new StreamHandler(storage_path().'/logs/sql-' . date('Y-m-d') . '.log', Logger::INFO));
// add records to the log
$log->addInfo($query, $data);
该代码用于:
这是基于@milz答案的代码:
DB::listen(function($sql) {
$LOG_TABLE_NAME = 'log';
foreach ($sql->bindings as $i => $binding) {
if ($binding instanceof \DateTime) {
$sql->bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
} else {
if (is_string($binding)) {
$sql->bindings[$i] = "'$binding'";
}
}
}
// Insert bindings into query
$query = str_replace(array('%', '?'), array('%%', '%s'), $sql->sql);
$query = vsprintf($query, $sql->bindings);
if(stripos($query, 'insert into `'.$LOG_TABLE_NAME.'`')===false){
$toLog = new LogModel();
$toLog->uId = 100;
$toLog->sql = $query;
$toLog->save();
}
});
核心是该if(stripos...
行,它防止了将insert into log
sql语句插入数据库的递归操作。
我认为本文中的答案:https : //arjunphp.com/laravel-5-5-log-eloquent-queries/
实现查询记录的快速简便的方法。
您只需要AppServiceProvider
在boot
方法中添加回调即可监听数据库查询:
namespace App\Providers;
use DB;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
DB::listen(function($query) {
logger()->info($query->sql . print_r($query->bindings, true));
});
}
}
假设您要打印以下语句的SQL查询。
$user = User::find(5);
您只需要执行以下操作:
DB::enableQueryLog();//enable query logging
$user = User::find(5);
print_r(DB::getQueryLog());//print sql query
这将在Laravel中打印最后执行的查询。
对于laravel 5及更高版本,仅使用DB :: getQueryLog()不会这样做。默认情况下,此值
protected $loggingQueries = false;
更改为
protected $loggingQueries = true;
在以下文件中进行日志记录查询。
/vendor/laravel/framework/src/illuminate/Database/Connection.php
然后,我们可以使用要在DB::getQueryLog()
其中打印查询的位置。
vendor
文件是个坏主意。它们必须保持原始。