Diberikan kode berikut:
DB::table('users')->get();
Saya ingin mendapatkan string kueri SQL mentah yang akan dihasilkan oleh pembuat kueri basis data di atas. Dalam contoh ini, itu akan menjadiSELECT * FROM users
.
Bagaimana saya melakukan ini?
Diberikan kode berikut:
DB::table('users')->get();
Saya ingin mendapatkan string kueri SQL mentah yang akan dihasilkan oleh pembuat kueri basis data di atas. Dalam contoh ini, itu akan menjadiSELECT * FROM users
.
Bagaimana saya melakukan ini?
Jawaban:
Untuk menampilkan ke layar pertanyaan terakhir dijalankan, Anda dapat menggunakan ini:
DB::enableQueryLog(); // Enable query log
// Your Eloquent query executed by using get()
dd(DB::getQueryLog()); // Show results of log
Saya percaya pertanyaan terbaru akan berada di bagian bawah array.
Anda akan memiliki sesuatu seperti itu:
array(1) {
[0]=>
array(3) {
["query"]=>
string(21) "select * from "users""
["bindings"]=>
array(0) {
}
["time"]=>
string(4) "0.92"
}
}
Log
kelas: Log::debug(DB::getQueryLog())
DB::enableQueryLog();
DB::enableQueryLog(); dd(DB::getQueryLog());
Tapi itu mengembalikan hanya []
....
DB::connection('database')->getQueryLog()
Gunakan toSql()
metode ini pada QueryBuilder
contoh.
DB::table('users')->toSql()
akan kembali:
pilih * dari `pengguna`
Ini lebih mudah daripada membuat daftar pendengar acara, dan juga memungkinkan Anda memeriksa seperti apa bentuk kueri pada saat Anda membangunnya.
getBindings
metode. Ini akan mengembalikan binding agar mereka terikat pada pernyataan SQL.
$query = \DB::table('users')->where('id', 10); $sql = str_replace_array('?', $query->getBindings(), $query->toSql()); dd($sql);
DB::QueryLog()
hanya berfungsi setelah Anda menjalankan kueri $builder->get()
. jika Anda ingin mendapatkan kueri sebelum mengeksekusi kueri Anda dapat menggunakan $builder->toSql()
metode. ini adalah contoh cara mendapatkan sql dan mengikatnya:
$query = str_replace(array('?'), array('\'%s\''), $builder->toSql());
$query = vsprintf($query, $builder->getBindings());
dump($query);
$result = $builder->get();
ATAU cukup buat kesalahan kueri Anda seperti memanggil tabel atau kolom yang tidak ada, Anda akan melihat kueri yang dihasilkan dalam pengecualian XD
$query = vsprintf(str_replace(array('?'), array('\'%s\''), $builder->toSql()), $builder->getBindings());
LIKE
kueri atau saat memformat tanggal. Anda harus melarikan diri dari yang pertama dengan tanda dua persen.
$builder->getBindings()
?
Anda dapat mendengarkan acara 'illuminate.query'. Sebelum kueri tambahkan pendengar acara berikut:
Event::listen('illuminate.query', function($query, $params, $time, $conn)
{
dd(array($query, $params, $time, $conn));
});
DB::table('users')->get();
Ini akan mencetak sesuatu seperti:
array(4) {
[0]=>
string(21) "select * from "users""
[1]=>
array(0) {
}
[2]=>
string(4) "0.94"
[3]=>
string(6) "sqlite"
}
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Event;
Anda hanya dapat melakukan use Event;
karena itu adalah fasad .
Jika Anda mencoba untuk mendapatkan Log menggunakan Illuminate tanpa Laravel use:
\Illuminate\Database\Capsule\Manager::getQueryLog();
Anda juga dapat mengaktifkan fungsi cepat seperti:
function logger() {
$queries = \Illuminate\Database\Capsule\Manager::getQueryLog();
$formattedQueries = [];
foreach( $queries as $query ) :
$prep = $query['query'];
foreach( $query['bindings'] as $binding ) :
$prep = preg_replace("#\?#", is_numeric($binding) ? $binding : "'" . $binding . "'", $prep, 1);
endforeach;
$formattedQueries[] = $prep;
endforeach;
return $formattedQueries;
}
EDIT
versi yang diperbarui tampaknya memiliki penebangan kueri dinonaktifkan secara default (di atas mengembalikan array kosong). Untuk menghidupkan kembali, saat menginisialisasi Manajer Kapsul, ambil contoh koneksi dan panggil enableQueryLog
metode
$capsule::connection()->enableQueryLog();
Sunting LAGI
Dengan mempertimbangkan pertanyaan aktual, Anda sebenarnya dapat melakukan hal berikut untuk mengonversi kueri tunggal saat ini alih-alih semua kueri sebelumnya:
$sql = $query->toSql();
$bindings = $query->getBindings();
'US/Eastern'
.
quick function
. Saya percaya kode yang mendasarinya akan menggunakan metode prep ( php.net/manual/en/mysqli.prepare.php ), itulah sebabnya hanya ?
diperlukan. Anda dapat php.net/manual/en/function.is-numeric.php untuk menentukan apakah akan merangkum input dalam tanda kutip tunggal.
is_numeric
ide Anda ), dan berhasil! Aku suka ini. Terima kasih.
Ada metode dalam fasih untuk mendapatkan string kueri.
toSql ()
dalam kasus kami,
DB::table('users')->toSql();
kembali
select * from users
adalah solusi tepat yang mengembalikan string kueri SQL .. Semoga ini bermanfaat ...
->where('foo', '=', 'bar')
bar tidak akan ditampilkan di sql
$data = User::toSql();
echo $data; //this will retrun select * from users. //here User is model
->toSql()
seperti yang akan Anda lakukan jika ada lebih banyak argumen setelah model. misalnyaUser::where('id', 1)->toSql()
Jika Anda menggunakan laravel 5.1 dan MySQL Anda dapat menggunakan fungsi ini yang dibuat oleh saya:
/*
* returns SQL with values in it
*/
function getSql($model)
{
$replace = function ($sql, $bindings)
{
$needle = '?';
foreach ($bindings as $replace){
$pos = strpos($sql, $needle);
if ($pos !== false) {
if (gettype($replace) === "string") {
$replace = ' "'.addslashes($replace).'" ';
}
$sql = substr_replace($sql, $replace, $pos, strlen($needle));
}
}
return $sql;
};
$sql = $replace($model->toSql(), $model->getBindings());
return $sql;
}
Sebagai parameter input, Anda dapat menggunakan salah satu dari ini
Menerangi \ Basis Data \ Eloquent \ Builder
Menerangi \ Database \ Eloquent \ Relations \ HasMany
Menerangi \ Database \ Query \ Builder
Pertama, Anda harus mengaktifkan log kueri dengan menelepon:
DB::enableQueryLog();
setelah permintaan menggunakan fasad DB Anda dapat menulis:
dd(DB::getQueryLog());
output akan seperti di bawah ini:
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
]
]
Ini adalah solusi terbaik yang bisa saya sarankan kepada siapa pun untuk men-debug permintaan terakhir atau permintaan terakhir yang fasih meskipun ini juga telah dibahas:
// query builder
$query = DB::table('table_name')->where('id', 1);
// binding replaced
$sql = str_replace_array('?', $query->getBindings(), $query->toSql());
// for laravel 5.8^
$sql = Str::replaceArray('?', $query->getBindings(), $query->toSql());
// print
dd($sql);
Cukup Anda dapat melakukan hal-hal berikut menggunakan toSql()
metode,
$query = DB::table('users')->get();
echo $query->toSql();
Jika tidak berfungsi, Anda dapat mengaturnya dari dokumentasi laravel .
Cara lain untuk melakukannya adalah
DB::getQueryLog()
tetapi jika itu mengembalikan array kosong maka secara default itu dinonaktifkan kunjungi ini ,
cukup aktifkan dengan DB::enableQueryLog()
dan itu akan bekerja :)
untuk info lebih lanjut kunjungi Masalah Github untuk mengetahui lebih banyak tentangnya.
Semoga bermanfaat :)
Sebuah 'macroable' pengganti untuk mendapatkan query SQL dengan binding.
Tambahkan fungsi makro di bawah ini dalam metode.AppServiceProvider
boot()
\Illuminate\Database\Query\Builder::macro('toRawSql', function(){
return array_reduce($this->getBindings(), function($sql, $binding){
return preg_replace('/\?/', is_numeric($binding) ? $binding : "'".$binding."'" , $sql, 1);
}, $this->toSql());
});
Tambahkan alias untuk Eloquent Builder. ( Laravel 5.4+ )
\Illuminate\Database\Eloquent\Builder::macro('toRawSql', function(){
return ($this->getQuery()->toRawSql());
});
Kemudian debug seperti biasa. ( Laravel 5.4+ )
Misalnya Pembuat Kueri
\Log::debug(\DB::table('users')->limit(1)->toRawSql())
Misalnya Eloquent Builder
\Log::debug(\App\User::limit(1)->toRawSql());
Catatan: dari Laravel 5.1 hingga 5.3, Karena Eloquent Builder tidak menggunakan
Macroable
ciri tersebut, tidak dapat menambahkantoRawSql
alias ke Eloquent Builder dengan cepat. Ikuti contoh di bawah ini untuk mencapai hal yang sama.
Misalnya Eloquent Builder ( Laravel 5.1 - 5.3 )
\Log::debug(\App\User::limit(1)->getQuery()->toRawSql());
Dari laravel 5.2
dan seterusnya. Anda dapat menggunakan DB::listen
untuk mendapatkan kueri yang dieksekusi.
DB::listen(function ($query) {
// $query->sql
// $query->bindings
// $query->time
});
Atau jika Anda ingin men-debug Builder
instance tunggal maka Anda dapat menggunakan toSql
metode.
DB::table('posts')->toSql();
Cara paling mudah adalah dengan membuat kesalahan yang disengaja . Misalnya, saya ingin melihat kueri SQL lengkap dari relasi berikut:
public function jobs()
{
return $this->belongsToMany(Job::class, 'eqtype_jobs')
->withPivot(['created_at','updated_at','id'])
->orderBy('pivot_created_at','desc');
}
Saya hanya membuat kolom agar tidak ditemukan, di sini saya pilih created_at
dan saya mengubahnya created_ats
dengan menambahkan trailing s
menjadi:
public function jobs()
{
return $this->belongsToMany(Job::class, 'eqtype_jobs')
->withPivot(['created_ats','updated_at','id'])
->orderBy('pivot_created_at','desc');
}
Jadi, debuger akan mengembalikan kesalahan berikut:
(4/4) ErrorException SQLSTATE [42S22]: Kolom tidak ditemukan: 1054 diketahui kolom 'eqtype_jobs.created_ats' di 'daftar bidang' (SQL: pilih
jobs
*,.eqtype_jobs
.set_id
Sebagaipivot_set_id
,eqtype_jobs
.job_id
Sepertipivot_job_id
,eqtype_jobs
.created_ats
Sepertipivot_created_ats
,eqtype_jobs
.updated_at
Sepertipivot_updated_at
,eqtype_jobs
.id
Sepertipivot_id
darijobs
inner joineqtype_jobs
onjobs
.id
=eqtype_jobs
.job_id
whereeqtype_jobs
.set_id
= 56 order denganpivot_created_at
desc limit 20 offset 0) (Lihat: /home/said/www/factory/resources/views/set/show.blade.php)
Pesan kesalahan di atas mengembalikan permintaan SQL lengkap dengan kesalahan
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
Sekarang, hapus saja ekstra s
dari Created_at dan uji SQL ini sesuka Anda dalam editor SQL apa pun seperti editor SQL phpMyAdmin!
Memperhatikan:
Solusinya telah diuji dengan Laravel 5.4 .
:id
DB::enableQueryLog();
$queries = DB::getQueryLog();
Pada Laravel 5.8.15 pembuat kueri sekarang memiliki dd
dan dump
metode sehingga Anda dapat melakukannya
DB::table('data')->where('a', 1)->dump();
Inilah fungsinya, saya ditempatkan di kelas model dasar saya. Cukup masukkan objek pembuat kueri ke dalamnya dan string SQL akan dikembalikan.
function getSQL($builder) {
$sql = $builder->toSql();
foreach ( $builder->getBindings() as $binding ) {
$value = is_numeric($binding) ? $binding : "'".$binding."'";
$sql = preg_replace('/\?/', $value, $sql, 1);
}
return $sql;
}
Menurut pendapat saya, ini akan menjadi pendekatan terbaik sebagai pemula:
echo "<pre>";
print_r($query->toSql());
print_r($query->getBindings());
Ini juga digambarkan di sini. https://stackoverflow.com/a/59207557/9573341
Untuk laravel 5.5.X
Jika Anda ingin menerima setiap permintaan SQL yang dijalankan oleh aplikasi Anda, Anda dapat menggunakan metode mendengarkan. Metode ini berguna untuk mencatat kueri atau debugging. Anda dapat mendaftarkan pendengar kueri Anda di penyedia layanan:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
DB::listen(function ($query) {
// $query->sql
// $query->bindings
// $query->time
});
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
//
}
}
Tambahkan fungsi ini ke aplikasi Anda dan cukup panggil.
function getQuery($sql){
$query = str_replace(array('?'), array('\'%s\''), $sql->toSql());
$query = vsprintf($query, $sql->getBindings());
return $query;
}
Output : "pilih * dari user
mana lang
= 'en' dan status
= '1' pesan dengan updated_at
batas desc 25 offset 0"
Anda dapat menggunakan paket ini untuk mendapatkan semua pertanyaan yang dieksekusi saat Anda memuat halaman Anda
https://github.com/barryvdh/laravel-debugbar
Cetak kueri terakhir
DB::enableQueryLog();
$query = DB::getQueryLog();
$lastQuery = end($query);
print_r($lastQuery);
Jika Anda tidak menggunakan Laravel tetapi menggunakan paket Eloquent maka:
use \Illuminate\Database\Capsule\Manager as Capsule;
use \Illuminate\Events\Dispatcher;
use \Illuminate\Container\Container;
$capsule = new Capsule;
$capsule->addConnection([
// connection details
]);
// Set the event dispatcher used by Eloquent models... (optional)
$capsule->setEventDispatcher(new Dispatcher(new Container));
// Make this Capsule instance available globally via static methods... (optional)
$capsule->setAsGlobal();
// Setup the Eloquent ORM...(optional unless you've used setEventDispatcher())
$capsule->bootEloquent();
// Listen for Query Events for Debug
$events = new Dispatcher;
$events->listen('illuminate.query', function($query, $bindings, $time, $name)
{
// Format binding data for sql insertion
foreach ($bindings as $i => $binding) {
if ($binding instanceof \DateTime) {
$bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
} else if (is_string($binding)) {
$bindings[$i] = "'$binding'";`enter code here`
}
}
// Insert bindings into query
$query = str_replace(array('%', '?'), array('%%', '%s'), $query);
$query = vsprintf($query, $bindings);
// Debug SQL queries
echo 'SQL: [' . $query . ']';
});
$capsule->setEventDispatcher($events);
Anda bisa menggunakan jarum jam
Clockwork adalah ekstensi Chrome untuk pengembangan PHP, memperluas Alat Pengembang dengan panel baru yang menyediakan semua jenis informasi yang berguna untuk debugging dan profil aplikasi PHP Anda, termasuk informasi tentang permintaan, header, dapatkan dan kirim data, cookie, data sesi, kueri basis data, rute, visualisasi runtime aplikasi dan banyak lagi.
tetapi berfungsi juga di firefox
Saya telah membuat beberapa fungsi sederhana untuk mendapatkan SQL dan binding dari beberapa query.
/**
* 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 instanceof Illuminate\Database\Eloquent\Relations\Relation )
{
$query = $query->getBaseQuery();
}
if( $query instanceof Illuminate\Database\Eloquent\Builder )
{
$query = $query->getQuery();
}
if( $query instanceof Illuminate\Database\Query\Builder )
{
return [ 'query' => $query->toSql(), 'bindings' => $query->getBindings() ];
}
return false;
}
/**
* 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 it
if( !$logging ) DB::enableQueryLog();
$query = $callback();
$lastQuery = getSql($query);
// Get querylog
$queries = new Illuminate\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 logging
if( !$logging ) DB::disableQueryLog();
// if callback returns a builder object, return the sql and bindings of it
if( $lastQuery )
{
$lastQueries->push($lastQuery);
}
return $lastQueries;
}
Pemakaian:
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 ],
// ]
Seperti halnya saya menyukai kerangka ini, saya benci kalau itu bertindak seperti omong kosong.
DB::enableQueryLog()
sama sekali tidak berguna. DB::listen
sama-sama tidak berguna. Itu menunjukkan bagian dari permintaan ketika saya berkata $query->count()
, tetapi jika saya lakukan$query->get()
, tidak ada yang bisa dikatakan.
Satu-satunya solusi yang tampaknya bekerja secara konsisten adalah dengan sengaja menempatkan beberapa sintaks atau kesalahan lain dalam parameter ORM, seperti nama kolom / tabel yang tidak ada, jalankan kode Anda pada baris perintah saat dalam mode debug, dan itu akan memuntahkan kesalahan SQL dengan permintaan penuh akhirnya. Kalau tidak, mudah-mudahan kesalahan muncul di file log jika dijalankan dari server web.
Jika Anda menggunakan tinker dan ingin mencatat permintaan SQL yang terbentuk, Anda bisa melakukannya
$ php artisan tinker
Psy Shell v0.9.9 (PHP 7.3.5 — cli) by Justin Hileman
>>> DB::listen(function ($query) { dump($query->sql); dump($query->bindings); dump($query->time); });
=> null
>>> App\User::find(1)
"select * from `users` where `users`.`id` = ? limit 1"
array:1 [
0 => 1
]
6.99
=> App\User {#3131
id: 1,
name: "admin",
email: "admin@example.com",
created_at: "2019-01-11 19:06:23",
updated_at: "2019-01-11 19:06:23",
}
>>>
Coba ini:
$results = DB::table('users')->toSql();
dd($results);
Catatan: get () telah diganti dengan toSql () untuk menampilkan kueri SQL mentah.
Cara saya melakukan ini, berdasarkan tampilan log, hanya perlu memodifikasi file app/Providers/AppServiceProvider.php
:
app/Providers/AppServiceProvider.php
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
DB::listen(function ($query) {
$querySql = str_replace(['?'], ['\'%s\''], $query->sql);
$queryRawSql = vsprintf($querySql, $query->bindings);
Log::debug('[SQL EXEC]', [
"raw sql" => $queryRawSql,
"time" => $query->time,
]
);
});
}
$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-27 17: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();