Як оформити запит у Laravel 5? DB :: getQueryLog () Повернення порожнього масиву


172

Я намагаюся переглянути журнал запиту, але DB::getQueryLog()просто повертає порожній масив:

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

Результат

Array
(
)

Як я можу переглянути журнал цього запиту?


Відладчик Laravel - чудовий інструмент для реєстрації запитів. Він також має багато інших дивовижних особливостей.
totymedli

Відповіді:


256

За замовчуванням журнал запитів відключений у 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();
}

Список літератури


6
Якщо ваша система використовує більше одного db-з'єднання, вам потрібно вказати його, інакше він може повернути порожній масив:\DB::connection('myconnection')->enableQueryLog(); print_r(\DB::connection('myconnection')->getQueryLog());
Діана Р.

Залиште свій коментар як свою відповідь @DianaR.
Нарендрасінг Сісодія


Як увімкнути його для красного мовлення "NameController :: create ();" заява?
Рубен Руїс

2
Зауважте, що в Laravel 5.4 DB::listenфункція зворотного дзвінка має іншу підпис. Це більше так: DB::listen(function($query) { $sql = $query->sql; $bindings = $query->bindings; $time = $query->time; ... });
racl101

45

Якщо все, що вас справді цікавить, - це власний запит (останній запуск) для швидкої налагодження:

DB::enableQueryLog();

# your laravel query builder goes here

$laQuery = DB::getQueryLog();

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

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

зробити print_r()ON , $laQuery[0]щоб отримати повний запит, в тому числі і кріплень. ( $lcWhatYouWantзмінна, наведена вище, змінює змінні на ??)

Якщо ви використовуєте щось інше, ніж основне з'єднання mysql, вам потрібно буде скористатися цим:

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

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

(з назвою вашого з'єднання, де "mysql2")


1
куди ходить цей код? (5.4) Я спробував контролер, модель і заглянув у проміжне програмне забезпечення, не знаючи, де його виконати, перш ніж я отримаю помилку db.
блам

Якщо ви отримуєте помилку під час запуску запиту, який зупиняє виконання, помилка повинна повідомити вам, у чому проблема. Якщо у вас помилки вимкнено, ви можете перевірити вхід помилок / зберігання / журнал / laravel або щось подібне. (На даний момент я не на своєму комп’ютері) Якщо ви говорите про помилку запуску коду, який я запропонував у своїй відповіді, переконайтеся, що ви включаєте фасад БД, де б ви не використовували код. Не впевнений, що ви намагаєтеся зробити, але контролер звучить як найбільш правильний із згаданих вами варіантів. (Я зазвичай запускаю запити в окремих класах помічників)
Skeets

14

Помістіть це у файл 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 ви знайдете у коментарях.


Трохи брудно, але +1 для $ query-> прив'язки та $ query-> підказки
Paolo Stefan

Акуратно! Використовуючи це, відображаються результати у вікні перегляду, там, де відбувається запит!
Чарльз Вуд

14

Спочатку потрібно ввімкнути журнал запитів

DB::enableQueryLog();

Тоді ви можете отримати журнали запитів, просто:

dd(DB::getQueryLog());

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


11

Мабуть, із Laravel 5.2, закриття DB::listenотримує лише один параметр.

Отже, якщо ви хочете використовувати DB::listenLaravel 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 я додав своє рішення до stackoverflow.com/a/44920198/3823826
Csongor Halmai


5

Використовуйте toSql()замість get()цього:

$users = User::orderBy('name', 'asc')->toSql();
echo $users;
// Outputs the string:
'select * from `users` order by `name` asc'

2

(Laravel 5.2) Я вважаю, що найпростіший спосіб - просто додати один рядок коду для моніторингу sql запитів:

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

1

Продовжуючи мабуть з Laravel 5.2, закриття в БД :: прослуховування отримує лише один параметр ... відповідь вище: ви можете помістити цей код у сценарій 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);

яку частину потрібно помістити в проміжне програмне забезпечення? які в маршрутах?
користувач1016265

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

Я думаю, що відповідь міститься в цій статті: 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));
        });
    }
}

0

Припустимо, ви хочете надрукувати SQL-запит наступних операторів.

$user = User::find(5);

Вам просто потрібно зробити наступне:

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

$user = User::find(5);

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

Це надрукує останній виконаний запит у Laravel.


-3

Для laravel 5 і далі, використовуючи лише DB :: getQueryLog (), це не буде робити. За замовчуванням у цьому значенні

 protected $loggingQueries = false;

змінити його на

protected $loggingQueries = true; 

у файлі нижче для запиту реєстрації.

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

І тоді ми можемо скористатись тим, DB::getQueryLog()де ви хочете роздрукувати запит.


1
Це погана ідея редагувати vendorфайли. Вони повинні зберігатися в оригіналі.
shukshin.ivan

@ shukshin.ivan Так, ви не повинні редагувати файли постачальників, але щоб отримати точний запит, ми маємо час редагувати цей код, тоді ми можемо змінити його назад.
Рупалі Пемаре
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.