निम्नलिखित कोड दिया गया है:
DB::table('users')->get();
मैं कच्चे SQL क्वेरी स्ट्रिंग प्राप्त करना चाहता हूं जो ऊपर डेटाबेस क्वेरी बिल्डर उत्पन्न करेगा। इस उदाहरण में, यह होगा SELECT * FROM users
।
मैं यह कैसे करु?
निम्नलिखित कोड दिया गया है:
DB::table('users')->get();
मैं कच्चे SQL क्वेरी स्ट्रिंग प्राप्त करना चाहता हूं जो ऊपर डेटाबेस क्वेरी बिल्डर उत्पन्न करेगा। इस उदाहरण में, यह होगा SELECT * FROM users
।
मैं यह कैसे करु?
जवाबों:
स्क्रीन पर आउटपुट के लिए अंतिम प्रश्न चले, आप इसका उपयोग कर सकते हैं:
DB::enableQueryLog(); // Enable query log
// Your Eloquent query executed by using get()
dd(DB::getQueryLog()); // Show results of log
मेरा मानना है कि सबसे हाल के प्रश्न सरणी के निचले भाग में होंगे।
आपके पास कुछ ऐसा होगा:
array(1) {
[0]=>
array(3) {
["query"]=>
string(21) "select * from "users""
["bindings"]=>
array(0) {
}
["time"]=>
string(4) "0.92"
}
}
( नीचे जोशुआ की टिप्पणी के लिए धन्यवाद ।)
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()
करने से पहले क्वेरी प्राप्त करना चाहते हैं, तो आप विधि का उपयोग कर सकते हैं । यह उदाहरण है कि एसक्यूएल कैसे प्राप्त करें और इसे कैसे बांधें:
$query = str_replace(array('?'), array('\'%s\''), $builder->toSql());
$query = vsprintf($query, $builder->getBindings());
dump($query);
$result = $builder->get();
या बस अपनी क्वेरी को त्रुटि दें जैसे कि अस्पष्टीकृत तालिका या स्तंभ के लिए कॉल करना, यू अपवाद XD में उत्पन्न क्वेरी को देखेंगे
$query = vsprintf(str_replace(array('?'), array('\'%s\''), $builder->toSql()), $builder->getBindings());
LIKE
क्वेरी के लिए या दिनांक स्वरूपित करते समय। आपको पहले दो प्रतिशत संकेतों के साथ भागने की आवश्यकता होगी।
$builder->getBindings()
?
आप '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"
}
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Event;
आप बस कर सकते हैं use Event;
क्योंकि यह एक मुखौटा है ।
यदि आप लारवेल के उपयोग के बिना इल्यूमिनेट का उपयोग करके लॉग प्राप्त करने की कोशिश कर रहे हैं:
\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 ) :
$prep = preg_replace("#\?#", is_numeric($binding) ? $binding : "'" . $binding . "'", $prep, 1);
endforeach;
$formattedQueries[] = $prep;
endforeach;
return $formattedQueries;
}
संपादित करें
लगता है कि अपडेट किए गए संस्करण डिफ़ॉल्ट रूप से क्वेरी लॉगिंग अक्षम हैं (ऊपर एक खाली सरणी देता है)। कैप्सूल मैनेजर को इनिशियलाइज़ करते समय वापस चालू करने के लिए, कनेक्शन का एक उदाहरण लें और enableQueryLog
विधि को कॉल करें
$capsule::connection()->enableQueryLog();
संपादित करें
वास्तविक प्रश्न को ध्यान में रखते हुए, आप वास्तव में सभी पिछले प्रश्नों के बजाय वर्तमान एकल क्वेरी को परिवर्तित करने के लिए निम्नलिखित कर सकते हैं:
$sql = $query->toSql();
$bindings = $query->getBindings();
'US/Eastern'
।
quick function
। मेरा मानना है कि अंतर्निहित कोड तैयार ( php.net/manual/en/mysqli.prepare.php ) विधियों का उपयोग करेगा , यही कारण है कि बस ?
आवश्यकता है। आप सिंगल कोट्स के भीतर इनपुट को एनकैप्सुलेट कर सकते हैं या नहीं, यह निर्धारित करने के लिए आप php.net/manual/en/function.is-numeric.php कर सकते हैं ।
is_numeric
विचार को शामिल करने के लिए ऊपर संपादित किया है), और यह काम करता है! मुझे यह पसंद है। धन्यवाद।
क्वेरी स्ट्रिंग प्राप्त करने के लिए वाक्पटु में एक विधि है।
toSql ()
हमारे मामले में,
DB::table('users')->toSql();
वापसी
select * from users
एसक्यूएल क्वेरी स्ट्रिंग को वापस लाने का सटीक उपाय है..इस मदद के लिए ...
->where('foo', '=', 'bar')
sql में बार
$data = User::toSql();
echo $data; //this will retrun select * from users. //here User is model
->toSql()
मॉडल के बाद अधिक तर्क हैं, तो आप कर सकते हैं। जैसेUser::where('id', 1)->toSql()
यदि आप लार्वा 5.1 और MySQL का उपयोग करते हैं तो आप मेरे द्वारा किए गए इस फ़ंक्शन का उपयोग कर सकते हैं:
/*
* 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;
}
इनपुट पैरामीटर के रूप में आप इनमें से किसी एक का उपयोग कर सकते हैं
रोशन \ डाटाबेस \ सुवक्ता \ बिल्डर
रोशन \ डाटाबेस \ सुवक्ता \ संबंध \ HasMany
रोशन \ डाटाबेस \ क्वेरी \ बिल्डर
पहले आपको कॉल करके क्वेरी लॉग को सक्षम करना होगा:
DB::enableQueryLog();
DB मुखौटा के उपयोग के बाद आप लिख सकते हैं:
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
]
]
यह सबसे अच्छा समाधान है जिसे मैं डिबग-इंग इलक्वेंट अंतिम प्रश्न या अंतिम प्रश्न के लिए किसी को भी सुझा सकता हूं, हालांकि इस पर भी चर्चा की गई है:
// 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);
बस आप toSql()
विधि का उपयोग कर निम्नलिखित सामान कर सकते हैं ,
$query = DB::table('users')->get();
echo $query->toSql();
यदि यह काम नहीं कर रहा है तो आप लार्वा प्रलेखन से बात सेट कर सकते हैं ।
इसे करने का एक और तरीका है
DB::getQueryLog()
लेकिन अगर यह एक खाली सरणी देता है, तो डिफ़ॉल्ट रूप से यह अक्षम है , इस पर जाएं ,
बस के साथ सक्षम है DB::enableQueryLog()
और यह काम करेगा :)
अधिक जानकारी के लिए Github जारी करें इसके बारे में अधिक जानने के करें।
आशा है ये मदद करेगा :)
ए बाइंडिंग के साथ SQL क्वेरी प्राप्त करने के लिए 'मैक्रोबल' प्रतिस्थापन।
में मैक्रो फ़ंक्शन के नीचे जोड़ें 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());
});
एलोकेन्ट बिल्डर के लिए एक उपनाम जोड़ें। ( लारवेल 5.4+ )
\Illuminate\Database\Eloquent\Builder::macro('toRawSql', function(){
return ($this->getQuery()->toRawSql());
});
फिर हमेशा की तरह डिबग करें। ( लारवेल 5.4+ )
जैसे क्वैरी बिल्डर
\Log::debug(\DB::table('users')->limit(1)->toRawSql())
एग एलोकेंट बिल्डर
\Log::debug(\App\User::limit(1)->toRawSql());
नोट: लारवेल 5.1 से 5.3 के बीच, चूंकि एलोकेंट बिल्डर का उपयोग नहीं होता है
Macroable
ट्रेटtoRawSql
फ्लाई पर एलोकेन्ट बिल्डर में एक उपनाम नहीं जोड़ सकता है । उसी को प्राप्त करने के लिए नीचे दिए गए उदाहरण का अनुसरण करें।
एग एलीकेंट बिल्डर ( लारवेल 5.1 - 5.3 )
\Log::debug(\App\User::limit(1)->getQuery()->toRawSql());
लार्वा 5.2
और आगे से। आप DB::listen
निष्पादित प्रश्नों को प्राप्त करने के लिए उपयोग कर सकते हैं ।
DB::listen(function ($query) {
// $query->sql
// $query->bindings
// $query->time
});
या यदि आप किसी एक Builder
उदाहरण को डीबग करना चाहते हैं तो आप toSql
विधि का उपयोग कर सकते हैं ।
DB::table('posts')->toSql();
सबसे आसान तरीका जानबूझकर गलती करना है । उदाहरण के लिए, मैं निम्नलिखित संबंध की पूर्ण SQL क्वेरी देखना चाहता हूं:
public function jobs()
{
return $this->belongsToMany(Job::class, 'eqtype_jobs')
->withPivot(['created_at','updated_at','id'])
->orderBy('pivot_created_at','desc');
}
मैं बस एक कॉलम बनाने के लिए नहीं पाया जा सकता है, यहाँ मैं चुनता created_at
हूं और मैंने इसे बदलने के लिए इसे created_ats
जोड़कर बदल दिया s
है:
public function jobs()
{
return $this->belongsToMany(Job::class, 'eqtype_jobs')
->withPivot(['created_ats','updated_at','id'])
->orderBy('pivot_created_at','desc');
}
इसलिए, डिबगर निम्न त्रुटि लौटाएगा:
(4/4) ErrorException SQLSTATE [42S22]: नहीं मिला कॉलम: 1054 अज्ञात स्तंभ 'फ़ील्ड सूची' में 'eqtype_jobs.created_ats' (एसक्यूएल: चयन
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
desc सीमा 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
create_at से अतिरिक्त को हटा दें और इस SQL का परीक्षण करें जैसे आप किसी SQL संपादक जैसे phpMyAdmin SQL संपादक में चाहते हैं!
नोटिस:
समाधान का परीक्षण Laravel 5.4 के साथ किया गया है ।
:id
DB::enableQueryLog();
$queries = DB::getQueryLog();
Laravel 5.8.15 के अनुसार क्वेरी बिल्डर के पास अब dd
और dump
विधियाँ हैं, ताकि आप कर सकें
DB::table('data')->where('a', 1)->dump();
यह फ़ंक्शन है, मैंने अपने बेस मॉडल वर्ग में रखा है। बस इसमें क्वेरी बिल्डर ऑब्जेक्ट को पास करें और SQL स्ट्रिंग वापस आ जाएगी।
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;
}
मेरी राय में, यह एक शुरुआत के रूप में सबसे अच्छा तरीका होगा:
echo "<pre>";
print_r($query->toSql());
print_r($query->getBindings());
यह भी यहाँ दर्शाया गया है। https://stackoverflow.com/a/59207557/9573341
लार्वा 5.5.X के लिए
यदि आप अपने आवेदन द्वारा निष्पादित प्रत्येक SQL क्वेरी प्राप्त करना चाहते हैं, तो आप सुनने की विधि का उपयोग कर सकते हैं। यह विधि लॉगिंग क्वेरी या डीबगिंग के लिए उपयोगी है। आप अपने क्वेरी श्रोता को एक सेवा प्रदाता में पंजीकृत कर सकते हैं:
<?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()
{
//
}
}
इस फ़ंक्शन को अपने एप्लिकेशन में जोड़ें और बस कॉल करें।
function getQuery($sql){
$query = str_replace(array('?'), array('\'%s\''), $sql->toSql());
$query = vsprintf($query, $sql->getBindings());
return $query;
}
आउटपुट : "से * का चयन करें, user
जहां से lang
= 'एन' और status
= order 1 'क्रम से updated_at
desc सीमा २५ ऑफसेट ०"
आप इस पैकेज का उपयोग उन सभी प्रश्नों को प्राप्त करने के लिए कर सकते हैं जो आपके पेज को लोड करते समय निष्पादित कर रहे हैं
https://github.com/barryvdh/laravel-debugbar
अंतिम क्वेरी प्रिंट करें
DB::enableQueryLog();
$query = DB::getQueryLog();
$lastQuery = end($query);
print_r($lastQuery);
यदि आप लारवेल का उपयोग नहीं कर रहे हैं लेकिन एलोकेंट पैकेज का उपयोग कर रहे हैं तो:
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);
आप घड़ी की कल का उपयोग कर सकते हैं
घड़ी की कल PHP के विकास के लिए एक क्रोम एक्सटेंशन है, डेवलपर टूल को एक नए पैनल के साथ बढ़ाता है जो आपके PHP अनुप्रयोगों को डिबगिंग और प्रोफाइलिंग के लिए उपयोगी सभी प्रकार की जानकारी प्रदान करता है, जिसमें अनुरोध, हेडर, डेटा और कुकीज़, सत्र डेटा, डेटाबेस प्रश्नों के बारे में जानकारी शामिल है, मार्गों, आवेदन क्रम और अधिक के दृश्य।
लेकिन फ़ायरफ़ॉक्स में भी काम करता है
मैं कुछ सरल कार्यों बना लिया है कुछ प्रश्नों से एसक्यूएल और बाइंडिंग मिलता है।
/**
* 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;
}
उपयोग:
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 त्रुटि को थूक देगा अंत में पूर्ण 'frickin क्वेरी के साथ। अन्यथा, उम्मीद है कि वेब सर्वर से चलने पर लॉग फ़ाइल में त्रुटि दिखाई देती है।
यदि आप टिंकर का उपयोग कर रहे हैं और SQL क्वेरी को लॉग करना चाहते हैं, तो आप कर सकते हैं
$ 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",
}
>>>
इसे इस्तेमाल करे:
$results = DB::table('users')->toSql();
dd($results);
नोट: कच्चे SQL क्वेरी को प्रदर्शित करने के लिए get () को toSql () से बदल दिया गया है।
यह करने का मेरा तरीका, लॉग दृश्य के आधार पर, केवल फ़ाइल को संशोधित करने की आवश्यकता है 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();