Как мне заставить конструктор запросов выводить свой сырой SQL-запрос со встроенными параметрами - PullRequest
0 голосов
/ 04 октября 2018

Учитывая следующий код:

DB::table('users')->where( 'gender' , '=', 'male', true)->toSql();
  1. Я получаю необработанную строку запроса SQL, но она использует параметры.

    select * from `users` where `gender`=?
    

    Можно ли как-нибудь встроить параметры?

  2. Можно ли сказать строителю не использовать обратные кавычки?теперь я использую DB::raw('gender') выражения, но это не то, что я хочу использовать.

Ответы [ 5 ]

0 голосов
/ 04 октября 2018

Некоторое время назад мне понадобился инструмент отладки, который мог бы представлять полный, легкий для чтения, копируемый / вставляемый SQL.В то время я использовал его для демонстрации ленивых нагрузок N + 1, которые снижали производительность.Поэтому я на самом деле проанализировал DebugBar, чтобы выяснить, как им это удалось, и придумал что-то, что звучало бы так, как будто оно подходит и вашим целям.

Это в основном просто переформатирует то, что Laravel ловит в журнале запросов.(Конечно, они действительно должны завершить выполнение, чтобы быть видимыми здесь.) Просто убедитесь, что, если вы используете какой-либо из методов raw, инкапсулированные имена полей в обратных галочках, или заглавные буквы будут выглядеть немного странно.

DB::enableQueryLog();
DB::flushQueryLog();

//Execute whatever code results in SQL queries

$queries = DB::getQueryLog();
DB::disableQueryLog();
DB::flushQueryLog();

$dbName = null;
$compiled = [];
foreach ($queries as $query) {
    if (DB::getDatabaseName() != $useDb) {
        $dbName = DB::getDatabaseName();
        $compiled[] = "USE `$dbName`;";
    }

    $sql = $query['query'];
    $values = $query['bindings'];

    $enclosures = [
        'back_tick' => '`',
        'apostrophe' => "'"
    ];

    $matches = [];
    foreach ($enclosures as $name => $enclosure) {
        $matches[$name] = [];
        preg_match_all("/$enclosure.*?$enclosure/", $sql, $matches[$name]);
        $matches[$name] = array_last($matches[$name]);
        $sql = preg_replace("/$enclosure.*?$enclosure/", "$enclosure?$enclosure", $sql);
    }

    $sql = strtoupper($sql);

    foreach ($enclosures as $name => $enclosure) {
        $sql = str_replace_array("$enclosure?$enclosure", $matches[$name], $sql);
    }

    $values = array_map(function ($value) {
        if (!is_numeric($value) && !is_null($value)) {
            $value = DB::connection()->getPdo()->quote($value);
        }
        return $value;
    }, $values);

    $sql = str_replace_array('?', $values, $sql);
    $sql = rtrim($sql, ';').';';

    $compiled[] = $sql;
}

Кстати, DB::getQueryLog() также включает время, необходимое для выполнения запроса, что делает его еще более полезным для диагностики проблем производительности.Просто имейте в виду, время соединения является фактором.Локальное размещение вашего приложения с удаленным доступом к базе данных займет больше времени, чем когда ваш проект фактически запущен.

0 голосов
/ 04 октября 2018

Если это не для отладки, вы можете использовать getBindings().

$q = \DB::table('contact')->where('created_at', '2018-01-01');
$sql = $q->toSql();
$bind = $q->getBindings();
$inline = vsprintf(str_replace("?", "'%s'", $sql), $bind);
echo $inline;

Очевидно, это работает только для однозначных типов, таких как int, date, string и т. Д. Если у вас есть массивывам нужно будет преобразовать $bind, чтобы его значения были только строками.

0 голосов
/ 04 октября 2018

Вы ищете метод getBindings () для получения фактических параметров.Так что-то вроде этого должно работать:

$completeSql = str_replace_array('?', $query->getBindings(), $query->toSql());

https://laravel.com/docs/5.7/helpers#method-str-replace-array для получения информации о хелпере str_replace_array (), который хорошо работает здесь.

И я думаю, что DB :: raw ()это способ избежать обратных кавычек без расширения содержимого.

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

DB::connection()->setSchemaGrammar(new YourExtendedMySqlGrammar());

https://laravel.com/docs/5.7/queries#raw-expressions для получения информации о необработанных выражениях.

0 голосов
/ 04 октября 2018

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

https://github.com/barryvdh/laravel-debugbar

0 голосов
/ 04 октября 2018
echo sprintf(str_replace('?', '%s',DB::table('users')->where( 'gender' , '=', 'male', true)->toSql()), 'male');

в качестве альтернативы вы можете включить ведение журнала запросов в вашей БД и посмотреть их там

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...