Как вывести сырой SQL-запрос в виде строки из билдера запросов?
Пожалуйста, переведите ниже описание проблемы на русский язык для StackOverflow.com:
У меня есть следующий код:
DB::table('users')->get();
Я хочу получить сырой SQL-запрос, который будет сгенерирован указанным конструктором запросов к базе данных. В этом примере это будет SELECT * FROM users
.
Как мне это сделать?
5 ответ(ов)
Чтобы получить SQL-запрос из экземпляра QueryBuilder
, вы можете использовать метод toSql()
. Например, вызов:
DB::table('users')->toSql();
возвратит:
select * from `users`
Это гораздо проще, чем настраивать слушателя событий, и также позволяет вам в любой момент проверить, как будет выглядеть запрос, пока вы его строите.
Обратите внимание: этот метод работает как для построителя запросов, так и для Eloquent, однако toSql()
используется вместо first()
или get()
. Вы не можете выполнить запрос и одновременно получить SQL-оператор с помощью этого метода.
DB::QueryLog()
работает только после выполнения запроса с помощью метода $builder->get()
.
Если вы хотите получить сырой SQL-запрос до или без его выполнения, вы можете использовать метод $builder->toSql()
.
Вот пример, как получить сырой SQL-запрос и заменить '?' на реальные значения привязки:
$query = str_replace(array('?'), array('\'%s\''), $builder->toSql());
$query = vsprintf($query, $builder->getBindings());
dump($query);
$result = $builder->get();
Кроме того, вы можете намеренно вызвать ошибку, например, используя несуществующую таблицу или столбец. В этом случае вы сможете увидеть сгенерированный запрос в сообщении исключения.
Вы можете прослушивать событие 'illuminate.query'. Перед выполнением запроса добавьте следующий слушатель события:
Event::listen('illuminate.query', function($query, $params, $time, $conn)
{
dd(array($query, $params, $time, $conn));
});
DB::table('users')->get();
Это выведет что-то вроде:
array(4) {
[0]=>
string(21) "select * from "users""
[1]=>
array(0) {
}
[2]=>
string(4) "0.94"
[3]=>
string(6) "sqlite"
}
Таким образом, вы сможете отследить выполняемые запросы, параметры, время выполнения и используемое соединение. Это очень полезно для отладки.
Если вы пытаетесь получить журналы запросов, используя Illuminate без Laravel, вы можете использовать следующий код:
\Illuminate\Database\Capsule\Manager::getQueryLog();
Также вы можете быстро создать функцию для форматирования запросов:
function logger()
{
$queries = \Illuminate\Database\Capsule\Manager::getQueryLog();
$formattedQueries = [];
foreach ($queries as $query) :
$prep = $query['query'];
foreach ($query['bindings'] as $binding) :
if (is_bool($binding)) {
$val = $binding === true ? 'TRUE' : 'FALSE';
} else if (is_numeric($binding)) {
$val = $binding;
} else {
$val = "'$binding'";
}
$prep = preg_replace("#\?#", $val, $prep, 1);
endforeach;
$formattedQueries[] = $prep;
endforeach;
return $formattedQueries;
}
ИСПРАВЛЕНИЕ
В новых версиях, похоже, журналирование запросов по умолчанию отключено (вызов выше вернет пустой массив). Чтобы включить его обратно, при инициализации Capsule Manager получите экземпляр соединения и вызовите метод enableQueryLog
:
$capsule::connection()->enableQueryLog();
СНОВА ИСПРАВЛЕНИЕ
Учитывая фактический вопрос, вы также можете сделать следующее, чтобы получить текущий один запрос вместо всех предыдущих:
$sql = $query->toSql();
$bindings = $query->getBindings();
В Eloquent есть метод для получения строки SQL запроса.
toSql()
В нашем случае:
DB::table('users')->toSql();
возвращает
select * from users
это точное решение, которое возвращает строку SQL запроса. Надеюсь, это поможет...
Как предотвратить SQL-инъекции в PHP?
Обновление данных в одной таблице из другой на основе совпадения ID
Функции startsWith() и endsWith() в PHP
Что такое потокобезопасность и непотокобезопасность в PHP?
Как получить расширение файла в PHP?