Как получить построитель запросов для вывода его необработанного SQL-запроса в виде строки?
545
Учитывая следующий код:
DB::table('users')->get();
Я хочу получить необработанную строку запроса SQL, которую сгенерирует построитель запросов базы данных выше. В этом примере это было бы SELECT * FROM users.
Может быть даже лучше вывести его в журнал вашего приложения, используя Logкласс: Log::debug(DB::getQueryLog())
msturdy
35
Возможно, вам понадобится включить это, так как сейчас оно по умолчанию отключено. Вы можете использовать эту команду, чтобы временно включить ее:DB::enableQueryLog();
Джошуа Фрик
5
Я попробовал твой ответ. То, что я пытался, DB::enableQueryLog(); dd(DB::getQueryLog());но это возвращается только []....
Я самый глупый человек
6
Если у вас есть несколько баз данных, вам может потребоваться сделать этоDB::connection('database')->getQueryLog()
Damien Ó Ceallaigh
745
Используйте toSql()метод на QueryBuilderэкземпляре.
DB::table('users')->toSql() вернется:
выберите * из `users`
Это проще, чем подключить прослушиватель событий, а также позволяет проверить, как будет выглядеть запрос в любой момент, пока вы его создаете.
Я думаю, что это самый простой способ при использовании Eloquent вне Laravel
Gab
8
@Stormsson Это невозможно, потому что PHP никогда не заменяет запрос связанными значениями. Чтобы получить запросы в полном объеме, вам нужно зарегистрировать их в MySQL. Больше информации здесь: stackoverflow.com/questions/1786322/…
Матфея
40
@Stormsson вы можете использовать getBindingsметод. Это вернет привязки для того, чтобы они были связаны с оператором SQL.
danronmoon
2
Очень полезно для отладки сложных запросов, которые Eloquent отказывается выполнять, так как они не отображаются в журнале запросов.
BobChao87
34
Получить запрос с привязками$query = \DB::table('users')->where('id', 10); $sql = str_replace_array('?', $query->getBindings(), $query->toSql()); dd($sql);
Эннио Соуза
88
DB::QueryLog()работать только после выполнения запроса $builder->get(). Если вы хотите получить запрос до его выполнения, вы можете использовать $builder->toSql()метод. Вот пример, как получить sql и связать его:
Это, безусловно, лучший ответ, простой и прямой к сути. Спасибо :)
Собакус
18
Как однострочник:$query = vsprintf(str_replace(array('?'), array('\'%s\''), $builder->toSql()), $builder->getBindings());
kramer65
Это должно быть включено во фреймворк как нативная функция .. спасибо
Томаш Млезива
Обратите внимание, что это не будет работать, если ваш запрос уже имеет знаки процента, например, для LIKEзапроса или при форматировании дат. Вам нужно сначала убежать с двойными знаками процента.
Неизвестный Дев
Есть ли проблемы безопасности при этом? Обеззаражены ли крепления $builder->getBindings()?
Солидо
56
Вы можете прослушать событие «световые запросы». Перед запросом добавьте следующий прослушиватель событий:
обновленные версии, по-видимому, по умолчанию отключают ведение журнала запросов (приведенное выше возвращает пустой массив). Чтобы снова включить, при инициализации Capsule Manager захватите экземпляр соединения и вызовите enableQueryLogметод
$capsule::connection()->enableQueryLog();
ИЗМЕНИТЬ СНОВА
Принимая во внимание фактический вопрос, вы могли бы фактически сделать следующее, чтобы преобразовать текущий одиночный запрос вместо всех предыдущих запросов:
я получаю этот тип возврата из запроса "name = [{" name ":" rifat "}]" что мне нужно сделать, чтобы получить только "name = rifat"?
бестелесный
Я бы распечатал ваши привязки, похоже, вы передаете массив вместо строки
Люк Сноуден
Это полезное начало, но, кажется, не следует добавлять одинарные кавычки вокруг параметризованных значений, например, когда я передаю строку вроде 'US/Eastern'.
Райан
1
@ Райан, это правда, поэтому я и сказал quick function. Я полагаю, что базовый код будет использовать методы prepare ( php.net/manual/en/mysqli.prepare.php ), поэтому ?требуется только метод . Вы можете php.net/manual/en/function.is-numeric.php, чтобы определить, следует ли инкапсулировать ввод в одинарные кавычки.
Люк Сноуден
1
@LukeSnowden Ваш ответ гениален! Я наконец нашел время, чтобы опробовать вашу новую версию (которую я отредактировал выше, чтобы включить вашу is_numericидею), и она работает! Мне это нравится. Спасибо.
Райан
36
В eloquent есть метод для получения строки запроса.
toSql ()
в нашем случае
DB::table('users')->toSql();
возвращение
select*from users
это точное решение, которое возвращает строку запроса SQL .. Надеюсь, это полезно ...
Ответ улучшен, чтобы включить все замечания, сделанные в комментариях. Большое спасибо.
Евгений Афанасьев
13
Сначала вам нужно будет включить журнал запросов, позвонив:
DB::enableQueryLog();
после запросов с использованием фасада БД вы можете написать:
dd(DB::getQueryLog());
вывод будет как ниже:
array:1[▼0=> array:3[▼"query"=>"select * from `users` left join `website_user` on `users`.`id` = `website_user`.`user_id` left join `region_user` on `users`.`id` = `region_user`.`user_id` left ▶""bindings"=> array:5[▶]"time"=>3.79]]
Привет, я использовал $ result = DB :: select ('select * from sqrt_user_modules, где user_id =: id', ['id' => $ user]); DB :: enableQueryLog (); но не получил никакого вывода dd (DB :: getQueryLog ());
Anoop PS
нужно ли нам включать какую-либо библиотеку
Anoop PS
1
Шаг 1: DB :: enableQueryLog (); шаг 2: $ result = DB :: select ('select * from sqrt_user_modules, где user_id =: id', ['id' => $ user]); шаг 3: дд (DB :: getQueryLog ());
Рави Грива
13
Это лучшее решение, которое я могу предложить любому для отладки красноречивого последнего или последнего запроса, хотя это также обсуждалось:
Примечание: с Laravel 5.1 до 5.3, поскольку Eloquent Builder не использует эту Macroableчерту, не может добавлять toRawSqlпсевдоним Eloquent Builder на лету. Следуйте приведенному ниже примеру, чтобы добиться того же.
Функция прослушивания полезна, объявляйте ее перед выполнением запроса и выводите sql & bindings в методе. Несовершенный, но работает быстрее / проще, чем другие ответы.
Андрей
7
Самый простой способ - сделать преднамеренную ошибку . Например, я хочу увидеть полный запрос SQL следующего отношения:
(4/4) ErrorException SQLSTATE [42S22]: Column не найдено: 1054 Неизвестные колонки 'eqtype_jobs.created_ats' в 'списке полей' (SQL: выберите
jobs*. eqtype_jobs. , set_idКак pivot_set_id,
eqtype_jobs. , job_idКак pivot_job_id, eqtype_jobs. , created_ats
Как pivot_created_ats, eqtype_jobs. , updated_atКак
pivot_updated_at, eqtype_jobs. , idКак pivot_idиз jobsвнутреннее соединение eqtype_jobsс jobs. id= eqtype_jobs. , job_idгде
eqtype_jobs. set_id= 56 упорядочить по pivot_created_atпределу по убыванию 20 смещение 0) (Вид: /home/said/www/factory/resources/views/set/show.blade.php)
Приведенное выше сообщение об ошибке возвращает полный запрос SQL с ошибкой
SQL:select jobs.*, eqtype_jobs.set_id as pivot_set_id, eqtype_jobs.job_id as pivot_job_id, eqtype_jobs.created_ats as pivot_created_ats, eqtype_jobs.updated_at as pivot_updated_at, eqtype_jobs.id as pivot_id from jobs inner join eqtype_jobs on jobs.id = eqtype_jobs.job_id where eqtype_jobs.set_id =56 order by pivot_created_at desc limit 20 offset 0
Теперь просто удалите лишний sиз созданного_атла и протестируйте этот SQL, как вам нравится, в любом редакторе SQL, таком как редактор SQL phpMyAdmin!
Это лучший ответ на сегодняшний день! Так просто! :)
Пикард
Это не будет отображаться запрос с креплениями, т.е. привязок покажет как:id
Shantha Кумара
@ShanthaKumara Действительно, я не знаю, какую версию или конфигурацию Laravel вы использовали. Однако каждый фрагмент или код в моем ответе был скопирован и вставлен из вывода реального кода проекта Laravel 5.4.
СаидбакР
6
Чтобы увидеть выполненный запрос Laravel, используйте журнал запросов laravel
Если вы хотите получать каждый SQL-запрос, выполняемый вашим приложением, вы можете использовать метод listen. Этот метод полезен для регистрации запросов или отладки. Вы можете зарегистрировать прослушиватель запросов у поставщика услуг:
<?php
namespaceApp\Providers;useIlluminate\Support\Facades\DB;useIlluminate\Support\ServiceProvider;classAppServiceProviderextendsServiceProvider{/**
* Bootstrap any application services.
*
* @return void
*/publicfunction boot(){
DB::listen(function($query){// $query->sql// $query->bindings// $query->time});}/**
* Register the service provider.
*
* @return void
*/publicfunctionregister(){//}}
Clockwork - это расширение для Chrome для разработки на PHP, расширяющее Инструменты разработчика новой панелью, предоставляющей все виды информации, полезной для отладки и профилирования ваших приложений PHP, включая информацию о запросах, заголовках, получении и публикации данных, файлах cookie, данных сеансов, запросах к базе данных, маршруты, визуализация времени выполнения приложения и многое другое.
Я создал несколько простых функций для получения SQL и привязок из некоторых запросов.
/**
* getSql
*
* Usage:
* getSql( DB::table("users") )
*
* Get the current SQL and bindings
*
* @param mixed $query Relation / Eloquent Builder / Query Builder
* @return array Array with sql and bindings or else false
*/function getSql($query){if( $query instanceofIlluminate\Database\Eloquent\Relations\Relation ){
$query = $query->getBaseQuery();}if( $query instanceofIlluminate\Database\Eloquent\Builder ){
$query = $query->getQuery();}if( $query instanceofIlluminate\Database\Query\Builder ){return['query'=> $query->toSql(),'bindings'=> $query->getBindings()];}returnfalse;}/**
* logQuery
*
* Get the SQL from a query in a closure
*
* Usage:
* logQueries(function() {
* return User::first()->applications;
* });
*
* @param closure $callback function to call some queries in
* @return Illuminate\Support\Collection Collection of queries
*/function logQueries(closure $callback){// check if query logging is enabled
$logging = DB::logging();// Get number of queries
$numberOfQueries = count(DB::getQueryLog());// if logging not enabled, temporarily enable itif(!$logging ) DB::enableQueryLog();
$query = $callback();
$lastQuery = getSql($query);// Get querylog
$queries =newIlluminate\Support\Collection( DB::getQueryLog());// calculate the number of queries done in callback
$queryCount = $queries->count()- $numberOfQueries;// Get last queries
$lastQueries = $queries->take(-$queryCount);// disable query loggingif(!$logging ) DB::disableQueryLog();// if callback returns a builder object, return the sql and bindings of itif( $lastQuery ){
$lastQueries->push($lastQuery);}return $lastQueries;}
Применение:
getSql( DB::table('users'));// returns // [// "sql" => "select * from `users`",// "bindings" => [],// ]
getSql( $project->rooms());// returns// [// "sql" => "select * from `rooms` where `rooms`.`project_id` = ? and `rooms`.`project_id` is not null",// "bindings" => [ 7 ],// ]
Столько, сколько я люблю эту структуру, я ненавижу, когда она действует как дерьмо.
DB::enableQueryLog()совершенно бесполезно. DB::listenодинаково бесполезен. Когда я сказал $query->count(), он показал часть запроса , но если я это сделаю $query->get(), ему нечего сказать.
Единственное решение, которое, по-видимому, работает согласованно, - это преднамеренно поместить некоторый синтаксис или другую ошибку в параметры ORM, например, несуществующее имя столбца / таблицы, запустить код в командной строке в режиме отладки, и он выдаст ошибку SQL. наконец, с полным проклятым запросом. В противном случае, мы надеемся, что ошибка появится в файле журнала при запуске с веб-сервера.
$users = DB::table('users')->select(DB::raw('count(*) as user_count, username '))->where('uid','>=',10)->limit(100)->groupBy('username')->get();
dd($users);
Смотрите журнал storage/logs/laravel-2019-10-27.log:
[2019-10-2717:39:17]local.DEBUG:[SQL EXEC]{"raw sql":"select count(*) as user_count, username from `users` where `uid` >= '10' group by `username` limit 100","time":304.21}
echo User::where('status', 1)->toSql();
Ответы:
Для вывода на экран последних выполненных запросов вы можете использовать это:
Я считаю, что самые последние запросы будут в нижней части массива.
У вас будет что-то вроде этого:
(Благодаря комментарию Джошуа ниже.)
источник
Log
класс:Log::debug(DB::getQueryLog())
DB::enableQueryLog();
DB::enableQueryLog(); dd(DB::getQueryLog());
но это возвращается только[]
....DB::connection('database')->getQueryLog()
Используйте
toSql()
метод наQueryBuilder
экземпляре.DB::table('users')->toSql()
вернется:Это проще, чем подключить прослушиватель событий, а также позволяет проверить, как будет выглядеть запрос в любой момент, пока вы его создаете.
источник
getBindings
метод. Это вернет привязки для того, чтобы они были связаны с оператором SQL.$query = \DB::table('users')->where('id', 10); $sql = str_replace_array('?', $query->getBindings(), $query->toSql()); dd($sql);
DB::QueryLog()
работать только после выполнения запроса$builder->get()
. Если вы хотите получить запрос до его выполнения, вы можете использовать$builder->toSql()
метод. Вот пример, как получить sql и связать его:ИЛИ просто сделайте ваш запрос ошибки, например, вызов несуществующей таблицы или столбца, вы увидите сгенерированный запрос в исключении XD
источник
$query = vsprintf(str_replace(array('?'), array('\'%s\''), $builder->toSql()), $builder->getBindings());
LIKE
запроса или при форматировании дат. Вам нужно сначала убежать с двойными знаками процента.$builder->getBindings()
?Вы можете прослушать событие «световые запросы». Перед запросом добавьте следующий прослушиватель событий:
Это распечатает что-то вроде:
источник
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Event;
вы можете просто сделать,use Event;
так как это фасад .Если вы пытаетесь получить Журнал с помощью Illuminate без использования Laravel:
Вы также можете добавить быструю функцию, например, так:
РЕДАКТИРОВАТЬ
обновленные версии, по-видимому, по умолчанию отключают ведение журнала запросов (приведенное выше возвращает пустой массив). Чтобы снова включить, при инициализации Capsule Manager захватите экземпляр соединения и вызовите
enableQueryLog
методИЗМЕНИТЬ СНОВА
Принимая во внимание фактический вопрос, вы могли бы фактически сделать следующее, чтобы преобразовать текущий одиночный запрос вместо всех предыдущих запросов:
источник
'US/Eastern'
.quick function
. Я полагаю, что базовый код будет использовать методы prepare ( php.net/manual/en/mysqli.prepare.php ), поэтому?
требуется только метод . Вы можете php.net/manual/en/function.is-numeric.php, чтобы определить, следует ли инкапсулировать ввод в одинарные кавычки.is_numeric
идею), и она работает! Мне это нравится. Спасибо.В eloquent есть метод для получения строки запроса.
toSql ()
в нашем случае
возвращение
это точное решение, которое возвращает строку запроса SQL .. Надеюсь, это полезно ...
источник
->where('foo', '=', 'bar')
бар не будет показывать в sqlисточник
->toSql()
как если бы после модели было больше аргументов. НапримерUser::where('id', 1)->toSql()
Если вы используете laravel 5.1 и MySQL, вы можете использовать эту функцию, сделанную мной:
В качестве входного параметра вы можете использовать любой из этих
источник
Сначала вам нужно будет включить журнал запросов, позвонив:
после запросов с использованием фасада БД вы можете написать:
вывод будет как ниже:
источник
Это лучшее решение, которое я могу предложить любому для отладки красноречивого последнего или последнего запроса, хотя это также обсуждалось:
источник
Первый способ:
Просто вы можете делать следующие вещи, используя
toSql()
метод,Если он не работает, вы можете настроить его из документации Laravel .
Второй способ:
Еще один способ сделать это
DB::getQueryLog()
но если он возвращает пустой массив, то по умолчанию он отключен, посетите это ,
просто включите,
DB::enableQueryLog()
и это будет работать :)для получения дополнительной информации посетите Github Issue, чтобы узнать больше об этом.
Надеюсь, поможет :)
источник
«Macroable» замена , чтобы получить SQL запрос с креплениями.
Добавьте ниже макрос-функцию в метод.
AppServiceProvider
boot()
Добавьте псевдоним для Eloquent Builder. ( Laravel 5.4+ )
Затем отлаживайте как обычно. ( Laravel 5.4+ )
Например, Query Builder
Например, Eloquent Builder
Например, Eloquent Builder ( Laravel 5.1 - 5.3 )
источник
использовать пакет debugbar
источник
От Laravel
5.2
и далее. Вы можете использовать,DB::listen
чтобы получить выполненные запросы.Или, если вы хотите отладить один
Builder
экземпляр, вы можете использоватьtoSql
метод.источник
Самый простой способ - сделать преднамеренную ошибку . Например, я хочу увидеть полный запрос SQL следующего отношения:
Я просто делаю столбец, который не будет найден, здесь я выбираю
created_at
и изменил егоcreated_ats
, добавив трейлингs
:Итак, отладчик вернет следующую ошибку:
Приведенное выше сообщение об ошибке возвращает полный запрос SQL с ошибкой
Теперь просто удалите лишний
s
из созданного_атла и протестируйте этот SQL, как вам нравится, в любом редакторе SQL, таком как редактор SQL phpMyAdmin!источник
:id
Чтобы увидеть выполненный запрос Laravel, используйте журнал запросов laravel
источник
Начиная с Laravel 5.8.15, у построителя запросов теперь есть
dd
иdump
методы, так что вы можете делатьисточник
Это функция, которую я поместил в свой базовый класс модели. Просто передайте объект построителя запросов в него, и строка SQL будет возвращена.
источник
На мой взгляд, это будет лучший подход для начинающих:
Это также изображено здесь. https://stackoverflow.com/a/59207557/9573341
источник
Для laravel 5.5.X
Если вы хотите получать каждый SQL-запрос, выполняемый вашим приложением, вы можете использовать метод listen. Этот метод полезен для регистрации запросов или отладки. Вы можете зарегистрировать прослушиватель запросов у поставщика услуг:
Источник
источник
Добавьте эту функцию в ваше приложение и просто позвоните.
Вывод : "выберите * из
user
гдеlang
= 'en' иstatus
= '1' порядок поupdated_at
пределу desc 25 смещение 0"источник
Вы можете использовать этот пакет для получения всех запросов, которые выполняются при загрузке вашей страницы
источник
Распечатать последний запрос
источник
Если вы не используете Laravel, а используете пакет Eloquent, тогда:
источник
Вы можете использовать часовой механизм
но работает и в Firefox
источник
Я создал несколько простых функций для получения SQL и привязок из некоторых запросов.
Применение:
источник
Столько, сколько я люблю эту структуру, я ненавижу, когда она действует как дерьмо.
DB::enableQueryLog()
совершенно бесполезно.DB::listen
одинаково бесполезен. Когда я сказал$query->count()
, он показал часть запроса , но если я это сделаю$query->get()
, ему нечего сказать.Единственное решение, которое, по-видимому, работает согласованно, - это преднамеренно поместить некоторый синтаксис или другую ошибку в параметры ORM, например, несуществующее имя столбца / таблицы, запустить код в командной строке в режиме отладки, и он выдаст ошибку SQL. наконец, с полным проклятым запросом. В противном случае, мы надеемся, что ошибка появится в файле журнала при запуске с веб-сервера.
источник
Если вы используете tinker и хотите записать сформированный SQL-запрос, вы можете сделать
источник
Попробуй это:
Примечание: get () был заменен на toSql () для отображения необработанного SQL-запроса.
источник
Мой способ сделать это, основанный на представлении журнала, нужно только изменить файл
app/Providers/AppServiceProvider.php
:app/Providers/AppServiceProvider.php
storage/logs/laravel-2019-10-27.log
:источник