如何在 Laravel 5 中执行查询? DB::getQueryLog() 返回空数组
How to Get the Query Executed in Laravel 5? DB::getQueryLog() Returning Empty Array
我正在尝试查看查询日志,但 DB::getQueryLog()
只是返回一个空数组:
$user = User::find(5);
print_r(DB::getQueryLog());
结果
Array
(
)
如何查看此查询的日志?
默认情况下,查询日志在Laravel 5中被禁用:
https://github.com/laravel/framework/commit/e0abfe5c49d225567cb4dfd56df9ef05cc297448
您需要通过调用以下方式启用查询日志:
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。多个数据库连接
如果您有多个数据库连接,您必须指定记录哪个连接
为 my_connection
启用查询日志:
DB::connection('my_connection')->enableQueryLog();
获取 my_connection
的查询日志:
print_r(
DB::connection('my_connection')->getQueryLog()
);
2。在哪里启用查询日志?
对于 HTTP 请求生命周期,您可以在某些 `BeforeAnyDbQueryMiddleware` [中间件][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()
);
}
}
中间件链不会 运行 用于 artisan 命令,因此对于 CLI 执行,您可以在 artisan.start
事件侦听器中启用查询日志。
例如你可以把它放在bootstrap/app.php
文件
$app['events']->listen('artisan.start', function(){
\DB::enableQueryLog();
});
3。内存
Laravel 将所有查询保存在内存中。因此在某些情况下,例如当插入大量行时,或者 运行ning 作业包含大量查询时,这可能会导致应用程序使用过多的内存。
在大多数情况下,您只需要在调试时使用查询日志,如果是这种情况,我建议您只在开发时启用它。
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);
}
);
继续上面的 响应:您可以将此代码放入中间件脚本中并在路由中使用它。
此外:
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 提交,源代码在 this page。您会在评论中为 laravel 5.2 找到此 fix-code。
对于 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 或 dump.
例如:
DB::table('users')->where('votes', '>', 100)->dd();
或
DB::table('users')->where('votes', '>', 100)->dump();
我认为答案位于这篇文章中:
https://arjunphp.com/laravel-5-5-log-eloquent-queries/
实现查询日志记录快速简单。
您只需在 boot
方法中的 AppServiceProvider
添加一个回调来监听数据库查询:
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;
}
}
GET REPOSNSE 的准确方法
我正在尝试查看查询日志,但 DB::getQueryLog()
只是返回一个空数组:
$user = User::find(5);
print_r(DB::getQueryLog());
结果
Array
(
)
如何查看此查询的日志?
默认情况下,查询日志在Laravel 5中被禁用: https://github.com/laravel/framework/commit/e0abfe5c49d225567cb4dfd56df9ef05cc297448
您需要通过调用以下方式启用查询日志:
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。多个数据库连接
如果您有多个数据库连接,您必须指定记录哪个连接
为 my_connection
启用查询日志:
DB::connection('my_connection')->enableQueryLog();
获取 my_connection
的查询日志:
print_r(
DB::connection('my_connection')->getQueryLog()
);
2。在哪里启用查询日志?
对于 HTTP 请求生命周期,您可以在某些 `BeforeAnyDbQueryMiddleware` [中间件][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()
);
}
}
中间件链不会 运行 用于 artisan 命令,因此对于 CLI 执行,您可以在 artisan.start
事件侦听器中启用查询日志。
例如你可以把它放在bootstrap/app.php
文件
$app['events']->listen('artisan.start', function(){
\DB::enableQueryLog();
});
3。内存
Laravel 将所有查询保存在内存中。因此在某些情况下,例如当插入大量行时,或者 运行ning 作业包含大量查询时,这可能会导致应用程序使用过多的内存。
在大多数情况下,您只需要在调试时使用查询日志,如果是这种情况,我建议您只在开发时启用它。
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);
}
);
继续上面的
此外:
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 提交,源代码在 this page。您会在评论中为 laravel 5.2 找到此 fix-code。
对于 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 或 dump.
例如:
DB::table('users')->where('votes', '>', 100)->dd();
或
DB::table('users')->where('votes', '>', 100)->dump();
我认为答案位于这篇文章中: https://arjunphp.com/laravel-5-5-log-eloquent-queries/
实现查询日志记录快速简单。
您只需在 boot
方法中的 AppServiceProvider
添加一个回调来监听数据库查询:
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;
}
}
GET REPOSNSE 的准确方法