ฉันจะรับตัวสร้างแบบสอบถามเพื่อแสดงผลแบบสอบถาม SQL ดิบเป็นสตริงได้อย่างไร


544

รับรหัสต่อไปนี้:

DB::table('users')->get();

ฉันต้องการรับสตริงแบบสอบถาม SQL ดิบที่ตัวสร้างแบบสอบถามฐานข้อมูลจะสร้างขึ้น SELECT * FROM usersในตัวอย่างนี้ก็จะเป็น

ฉันจะทำสิ่งนี้ได้อย่างไร


14
Laravel Eloquent ORM ได้รับข้อความค้นหาดิบ:echo User::where('status', 1)->toSql();
Muhammad Shahzad

ฉันกำลังใช้แพ็คเก็ตสำหรับ Laravel - Telescope มันบันทึกการสืบค้นทั้งหมดและทำสิ่งอื่น ๆ อีกมากมาย
vinsa

คำตอบ:


658

หากต้องการส่งออกไปยังหน้าจอการสืบค้นล่าสุดที่คุณสามารถทำได้:

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"
  }
}

(ขอบคุณความคิดเห็นของโจชัวด้านล่าง)


2
hmm im ไม่แน่ใจ แต่คุณอาจจะมาพร้อมกับสิ่งที่คุณต้องการด้วยแพ็คเกจนักแต่งเพลงstackoverflow.com/a/17339752/813181
juckyato

9
อาจดีกว่าที่จะส่งออกไปยังบันทึกของแอปพลิเคชันของคุณโดยใช้Logคลาส: Log::debug(DB::getQueryLog())
msturdy

35
คุณอาจต้องเปิดใช้งานสิ่งนี้เมื่อปิดใช้งานโดยค่าเริ่มต้นแล้ว คุณสามารถใช้คำสั่งนี้เพื่อเปิดใช้ชั่วคราว:DB::enableQueryLog();
Joshua Fricke

5
ฉันลองคำตอบของคุณ สิ่งที่ฉันพยายามคือDB::enableQueryLog(); dd(DB::getQueryLog());แต่มันกลับมาเพียงแค่[]....
ฉันเป็นคนที่โง่ที่สุดใน

6
หากคุณมีฐานข้อมูลหลายตัวคุณอาจต้องทำDB::connection('database')->getQueryLog()
Damien Ó Ceallaigh

745

ใช้toSql()วิธีการในQueryBuilderอินสแตนซ์

DB::table('users')->toSql() จะกลับมา:

