Как выполнить запрос в Laravel 5? DB::getQueryLog возвращает пустой массив

Я пытаюсь просмотреть журнал для запроса, но DB::getQueryLog() просто возвращает пустой массив:

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

результат:

Array
(
)

Как я могу просмотреть журнал для этого запроса?

15 ответов

Решение

По умолчанию журнал запросов отключен в 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 
    }
);  

Некоторые советы

1. Несколько соединений с БД

Если у вас есть более одного подключения к БД, вы должны указать, какое соединение регистрировать

Чтобы включить журнал запросов для my_connection:

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

Чтобы получить журнал запросов для my_connection:

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

2. Где включить журнал запросов?

Для жизненного цикла 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();
});

3. Память

Laravel хранит все запросы в памяти. Поэтому в некоторых случаях, например при вставке большого количества строк или при длительном выполнении задания с большим количеством запросов, это может привести к тому, что приложение будет использовать избыточную память.

В большинстве случаев вам понадобится журнал запросов только для отладки, и в этом случае я бы порекомендовал включить его только для разработки.

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

Рекомендации

Если все, что вас действительно волнует, это фактический запрос (последний запущенный) для целей быстрой отладки:

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

Вы должны сначала включить ведение журнала запросов

DB::enableQueryLog();

Было бы лучше, если вы включите ведение журнала запросов перед запуском приложения, что вы можете сделать в BeforeMiddleware, а затем извлечь выполненные запросы в AfterMiddleware.

Поместите это в файл rout.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);
    }
);

Использование 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://laravel.com/docs/5.8/queries

(Laravel 5.2) Я считаю, что самый простой способ - просто добавить одну строку кода для мониторинга SQL-запросов:\DB::listen(function($sql) {var_dump($sql); });

Предположим, вы хотите распечатать SQL-запрос следующих операторов.

$user = User::find(5);

Вам просто нужно сделать следующее:

DB::enableQueryLog();//enable query logging

$user = User::find(5);

print_r(DB::getQueryLog());//print sql query

Это напечатает последний выполненный запрос в Laravel.

Выполнение запроса

      \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;
   }
}

Точный метод ПОЛУЧЕНИЯ ОТЧЕТА

Этот код для:

  • Ларавел 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 заявление в базу данных.

В продолжение, по- видимому, с 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);

Думаю, ответ находится в этой статье: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));
        });
    }
}

Добавьте эту функцию в свой вспомогательный файл и просто вызовите.

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"

Для laravel 5 и далее использование только DB:: getQueryLog () не подойдет. По умолчанию в этом значение

 protected $loggingQueries = false;

измените это на

protected $loggingQueries = true; 

в файле ниже для регистрации запроса. /vendor/laravel/framework/src/illuminate/Database/Connection.php И тогда мы можем использовать DB::getQueryLog(), где вы хотите напечатать запрос.

Другие вопросы по тегам