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

143

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

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

Результат

Array
(
)

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

  • 0
    Laravel Debugbar - отличный инструмент для регистрации запросов. У этого также есть много других удивительных особенностей.
Теги:
logging
laravel-5

10 ответов

222
Лучший ответ

По умолчанию журнал запросов отключен в 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. Несколько соединений DB

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

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

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

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

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

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

Для жизненного цикла HTTP-запроса вы можете включить журнал запросов в методе handle для некоторого BeforeAnyDbQueryMiddleware middleware, а затем восстановить выполненные запросы в методе 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()
        );
    }
}

Цепочка промежуточного слоя не будет выполняться для команд artisan, поэтому для выполнения 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();
}

Ссылки

  • 6
    Если ваша система использует более одного соединения с БД, вы должны указать это, в противном случае она может вернуть пустой массив: \DB::connection('myconnection')->enableQueryLog(); print_r(\DB::connection('myconnection')->getQueryLog());
  • 0
    Разместите свой комментарий как ответ @DianaR.
Показать ещё 4 комментария
35

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

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

  • 0
    Куда идет этот код? (5.4) Я пробовал контроллер, модель и искал промежуточное ПО, не зная, где его выполнить, прежде чем я получу ошибку db.
  • 0
    Если вы получаете ошибку при выполнении запроса, который останавливает выполнение, ошибка должна сообщить вам, в чем проблема. Если у вас отключены ошибки, вы можете проверить журнал ошибок в / storage / log / laravel или что-то в этом роде. (Я сейчас не за своим компьютером) Если вы говорите, что получаете ошибку при выполнении кода, который я предложил в своем ответе, убедитесь, что вы включаете фасад БД, где бы вы ни выполняли код. Не уверен, что вы пытаетесь сделать, но контроллер звучит как самый правильный из упомянутых вами вариантов. (Я обычно запускаю запросы в отдельных вспомогательных классах)
10

По-видимому, с 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);
    }
);
9

Поместите это на файл route.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 в комментариях.

8

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

DB::enableQueryLog();

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

2

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

  • 0
    Я получил белый экран, когда я попробовал это.
  • 0
    это сработало для меня
1

Вы просто выполните следующие шаги, если хотите распечатать запрос, перейдите к поставщику \laravel\framework\src\Illuminate\Database\connection.php

 protected $loggingQueries = false;

включить его, поставив true

 protected $loggingQueries = true;

и в контроллере u необходимо выполнить

dd(DB::getQueryLog());

вы получите желаемый результат

1

Этот код предназначен для:

  • 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 в базу данных.

0

Продолжая По-видимому, с Laravel 5.2 закрытие в DB:: listen получает только один параметр..., ответ выше: вы можете поместить этот код в промежуточное ПО script и использовать его в маршрутах.

Дополнительно:

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);
  • 0
    какую часть следует поместить в промежуточное ПО? который в маршрутах?
-2

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

 protected $loggingQueries = false;

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

protected $loggingQueries = true; 

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

  • 1
    Это плохая идея - редактировать файлы vendor . Они должны быть оригинальными.
  • 0
    @ shukshin.ivan Да, не нужно редактировать файлы вендора, но чтобы получить точный запрос, мы должны отредактировать этот код на какое-то время, тогда мы сможем изменить его обратно.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню