Получить сырой SQL запрос в Laravel (полное руководство)
Узнайте, как извлечь сырой SQL запрос из билдера запросов Laravel. Используйте toSql(), getBindings(), макросы и пакеты для отладки и оптимизации запросов для разработки.
Как получить строку исходного SQL‑запроса из билдера запросов Laravel?
Дан следующий код:
DB::table('users')->get();
Я хочу получить строку исходного SQL‑запроса, которую сгенерирует указанный выше билдер запросов. В этом примере это будет SELECT * FROM users.
Как это сделать?
Вы можете получить строку исходного SQL‑запроса из билдера запросов Laravel, используя метод toSql().
Для примера DB::table('users')->get() вызов toSql() на экземпляре билдера вернёт строку SELECT * FROM users, но запрос не будет выполнен.
Содержание
- Базовый метод toSql()
- Получение SQL с привязками
- Создание пользовательских макросов
- Использование пакетов
- Подходы к отладке
Базовый метод toSql()
Самый простой способ получить исходный SQL‑запрос – использовать метод toSql(), который возвращает строку SQL без выполнения запроса и без извлечения данных:
$query = DB::table('users')->where('id', 1);
$sql = $query->toSql();
Он вернёт:
select * from `users` where `id` = ?
Как объясняет Tinkerwell, этот метод полезен, когда вы не хотите изменять данные и просто хотите просмотреть сгенерированный SQL.
Получение SQL с привязками
Метод toSql() показывает запрос только с плейсхолдерами ?, но не реальными значениями. Чтобы получить полный SQL с заменёнными привязками, нужно объединить toSql() с getBindings():
Метод 1: Использование str_replace_array()
$query = DB::table('users')
->where('id', 1)
->where('email', 'test@example.com');
$sql = str_replace_array('?', $query->getBindings(), $query->toSql());
Для Laravel 5.8 и новее можно использовать фасад Str:
use Illuminate\Support\Str;
$sql = Str::replaceArray('?', $query->getBindings(), $query->toSql());
Метод 2: Использование vsprintf()
Как пишет Aryan Vania, можно применить vsprintf() для форматирования запроса:
$sql = vsprintf(str_replace('?', '%s', $query->toSql()), $query->getBindings());
Метод 3: Продвинутое управление привязками
Для более сложных сценариев с правильной экранизацией gist от Jesse Obrien предлагает надёжное решение:
use Illuminate\Database\Query\Builder;
Builder::macro('fullSql', function () {
$sql = str_replace(['%', '?'], ['%%', '%s'], $this->toSql());
$handledBindings = array_map(function ($binding) {
if (is_numeric($binding)) {
return $binding;
}
$value = str_replace(['\\', "'"], ['\\\\', "\\'"], $binding);
return "'{$value}'";
}, $this->getConnection()->prepareBindings($this->getBindings()));
return vsprintf($sql, $handledBindings);
});
// Использование:
$sql = $query->fullSql();
Создание пользовательских макросов
Вы можете расширить билдер запросов Laravel, создавая макросы в сервис‑провайдере. Как отмечает DEV Community:
// В AppServiceProvider.php
use Illuminate\Database\Query\Builder;
public function boot()
{
Builder::macro('toRawSql', function () {
return vsprintf(str_replace('?', '%s', $this->toSql()), $this->getBindings());
});
}
// Использование:
$sql = DB::table('users')->where('id', 1)->toRawSql();
Такой макрос добавит метод toRawSql(), который возвращает полный SQL‑строку с привязками.
Использование пакетов
Для более надёжного решения рассмотрите специализированные пакеты:
Пакет to-raw-sql
Как упомянуто в Reddit, пакет to-raw-sql предоставляет метод toRawSql():
composer require spiralaw/to-raw-sql
Laravel Debugbar
Arie Visser рекомендует использовать Laravel Debugbar, который автоматически отображает исходный SQL с привязками в панели отладки при выполнении запросов.
Подходы к отладке
Логирование запросов
Laracoding советует включить логирование запросов, чтобы захватить несколько запросов:
DB::enableQueryLog();
// Ваш запрос здесь
DB::table('users')->get();
$queries = DB::getQueryLog();
Laravel Debugbar
Для комплексной отладки Arie Visser предлагает использовать Laravel Debugbar, который автоматически показывает исходный SQL с привязками при выполнении запросов.
Источники
- How to get the raw SQL query from the Laravel Query Builder - Tinkerwell
- How to Extract Raw SQL Output from the Laravel Query Builder? 2 Easiest Solutions! - Medium
- How to Get the Raw SQL Query from Laravel Query Builder - DEV Community
- Six Ways to Get Raw SQL Output From Query Builder in Laravel - Arie Visser
- How do I get the query builder to output its raw SQL query as a string - Medium
- How to Get Raw SQL Query From Laravel Query Builder or Model - Laracoding
- How To Get The Raw SQL Query From Laravel’s Query Builder? - Uptimia
- toRawSql(): Get raw SQL from Laravel Query Builder and Eloquent Builder - Reddit
- Bind parameters into the SQL query for Laravel ORM - GitHub Gist
- Laravel how to get query with bindings? - Stack Overflow
Заключение
Чтобы получить строку исходного SQL‑запроса из билдера запросов Laravel:
- Используйте
toSql()для базового SQL без привязок. - Объедините с
getBindings()и методами замены строк для полного SQL с реальными значениями. - Создайте пользовательские макросы для повторного использования.
- Рассмотрите пакеты вроде
to-raw-sqlдля надёжной функциональности. - Используйте инструменты отладки как Laravel Debugbar во время разработки.
Наиболее распространённый подход – toSql() в сочетании с getBindings() и заменой строк, но для сложных приложений создание собственных макросов или использование специализированных пакетов обеспечивает лучшую поддерживаемость и надёжность генерации SQL.