如何在Laravel 5中执行查询?DB::getQueryLog()返回空数组

我试图查看日志查询,但DB::getQueryLog()只是返回一个空数组:

$user = User::find(5);
print_r(DB::getQueryLog());

结果

Array
(
)

如何查看此查询的日志?

321099 次浏览

Laravel 5默认关闭查询日志功能。 https://github.com/laravel/framework/commit/e0abfe5c49d225567cb4dfd56df9ef05cc297448 < / p >

您需要通过调用以下命令来启用查询日志:

DB::enableQueryLog();


// and then you can get query log


dd(DB::getQueryLog());

或者注册一个事件监听器:

DB::listen(
function ($sql, $bindings, $time) {
//  $sql - select * from `ncv_users` where `ncv_users`.`id` = ? limit 1
//  $bindings - [5]
//  $time(in milliseconds) - 0.38
}
);

一些技巧

1. 多个DB连接

如果有多个DB连接,则必须指定要记录哪个连接

开启my_connection的查询日志:

DB::connection('my_connection')->enableQueryLog();

获取my_connection的查询日志:

print_r(
DB::connection('my_connection')->getQueryLog()
);

2. 在哪里启用查询日志?

对于HTTP请求生命周期,您可以在一些' BeforeAnyDbQueryMiddleware ' [middleware][1]的' handle '方法中启用查询日志,然后在同一中间件的[' terminate '][2]方法中检索已执行的查询。
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();
});

3.内存

Laravel将所有查询保存在内存中。因此,在某些情况下,例如插入大量行的时候,或者有一个长时间运行的带有大量查询的作业时,这可能会导致应用程序使用多余的内存。

在大多数情况下,您只需要调试查询日志,如果是这种情况,我建议您只在开发时启用它。

if (App::environment('local')) {
// The environment is local
DB::enableQueryLog();
}

参考文献

您需要首先启用查询日志记录

DB::enableQueryLog();

您可以通过以下方式获取查询日志:

dd(DB::getQueryLog());

如果在应用程序启动之前启用查询日志记录,效果会更好,您可以在BeforeMiddleware中这样做,然后在AfterMiddleware中检索已执行的查询。

显然,在Laravel 5.2中,DB::listen中的闭包只接收一个参数。

因此,如果你想在Laravel 5.2中使用DB::listen,你应该这样做:

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.2中,DB::listen中的闭包只接收一个参数…响应:你可以把这段代码放到中间件脚本中,并在路由中使用它。

另外:

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);

这段代码用于:

  • Laravel 5.2
  • 将语句记录到mysql数据库中

下面是基于@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语句递归插入数据库。

如果你真正关心的是实际的查询(最后一次运行),以便快速调试:

DB::enableQueryLog();


# your laravel query builder goes here


$laQuery = DB::getQueryLog();


$lcWhatYouWant = $laQuery[0]['query']; # <-------


# optionally disable the query log:
DB::disableQueryLog();

$laQuery[0]上执行print_r()来获得完整的查询,包括绑定。(上面的$lcWhatYouWant变量将被替换为??变量)

如果你使用的不是主mysql连接,你需要使用这些:

DB::connection("mysql2")->enableQueryLog();


DB::connection("mysql2")->getQueryLog();

(使用“mysql2”所在的连接名)

(Laravel 5.2)我发现最简单的方法就是添加一行代码来监视sql查询:

\DB::listen(function($sql) {var_dump($sql); });

把这个放到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及以上版本,仅使用DB::getQueryLog()是不行的。 默认值为

 protected $loggingQueries = false;

改为

protected $loggingQueries = true;

在下面的文件中进行日志查询。

/vendor/laravel/framework/src/illuminate/Database/Connection.php

然后我们可以在想要打印查询的地方使用DB::getQueryLog()

使用toSql()代替get(),如下所示:

$users = User::orderBy('name', 'asc')->toSql();


echo $users;


// Outputs the string:
'select * from `users` order by `name` asc'

对于laravel 5.8,只需添加dd转储

例:

DB::table('users')->where('votes', '>', 100)->dd();

DB::table('users')->where('votes', '>', 100)->dump();
< p >参考: https://laravel.com/docs/5.8/queries#debugging < / p >
我认为答案就在这篇文章中: https://arjunphp.com/laravel-5-5-log-eloquent-queries/ < / p >

是快速简单地实现查询日志。

你只需要在boot方法的AppServiceProvider中添加一个回调来监听DB查询:

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中最后执行的查询。

将这个函数添加到您的助手文件中,然后简单地调用。

function getRawQuery($sql){
$query = str_replace(array('?'), array('\'%s\''), $sql->toSql());
$query = vsprintf($query, $sql->getBindings());
return $query;
}

输出:"select * from user where status = '1' order by id desc limit 25 offset 0"

查询执行

\Event::listen('Illuminate\Database\Events\QueryExecuted', function ($query) {
$sql = $query->sql;
$time = $query->time;
$connection = $query->connection->getName();
 

Log::debug('query : '.$sql);
Log::debug('time '.$time);
Log::debug('connection '.$connection);
});

查询

StaffRegister::all();

输出

[2021-03-14 08:00:57] local.DEBUG: query : select * from `staff_registers`
[2021-03-14 08:00:57] local.DEBUG: time 0.93
[2021-03-14 08:00:57] local.DEBUG: connection mysql

完整的结构

<?php


namespace App\Http\Controllers;


use Illuminate\Support\Facades\Log;
use App\Models\StaffRegister;


class AuthController extends Controller
{
public function index(){
   

\Event::listen('Illuminate\Database\Events\QueryExecuted', function ($query) {
      

$sql = $query->sql;
$time = $query->time;
$connection = $query->connection->getName();


Log::debug('query : '.$sql);
Log::debug('time '.$time);
Log::debug('connection '.$connection);
});


$obj = StaffRegister::all();
    

return $obj;
}
}

准确的方法得到休息