Aşağıdaki kod verildiğinde:
DB::table('users')->get();
Yukarıdaki veritabanı sorgu oluşturucu oluşturacak ham SQL sorgu dizesi almak istiyorum. Bu örnekte olurdu SELECT * FROM users
.
Bunu nasıl yaparım?
Aşağıdaki kod verildiğinde:
DB::table('users')->get();
Yukarıdaki veritabanı sorgu oluşturucu oluşturacak ham SQL sorgu dizesi almak istiyorum. Bu örnekte olurdu SELECT * FROM users
.
Bunu nasıl yaparım?
Yanıtlar:
Ekrana son sorguların çıktısını almak için şunu kullanabilirsiniz:
DB::enableQueryLog(); // Enable query log
// Your Eloquent query executed by using get()
dd(DB::getQueryLog()); // Show results of log
En son sorguların dizinin altında olacağına inanıyorum.
Böyle bir şeye sahip olacaksınız:
array(1) {
[0]=>
array(3) {
["query"]=>
string(21) "select * from "users""
["bindings"]=>
array(0) {
}
["time"]=>
string(4) "0.92"
}
}
( Joshua'nın aşağıdaki yorumuna teşekkürler .)
Log
Sınıfı kullanarak uygulamanızın günlüğüne çıktı almak daha iyi olabilir : Log::debug(DB::getQueryLog())
DB::enableQueryLog();
DB::enableQueryLog(); dd(DB::getQueryLog());
ama sadece döner []
....
DB::connection('database')->getQueryLog()
toSql()
Bir QueryBuilder
örnekte yöntemi kullanın .
DB::table('users')->toSql()
dönecekti:
"kullanıcılar" dan * seçin
Bu, bir olay dinleyicisini bağlamaktan daha kolaydır ve ayrıca sorguyu oluştururken herhangi bir noktada gerçekte nasıl görüneceğini kontrol etmenizi sağlar.
getBindings
yöntemini kullanabilirsiniz . Bu, bağlamaları SQL deyimine bağlı olmaları için döndürür.
$query = \DB::table('users')->where('id', 10); $sql = str_replace_array('?', $query->getBindings(), $query->toSql()); dd($sql);
DB::QueryLog()
yalnızca sorguyu yürüttükten sonra çalışır $builder->get()
. sorguyu yürütmeden önce sorguyu almak istiyorsanız $builder->toSql()
yöntemi kullanabilirsiniz . sql almak ve bağlamak için nasıl bir örnek:
$query = str_replace(array('?'), array('\'%s\''), $builder->toSql());
$query = vsprintf($query, $builder->getBindings());
dump($query);
$result = $builder->get();
VEYA sadece varolan tablo veya sütun çağırmak gibi sorgu hata yapmak, u istisna XD oluşturulan sorgu göreceksiniz
$query = vsprintf(str_replace(array('?'), array('\'%s\''), $builder->toSql()), $builder->getBindings());
LIKE
sorgu için veya tarih biçimlendirilirken yüzde işareti varsa bunun işe yaramayacağını unutmayın . İlk önce onlardan yüzde çift işaretlerle kaçmanız gerekecek.
$builder->getBindings()
mi?
'İlluminate.query' olayını dinleyebilirsiniz. Sorgudan önce aşağıdaki olay dinleyicisini ekleyin:
Event::listen('illuminate.query', function($query, $params, $time, $conn)
{
dd(array($query, $params, $time, $conn));
});
DB::table('users')->get();
Bu şöyle bir şey yazdırır:
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;
size basitçe yapabilirsiniz use Event;
bir beri cephe .
Laravel kullanmadan Illuminate kullanarak Log almaya çalışıyorsanız:
\Illuminate\Database\Capsule\Manager::getQueryLog();
Bunun gibi hızlı bir işlevi de kullanabilirsiniz:
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;
}
DÜZENLE
güncellenmiş sürümlerde varsayılan olarak sorgu günlüğü devre dışı bırakılmış gibi görünür (yukarıdaki boş bir dizi döndürür). Tekrar açmak için, Kapsül Yöneticisi'ni başlatırken, bağlantının bir örneğini alın ve enableQueryLog
yöntemi çağırın
$capsule::connection()->enableQueryLog();
TEKRAR DÜZENLE
Asıl soruyu göz önünde bulundurarak, gerçekte tek bir sorguyu önceki tüm sorgular yerine dönüştürmek için aşağıdakileri yapabilirsiniz:
$sql = $query->toSql();
$bindings = $query->getBindings();
'US/Eastern'
.
quick function
. Temel kodun hazırlamak için ( php.net/manual/en/mysqli.prepare.php ) yöntemleri kullanacağına inanıyorum , bu yüzden sadece ?
gerekli. Sen olabilir php.net/manual/en/function.is-numeric.php tek tırnak içinde giriş saklanması olup olmadığını belirlemek için.
is_numeric
fikrinizi eklemek için yukarıda düzenlediğim ) ve işe yarıyor! Bunu seviyorum. Teşekkür ederim.
Sorgu dizesini almak için anlamlı bir yöntem vardır.
toSql ()
bizim durumumuzda,
DB::table('users')->toSql();
dönüş
select * from users
SQL sorgu dizesini döndüren tam çözümdür ...
->where('foo', '=', 'bar')
bar sql göstermez zaman
$data = User::toSql();
echo $data; //this will retrun select * from users. //here User is model
->toSql()
Modelden sonra daha fazla bağımsız değişken varsa yaptığınız gibi ekleyebilirsiniz . ör.User::where('id', 1)->toSql()
Laravel 5.1 ve MySQL kullanıyorsanız benim tarafımdan yapılan bu fonksiyonu kullanabilirsiniz:
/*
* 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;
}
Bir giriş parametresi olarak aşağıdakilerden birini kullanabilirsiniz:
Aydınlatmak \ Database \ Etkili \ Oluşturucu
Aydınlatmak \ Database \ Etkili \ İlişkiler \ hasMany
Aydınlatmak \ Database \ Sorgu \ Oluşturucu
İlk önce şu sorguları arayarak sorgu günlüğünü etkinleştirmeniz gerekir:
DB::enableQueryLog();
DB cephesini kullanarak yapılan sorgulardan sonra şunları yazabilirsiniz:
dd(DB::getQueryLog());
çıktı aşağıdaki gibi olacak:
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
]
]
Her ne kadar bu da tartışılmış olsa da, bu son sorgu veya son sorgu hata ayıklama için herhangi birine önerebilirim en iyi çözümdür:
// 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);
Sadece toSql()
yöntemi kullanarak aşağıdaki şeyleri yapabilirsiniz ,
$query = DB::table('users')->get();
echo $query->toSql();
Çalışmıyorsa , laravel belgelerinden bir şey ayarlayabilirsiniz .
Bunu yapmanın başka bir yolu da
DB::getQueryLog()
ancak boş bir dizi döndürürse, varsayılan olarak devre dışı bırakılırsa bunu ziyaret edin ,
sadece ile etkinleştirin DB::enableQueryLog()
ve işe yarayacak :)
daha fazla bilgi için Github Sorununu ziyaret edin .
Umarım yardımcı olur :)
Bir 'macroable' yedek bağlamaları ile SQL sorgusu alır.
Yönteme aşağıdaki makro işlevini ekleyin .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());
});
Eloquent Builder için bir takma ad ekleyin. ( Laravel 5.4+ )
\Illuminate\Database\Eloquent\Builder::macro('toRawSql', function(){
return ($this->getQuery()->toRawSql());
});
Sonra her zamanki gibi hata ayıklayın. ( Laravel 5.4+ )
Sorgu Oluşturucu
\Log::debug(\DB::table('users')->limit(1)->toRawSql())
Örnek: Eloquent Builder
\Log::debug(\App\User::limit(1)->toRawSql());
Not: Laravel 5.1'den 5.3'e, Eloquent Builder
Macroable
özelliği kullanmadığındantoRawSql
, Eloquent Builder'a anında bir takma ad ekleyemez . Aynısını elde etmek için aşağıdaki örneği izleyin.
Örneğin Eloquent Builder ( Laravel 5.1 - 5.3 )
\Log::debug(\App\User::limit(1)->getQuery()->toRawSql());
Laravel 5.2
ve sonrası. DB::listen
çalıştırılan sorguları almak için kullanabilirsiniz .
DB::listen(function ($query) {
// $query->sql
// $query->bindings
// $query->time
});
Veya tek bir Builder
örnekte hata ayıklamak istiyorsanız, toSql
yöntemi kullanabilirsiniz .
DB::table('posts')->toSql();
En kolay yol kasıtlı hata yapmaktır . Örneğin, aşağıdaki ilişkinin tam SQL sorgusunu görmek istiyorum:
public function jobs()
{
return $this->belongsToMany(Job::class, 'eqtype_jobs')
->withPivot(['created_at','updated_at','id'])
->orderBy('pivot_created_at','desc');
}
Ben sadece bulunacak bir sütun yapmak için, ben burada seçin created_at
ve ben olmak için son created_ats
ekleyerek bunu değiştirdim s
:
public function jobs()
{
return $this->belongsToMany(Job::class, 'eqtype_jobs')
->withPivot(['created_ats','updated_at','id'])
->orderBy('pivot_created_at','desc');
}
Bu nedenle, hata ayıklayıcı aşağıdaki hatayı döndürür:
(4/4) ErrorException sqlstate [42S22]: bulunamadı Kolon: 'alanına listesi' 1054 Bilinmeyen sütun 'eqtype_jobs.created_ats' (SQL: seçmek
jobs
*,.eqtype_jobs
.set_id
Olarakpivot_set_id
,eqtype_jobs
.job_id
Olarakpivot_job_id
,eqtype_jobs
.created_ats
Olarakpivot_created_ats
,eqtype_jobs
.updated_at
Olarakpivot_updated_at
,eqtype_jobs
.id
Olarakpivot_id
gelenjobs
iç birleştirmeeqtype_jobs
üzerinejobs
.id
=eqtype_jobs
.job_id
buradaeqtype_jobs
.set_id
= 56 ile siparişpivot_created_at
azalan sınırı 20) ofset 0 (Görünüm: /home/said/www/factory/resources/views/set/show.blade.php)
Yukarıdaki hata iletisi, tam SQL sorgusunu hatayla döndürür
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
Şimdi, ekstraları s
yaratılan_at'tan kaldırın ve bu SQL'i phpMyAdmin SQL editörü gibi herhangi bir SQL editöründe istediğiniz gibi test edin!
Farkına varmak:
Çözelti Laravel 5.4 ile test edilmiştir .
:id
DB::enableQueryLog();
$queries = DB::getQueryLog();
Bu, temel model sınıfıma yerleştirdiğim işlev. Sorgu oluşturucu nesnesini içine iletin ve SQL dizesi döndürülecektir.
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;
}
Bence bu yeni başlayanlar için en iyi yaklaşım olacak:
echo "<pre>";
print_r($query->toSql());
print_r($query->getBindings());
Bu da burada tasvir edilmiştir. https://stackoverflow.com/a/59207557/9573341
Laravel 5.5.X için
Uygulamanız tarafından yürütülen her bir SQL sorgusunu almak istiyorsanız listen yöntemini kullanabilirsiniz. Bu yöntem, sorguları günlüğe kaydetmek veya hata ayıklamak için kullanışlıdır. Sorgu dinleyicinizi bir servis sağlayıcısına kaydedebilirsiniz:
<?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()
{
//
}
}
Bu işlevi uygulamanıza ekleyin ve arayın.
function getQuery($sql){
$query = str_replace(array('?'), array('\'%s\''), $sql->toSql());
$query = vsprintf($query, $sql->getBindings());
return $query;
}
Çıktı : "seçin * user
nerede lang
= 'tr' ve status
tarafından = '1' sipariş updated_at
desc sınırı 25 ofset 0"
Bu paketi, sayfanızı yüklediğinizde yürütülen tüm sorguları almak için kullanabilirsiniz
https://github.com/barryvdh/laravel-debugbar
Son sorguyu yazdır
DB::enableQueryLog();
$query = DB::getQueryLog();
$lastQuery = end($query);
print_r($lastQuery);
Laravel kullanmıyorsanız, ancak Eloquent paketini kullanıyorsanız:
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);
saat çalışmasını kullanabilirsiniz
Clockwork, PHP geliştirme için bir Chrome uzantısıdır ve Geliştirici Araçlarını, istek, üstbilgiler, alma ve gönderme verileri, çerezler, oturum verileri, veritabanı sorguları, yollar, uygulama çalışma zamanının görselleştirilmesi ve daha fazlası.
ancak firefox'ta da çalışır
Bazı sorgulardan SQL ve bağlamaları almak için bazı basit fonksiyonlar oluşturdum.
/**
* 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;
}
Kullanımı:
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 ],
// ]
Bu çerçeveyi sevdiğim kadar, bok gibi davrandığında nefret ediyorum.
DB::enableQueryLog()
tamamen işe yaramaz. DB::listen
eşit derecede yararsızdır. Söylediğimde sorgunun bir kısmını gösterdi $query->count()
, ama yaparsam$query->get()
söyleyecek bir şeyi yok.
Tutarlı çalışıyor gibi görünen tek çözüm, kasıtlı olarak olmayan bir sütun / tablo adı gibi ORM parametrelerine sözdizimi veya başka bir hata koymaktır, kodunuzu hata ayıklama modundayken komut satırında çalıştırın ve SQL hatasını tükürecektir. nihayet tam frickin sorgusu ile. Aksi takdirde, web sunucusundan çalıştırıldıysa hata günlük dosyasında görünür.
Tinker kullanıyorsanız ve oluşan SQL sorgusunu günlüğe kaydetmek istiyorsanız
$ 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",
}
>>>
Bunu dene:
$results = DB::table('users')->toSql();
dd($results);
Not: ham SQL sorgusunu görüntülemek için get () yerine toSql () kullanılmıştır.
Günlük görünümüne dayanarak bunu yapma yolumun yalnızca dosyayı değiştirmesi gerekir 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();