เลือก * จาก `ผู้ใช้ '

นี่ง่ายกว่าการต่อสายผู้ฟังเหตุการณ์และให้คุณตรวจสอบว่าคิวรีใดจะมีลักษณะเหมือนจริง ณ จุดใด ๆ ในขณะที่คุณกำลังสร้าง


6
ฉันคิดว่านี่เป็นวิธีที่ง่ายที่สุดเมื่อใช้ Eloquent นอก Laravel
Gab

8
@Stormsson นั้นเป็นไปไม่ได้เพราะ PHP ไม่เคยมีการสืบค้นด้วยการเชื่อมโยงที่ถูกแทนที่ด้วยค่าของมัน เพื่อให้ได้แบบสอบถามอย่างครบถ้วนคุณต้องเข้าสู่ระบบจาก MySQL มีข้อมูลเพิ่มเติมที่นี่: stackoverflow.com/questions/1786322/…
แมทธิว

40
@Stormsson คุณสามารถใช้getBindingsวิธีการ สิ่งนี้จะคืนค่าการเชื่อมโยงเพื่อให้ผูกพันกับคำสั่ง SQL
Danronmoon

2
มีประโยชน์มากสำหรับการดีบักข้อความค้นหาที่ซับซ้อนซึ่ง Eloquent ปฏิเสธที่จะทำงานเนื่องจากข้อความเหล่านั้นไม่แสดงในบันทึกการสืบค้น
BobChao87

34
เพื่อรับการสืบค้นด้วย bindinds$query = \DB::table('users')->where('id', 10); $sql = str_replace_array('?', $query->getBindings(), $query->toSql()); dd($sql);
Ennio Sousa

88

DB::QueryLog()$builder->get()ทำงานเฉพาะหลังจากที่คุณดำเนินการแบบสอบถาม ถ้าคุณต้องการได้รับแบบสอบถามก่อนดำเนินการแบบสอบถามคุณสามารถใช้$builder->toSql()วิธีการ นี่คือตัวอย่างวิธีการรับ sql และผูกมัน:

    $query = str_replace(array('?'), array('\'%s\''), $builder->toSql());
    $query = vsprintf($query, $builder->getBindings());
    dump($query);

    $result = $builder->get();

หรือเพียงแค่ทำให้ข้อผิดพลาดการค้นหาของคุณเช่นการเรียกใช้ตารางหรือคอลัมน์ที่ไม่มีอยู่คุณจะเห็นข้อความค้นหาที่สร้างขึ้นยกเว้น XD


3
นี่คือคำตอบที่ดีที่สุดเรียบง่ายและตรงประเด็น ขอบคุณ :)
Sobakus

18
ในฐานะสายการบินหนึ่ง:$query = vsprintf(str_replace(array('?'), array('\'%s\''), $builder->toSql()), $builder->getBindings());
kramer65

สิ่งนี้ควรรวมอยู่ในกรอบการทำงานเป็นฟังก์ชันดั้งเดิม .. ขอบคุณ
Tomáš Mleziva

โปรดทราบว่าสิ่งนี้จะใช้ไม่ได้หากคำค้นหาของคุณมีเครื่องหมายเปอร์เซ็นต์เช่นLIKEแบบสอบถามหรือเมื่อจัดรูปแบบวันที่ คุณจะต้องหลบหนีสิ่งเหล่านี้ก่อนด้วยเครื่องหมายสองเปอร์เซ็นต์
Dev ที่ไม่รู้จัก

มีความกังวลด้านความปลอดภัยเมื่อทำเช่นนี้? การผูกมัดมาจากการทำให้บริสุทธิ์$builder->getBindings()หรือไม่?
solidau

56

คุณสามารถฟังเหตุการณ์ '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"
}

1
ฉันได้รับการโทรหาวิธีที่ไม่ได้กำหนด Illuminate \ Database \ Query \ Builder :: Listen () ใน Laravel 4
Miguel Stevens

2
ขอบคุณมาก ที่ดีที่จะทราบววที่มีฟังก์ชั่นที่ผลิตการถ่ายโอนข้อมูลตัวแปรที่กำหนดและการดำเนินการในตอนท้ายของสคริปต์และยังที่จะจัดกิจกรรมนำเข้า ได้แก่use Illuminate\Support\Facades\Event;
radtek

1
@radtek: แทนที่จะuse Illuminate\Support\Facades\Event;คุณก็สามารถทำได้use Event;เนื่องจากเป็นซุ้ม
TachyonVortex

50

หากคุณพยายามรับ Log โดยใช้ Illuminate โดยไม่ใช้ Laravel ให้ทำดังนี้

\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;
}

แก้ไข

ดูเหมือนว่ารุ่นที่ปรับปรุงแล้วจะมีการปิดใช้งานการบันทึกแบบสอบถามโดยค่าเริ่มต้น (ข้างต้นจะส่งคืนอาร์เรย์ว่าง) หากต้องการเปิดใช้งานเมื่อเริ่มต้น Capsule Manager ให้คว้าอินสแตนซ์ของการเชื่อมต่อและเรียกใช้enableQueryLogเมธอด

$capsule::connection()->enableQueryLog();

แก้ไขอีกครั้ง

เมื่อพิจารณาคำถามจริงแล้วคุณสามารถทำสิ่งต่อไปนี้เพื่อแปลงแบบสอบถามเดี่ยวปัจจุบันแทนแบบสอบถามก่อนหน้าทั้งหมด:

$sql = $query->toSql();
$bindings = $query->getBindings();

ฉันได้รับผลตอบแทนประเภทนี้จากการสืบค้น "name = [{" name ":" rifat "}]" ฉันต้องทำอย่างไรจึงจะได้รับ "name = rifat" เท่านั้น?
ตัวตน

ฉันจะพิมพ์การผูกของคุณดูเหมือนว่าคุณจะผ่านอาร์เรย์แทนสตริง
ลุค Snowden

นี่คือจุดเริ่มต้นที่เป็นประโยชน์ 'US/Eastern'แต่ก็ดูเหมือนว่าจะละเลยที่จะเพิ่มราคาเดียวทั่วค่าพารามิเตอร์เช่นเมื่อผมผ่านสายเช่น
Ryan

1
@Ryan quick functionนี้เป็นจริงด้วยเหตุว่าทำไมผมกล่าว ฉันเชื่อว่ารหัสพื้นฐานจะใช้วิธีการเตรียมตัว ( php.net/manual/en/mysqli.prepare.php ) ซึ่งเป็นเหตุผลว่าทำไมจึง?จำเป็นต้องมี คุณสามารถphp.net/manual/en/function.is-numeric.phpเพื่อกำหนดว่าจะใส่แค็ปซูลอินพุตภายในเครื่องหมายคำพูดเดี่ยวหรือไม่
ลุคสโนว์เดน

1
@LukeSnowden คำตอบของคุณคืออัจฉริยะ! ในที่สุดฉันก็ใช้เวลาลองเวอร์ชันใหม่ของคุณ (ซึ่งฉันแก้ไขข้างต้นเพื่อรวมis_numericความคิดของคุณ) และใช้งานได้! ฉันรักสิ่งนี้. ขอบคุณ.
Ryan

36

มีวิธีการฝีปากในการรับสตริงแบบสอบถาม

toSql ()

ในกรณีของเรา

 DB::table('users')->toSql(); 

กลับ

select * from users

เป็นวิธีการแก้ปัญหาที่แน่นอนที่ส่งกลับสตริงแบบสอบถาม SQL .. หวังว่าจะเป็นประโยชน์ ...


11
สิ่งที่เกี่ยวกับการผูกแบบสอบถาม? เช่นเมื่อคุณ->where('foo', '=', 'bar')แสดงบาร์จะไม่แสดงใน sql
Toskan

28
$data = User::toSql();
echo $data; //this will retrun select * from users. //here User is model

นี่คือแม่นยำควบคุมและตรงกับความต้องการของคำถาม
benjaminhull

ขอบคุณสำหรับความคิดเห็นของคุณ.
Kuldeep Mishra

2
คุณสามารถผนวก->toSql()เช่นเดียวกับที่คุณทำถ้ามีข้อโต้แย้งเพิ่มเติมหลังจากแบบจำลอง เช่นUser::where('id', 1)->toSql()
Toby Mellor

24

หากคุณใช้ laravel 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;
}

ในฐานะที่เป็นพารามิเตอร์การป้อนข้อมูลคุณสามารถใช้อย่างใดอย่างหนึ่งเหล่านี้

Illuminate \ ฐานข้อมูล \ ฝีปาก \ Builder

Illuminate \ ฐานข้อมูล \ ฝีปาก \ สัมพันธ์ \ hasMany

Illuminate \ ฐานข้อมูล \ แบบสอบถาม \ Builder


คำตอบได้รับการปรับปรุงเพื่อรวมคำพูดทั้งหมดที่แสดงความคิดเห็นไว้ ขอบคุณมาก.
Yevgeniy Afanasyev

13

ก่อนอื่นคุณจะต้องเปิดใช้งานบันทึกแบบสอบถามโดยโทร:

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
  ]
]

คำตอบที่เป็นประโยชน์มาก
Anoop PS

สวัสดีฉันใช้ $ result = DB :: select ('select * จาก 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: dd (DB :: getQueryLog ());
Ravi Mane

12

นี่เป็นทางออกที่ดีที่สุดที่ฉันสามารถแนะนำให้กับผู้ใช้คนใดคนหนึ่งสำหรับการสืบค้นครั้งล่าสุดหรือคำถามสุดท้ายแม้จะมีการพูดถึงเช่นนี้:

// 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);

10

วิธีแรก:

เพียงคุณสามารถทำสิ่งต่าง ๆ โดยใช้toSql()วิธีการ

$query = DB::table('users')->get();

echo $query->toSql();

ถ้ามันไม่ทำงานคุณสามารถตั้งค่าสิ่งนี้ได้จากเอกสาร laravelเอกสาร

วิธีที่สอง:

อีกวิธีในการทำก็คือ

DB::getQueryLog()

แต่ถ้ามันส่งคืนอาร์เรย์ว่างเปล่าโดยค่าเริ่มต้นมันถูกปิดใช้งานไปที่นี้ ,

เพียงแค่เปิดใช้งานด้วย DB::enableQueryLog()และมันจะทำงาน :)

สำหรับข้อมูลเพิ่มเติมโปรดเยี่ยมชม Github Issueเพื่อเรียนรู้เพิ่มเติมเกี่ยวกับมัน

หวังว่าจะช่วย :)


10

การแทนที่'แมโครable'เพื่อรับเคียวรี SQL ด้วยการโยง

  1. เพิ่มฟังก์ชันมาโครด้านล่างในวิธีการ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());
    });
  2. เพิ่มนามแฝงสำหรับ Eloquent Builder ( Laravel 5.4+ )

    \Illuminate\Database\Eloquent\Builder::macro('toRawSql', function(){
        return ($this->getQuery()->toRawSql());
    });
  3. จากนั้นทำการดีบักตามปกติ ( Laravel 5.4+) )

    ตัวสร้างแบบสอบถาม

    \Log::debug(\DB::table('users')->limit(1)->toRawSql())

    ตัวสร้าง Eloquent

    \Log::debug(\App\User::limit(1)->toRawSql());

หมายเหตุ: จาก Laravel 5.1 ถึง 5.3 เนื่องจาก Eloquent Builder ไม่ได้ใช้ประโยชน์จากMacroableคุณลักษณะจึงไม่สามารถเพิ่มtoRawSqlชื่อแทนใน Eloquent Builder ได้ทันที ทำตามตัวอย่างด้านล่างเพื่อให้ได้เหมือนกัน

ตัวสร้าง Eloquent ( Laravel 5.1 - 5.3 )

\Log::debug(\App\User::limit(1)->getQuery()->toRawSql());

อ๊ะฉันมาสาย เพียงแค่ต้องการส่งคำตอบโดยใช้มาโคร นี่คือคำตอบที่ดีที่สุด ควรเป็นคำตอบที่ได้รับการยอมรับ: D
nmfzone

คุณสามารถสรุปส่วนหลังในขอบเขตบนโมเดลพื้นฐานได้
Ogier Schelvis


7

ตั้งแต่ laravel 5.2เป็นต้นไป คุณสามารถใช้DB::listenเพื่อเรียกค้นคิวรี่

DB::listen(function ($query) {
    // $query->sql
    // $query->bindings
    // $query->time
});

หรือถ้าคุณต้องการที่จะแก้ปัญหาBuilderอินสแตนซ์เดียวจากนั้นคุณสามารถใช้toSqlวิธีการ

DB::table('posts')->toSql(); 

1
สิ่งที่ฟังมีประโยชน์ให้ประกาศก่อนที่จะเรียกใช้แบบสอบถามและดัมพ์ sql & bindings ภายในเมธอด ไม่สมบูรณ์ แต่ทำงานเร็วขึ้น / ง่ายกว่าคำตอบอื่น ๆ
แอนดรู

7

วิธีที่ง่ายที่สุดมากที่สุดคือการทำให้ความผิดพลาดโดยเจตนา ตัวอย่างเช่นฉันต้องการดูแบบสอบถาม 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 Unknown คอลัมน์ '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จาก created_at และทดสอบ SQL นี้ตามที่คุณต้องการในตัวแก้ไข SQL ใด ๆ เช่นตัวแก้ไข phpMyAdmin SQL!

หมายเหตุ:

วิธีการแก้ปัญหาที่ได้รับการทดสอบกับLaravel 5.4


2
นี่คือคำตอบที่ดีที่สุดโดยไกล! ง่ายมาก! :)
Picard

สิ่งนี้จะไม่แสดงข้อความค้นหาที่มีการผูกเช่นการผูกจะแสดงเช่น:id
Shantha Kumara

@ShanthaKumara แน่นอนฉันไม่รู้ว่ารุ่นหรือการกำหนดค่าของ Laravel ที่คุณใช้อยู่คืออะไร อย่างไรก็ตามข้อมูลโค้ดหรือรหัสทุกคำตอบของฉันถูกคัดลอกและวางจากผลลัพธ์โค้ดจริงของโครงการ Laravel 5.4
SaidbakR

6

หากต้องการดูแบบสอบถามที่ดำเนินการ Laravel ให้ใช้บันทึกแบบสอบถาม laravel

DB::enableQueryLog();

$queries = DB::getQueryLog();

6

ในฐานะของ Laravel 5.8.15 ตัวสร้างคิวรีมี ddและdumpวิธีการเพื่อให้คุณสามารถทำได้

DB::table('data')->where('a', 1)->dump();

ขอบคุณ ววทำงานได้ดีจริงๆ DB :: table ('data') -> where ('a', 1) -> dd ();
Waqas

ดีกว่าคำตอบอื่น ๆ ที่ระบุไว้
Hamees A. Khan

5

นี่คือฟังก์ชั่นที่ฉันวางในคลาสโมเดลพื้นฐานของฉัน เพียงผ่านวัตถุตัวสร้างแบบสอบถามลงในนั้นและสตริง 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;
}


4

สำหรับ laravel 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()
    {
        //
    }
}

แหล่ง


4

เพิ่มฟังก์ชั่นนี้ในแอปพลิเคชันของคุณและเพียงโทร

function getQuery($sql){
        $query = str_replace(array('?'), array('\'%s\''), $sql->toSql());
        $query = vsprintf($query, $sql->getBindings());     
        return $query;
}

เอาท์พุท : "select * from userwhere lang= 'en' และstatus= '1' คำสั่งโดยupdated_atขีด จำกัด สูงสุด 25 ออฟเซ็ต 0"


3

คุณสามารถใช้แพ็คเกจนี้เพื่อรับข้อความค้นหาทั้งหมดที่กำลังดำเนินการเมื่อคุณโหลดหน้าเว็บของคุณ

https://github.com/barryvdh/laravel-debugbar

แพ็คเกจนั้นดีเมื่อคุณไม่มีข้อผิดพลาดของแบบสอบถาม หากคุณมีข้อผิดพลาด SQL จะไม่แสดงอะไรเลย
lewis4u


2

หากคุณไม่ได้ใช้ Laravel แต่ใช้แพ็คเกจ Eloquent:

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);

2

คุณสามารถใช้เครื่องจักร

Clockwork เป็นส่วนเสริมของ Chrome สำหรับการพัฒนา PHP ขยายเครื่องมือสำหรับนักพัฒนาด้วยพาเนลใหม่ที่ให้ข้อมูลทุกชนิดที่เป็นประโยชน์สำหรับการดีบักและรวบรวมแอปพลิเคชัน PHP ของคุณรวมถึงข้อมูลเกี่ยวกับคำขอส่วนหัวรับและโพสต์ข้อมูลคุกกี้ข้อมูลเซสชัน เส้นทางการแสดงผลแอปพลิเคชันรันไทม์และอื่น ๆ

แต่ทำงานได้ใน Firefox


2

ฉันได้สร้างฟังก์ชั่นง่าย ๆ เพื่อรับ 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 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 ],
// ]

2

เท่าที่ฉันรักกรอบนี้ฉันเกลียดเมื่อมันทำหน้าที่เหมือนอึ

DB::enableQueryLog()ไม่มีประโยชน์โดยสิ้นเชิง DB::listenไม่มีประโยชน์เท่ากัน มันแสดงให้เห็นส่วนหนึ่งของแบบสอบถามเมื่อฉันพูด$query->count()แต่ถ้าฉันทำ$query->get()มันก็ไม่มีอะไรจะพูด

วิธีแก้ปัญหาเดียวที่ทำงานได้อย่างต่อเนื่องคือการใส่ไวยากรณ์หรือข้อผิดพลาดอื่น ๆ ในพารามิเตอร์ ORM เช่นชื่อคอลัมน์ / ตารางที่ไม่มีอยู่ให้รันโค้ดของคุณบนบรรทัดคำสั่งขณะที่อยู่ในโหมดดีบั๊กและมันจะพ่นข้อผิดพลาด SQL ด้วยคำค้นหาเต็มรูปแบบในที่สุด มิฉะนั้นหวังว่าข้อผิดพลาดจะปรากฏในไฟล์บันทึกหากเรียกใช้จากเว็บเซิร์ฟเวอร์


บันทึกแบบสอบถามทำงานได้ดีสำหรับฉันอย่างน้อย คุณควรมีข้อผิดพลาดอื่น ๆ ในใบสมัครของคุณ
user1415066

1

หากคุณใช้ทิงเกอร์และต้องการบันทึกแบบสอบถาม 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",
   }
>>>

1

ลองสิ่งนี้:

$results = DB::table('users')->toSql();
dd($results);

หมายเหตุ: get () ถูกแทนที่ด้วย toSql () เพื่อแสดงเคียวรี SQL แบบ raw


1

วิธีการของฉันในการทำสิ่งนี้ตามมุมมองบันทึกจะต้องแก้ไขไฟล์เท่านั้นapp/Providers/AppServiceProvider.php:

  1. เพิ่มรหัสนี้ลงใน 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,
            ]
        );
    });
}
  1. รหัสจับ sql ของฉัน:
$users = DB::table('users')
    ->select(DB::raw('count(*) as user_count, username '))
    ->where('uid', '>=', 10)
    ->limit(100)
    ->groupBy('username')
    ->get()
;
dd($users);
  1. ดูบันทึก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} 
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.