Làm cách nào để tôi tạo Trình tạo truy vấn để xuất truy vấn SQL thô dưới dạng chuỗi?


544

Cho mã sau:

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

Tôi muốn lấy chuỗi truy vấn SQL thô mà trình xây dựng truy vấn cơ sở dữ liệu ở trên sẽ tạo. Trong ví dụ này, nó sẽ được SELECT * FROM users.

Làm thế nào để tôi làm điều này?


14
Laravel Eloquent ORM nhận được truy vấn thô:echo User::where('status', 1)->toSql();
Muhammad Shahzad

Tôi đang sử dụng một gói cho Laravel - Kính viễn vọng, nó ghi lại tất cả các truy vấn và làm nhiều việc khác.
vinsa

Câu trả lời:


660

Để xuất ra màn hình các truy vấn cuối cùng đã chạy, bạn có thể sử dụng:

DB::enableQueryLog(); // Enable query log

// Your Eloquent query executed by using get()

dd(DB::getQueryLog()); // Show results of log

Tôi tin rằng các truy vấn gần đây nhất sẽ ở dưới cùng của mảng.

Bạn sẽ có một cái gì đó như thế:

array(1) {
  [0]=>
  array(3) {
    ["query"]=>
    string(21) "select * from "users""
    ["bindings"]=>
    array(0) {
    }
    ["time"]=>
    string(4) "0.92"
  }
}

(Cảm ơn bình luận của Joshua bên dưới.)


2
hmm tôi không chắc nhưng bạn có thể đồng hành với những gì bạn muốn với gói soạn thảo stackoverflow.com/a/17339752/813181
jfortunato

9
Thậm chí có thể tốt hơn để xuất nó vào nhật ký ứng dụng của bạn bằng cách sử dụng Loglớp: Log::debug(DB::getQueryLog())
msturdy

35
Bạn có thể cần phải bật cái này khi nó bị tắt theo mặc định. Bạn có thể sử dụng lệnh này để bật tạm thời:DB::enableQueryLog();
Joshua Fricke

5
Tôi đã thử câu trả lời của bạn. Những gì tôi đã cố gắng là DB::enableQueryLog(); dd(DB::getQueryLog());Nhưng nó chỉ trở lại []....
Tôi là Người ngu ngốc nhất

6
Nếu bạn có nhiều cơ sở dữ liệu, bạn có thể cần phải làmDB::connection('database')->getQueryLog()
Damien Ó Ceallaigh

745

Sử dụng toSql()phương pháp trên một QueryBuilderví dụ.

DB::table('users')->toSql() sẽ trở lại:

chọn * từ `users`

Điều này dễ hơn là kết nối một trình lắng nghe sự kiện và cũng cho phép bạn kiểm tra xem truy vấn sẽ thực sự trông như thế nào tại bất kỳ điểm nào trong khi bạn đang xây dựng nó.


6
Tôi nghĩ rằng đây là cách dễ nhất khi sử dụng Eloquent bên ngoài Laravel
Gab

8
@Stormsson Điều đó là không thể bởi vì PHP không bao giờ có truy vấn với các ràng buộc được thay thế bằng các giá trị của chúng. Để có được toàn bộ các truy vấn, bạn cần phải đăng nhập chúng từ MySQL. Có thêm thông tin ở đây: stackoverflow.com/questions/1786322/ Kẻ
Matthew

40
@Stormsson bạn có thể sử dụng getBindingsphương pháp. Điều này sẽ trả về các ràng buộc để chúng sẽ được liên kết với câu lệnh SQL.
danronmoon

2
Rất hữu ích để gỡ lỗi các truy vấn phức tạp mà Eloquent từ chối chạy khi những truy vấn không hiển thị trong nhật ký truy vấn.
BobChao87

34
Để nhận được truy vấn với bindinds$query = \DB::table('users')->where('id', 10); $sql = str_replace_array('?', $query->getBindings(), $query->toSql()); dd($sql);
Ennio Sousa

88

DB::QueryLog()chỉ hoạt động sau khi bạn thực hiện truy vấn $builder->get(). nếu bạn muốn lấy truy vấn trước khi thực hiện truy vấn, bạn có thể sử dụng $builder->toSql()phương thức. đây là ví dụ làm thế nào để có được sql và liên kết nó:

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

    $result = $builder->get();

HOẶC chỉ làm cho lỗi truy vấn của bạn như gọi cho bảng hoặc cột không tồn tại, bạn sẽ thấy truy vấn được tạo trong ngoại lệ XD


3
Đây là, câu trả lời tốt nhất, đơn giản và đi thẳng vào vấn đề. Cảm ơn :)
Sobakus

18
Là một lớp lót:$query = vsprintf(str_replace(array('?'), array('\'%s\''), $builder->toSql()), $builder->getBindings());
kramer65

Điều này nên được bao gồm trong khung như là một hàm riêng .. cảm ơn
Tomáš Mleziva

Lưu ý rằng điều này sẽ không hoạt động nếu truy vấn của bạn đã có dấu phần trăm như đối với LIKEtruy vấn hoặc khi định dạng ngày. Bạn sẽ cần phải thoát khỏi những người đầu tiên với dấu hiệu phần trăm.
The Dev Dev

Có những lo ngại về an ninh khi làm điều này? Các ràng buộc đến vệ sinh từ $builder->getBindings()?
solidau

56

Bạn có thể nghe sự kiện 'illuminate.query'. Trước khi truy vấn thêm trình nghe sự kiện sau:

Event::listen('illuminate.query', function($query, $params, $time, $conn) 
{ 
    dd(array($query, $params, $time, $conn));
});

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

Điều này sẽ in ra một cái gì đó như:

array(4) {
  [0]=>
  string(21) "select * from "users""
  [1]=>
  array(0) {
  }
  [2]=>
  string(4) "0.94"
  [3]=>
  string(6) "sqlite"
}

1
Tôi nhận được phương thức Gọi đến không xác định Illuminate \ Database \ Query \ Builder :: lắng nghe () trong Laravel 4
Miguel Stevens

2
Cảm ơn điều này là tuyệt vời. Thật tốt khi lưu ý rằng dd là một hàm tạo ra kết xuất biến đã cho và thực hiện kết thúc tập lệnh và cũng để nhập Sự kiện, bao gồmuse Illuminate\Support\Facades\Event;
radtek

1
@radtek: Thay vì use Illuminate\Support\Facades\Event;bạn chỉ có thể làm use Event;vì đó là mặt tiền .
TachyonVortex 4/12/2015

50

Nếu bạn đang cố lấy Nhật ký bằng Illuminate mà không cần sử dụng Laravel:

\Illuminate\Database\Capsule\Manager::getQueryLog();

Bạn cũng có thể cập nhật một chức năng nhanh như vậy:

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

BIÊN TẬP

các phiên bản cập nhật dường như đã vô hiệu hóa ghi nhật ký truy vấn (ở trên trả về một mảng trống). Để bật lại, khi khởi chạy Trình quản lý Capsule, hãy lấy một thể hiện của kết nối và gọi enableQueryLogphương thức

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

CHỈNH SỬA

Cân nhắc câu hỏi thực tế, bạn thực sự có thể thực hiện các thao tác sau để chuyển đổi truy vấn đơn hiện tại thay vì tất cả các truy vấn trước đó:

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

tôi đang nhận được loại trả về này từ truy vấn "name = [{" name ":" rifat "}]" tôi chỉ cần làm gì để có được "name = rifat"?
kết hợp

Tôi sẽ in ra các ràng buộc của bạn, có vẻ như bạn đang truyền một mảng thay vì một chuỗi
Luke Snowden

Đây là một khởi đầu hữu ích, nhưng dường như bỏ qua việc thêm các trích dẫn đơn xung quanh các giá trị được tham số hóa, chẳng hạn như khi tôi chuyển một chuỗi như thế nào 'US/Eastern'.
Ryan

1
@Ryan điều này là đúng do đó tôi đã nêu quick function. Tôi tin rằng mã cơ bản sẽ sử dụng các phương thức chuẩn bị ( php.net/manual/en/mysqli.prepare.php ), đó là lý do tại sao chỉ ?cần có. Bạn có thể php.net/manual/en/feft.is-numeric.php để xác định xem có nên đóng gói đầu vào trong các dấu ngoặc đơn hay không.
Luke Snowden

1
@LukeSnowden Câu trả lời của bạn là thiên tài! Cuối cùng tôi đã dành thời gian để dùng thử phiên bản mới của bạn (mà tôi đã chỉnh sửa ở trên để bao gồm is_numericý tưởng của bạn ), và nó hoạt động! Tôi thích điều này. Cảm ơn bạn.
Ryan

36

Có một phương pháp hùng hồn để nhận chuỗi truy vấn.

toSql ()

trong trường hợp của chúng ta,

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

trở về

select * from users

là giải pháp chính xác trả về chuỗi truy vấn SQL .. Hy vọng điều này hữu ích ...


11
những gì về các ràng buộc truy vấn? ví dụ như khi bạn làm ->where('foo', '=', 'bar')thanh sẽ không hiển thị trong sql
Toskan

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

Điều này chính xác hơn, được kiểm soát và đáp ứng nhu cầu của câu hỏi.
benjaminhull

Cảm ơn bình luận của bạn.
Kuldeep Mishra

2
Bạn có thể nối thêm ->toSql()như bạn sẽ làm nếu có nhiều đối số sau mô hình. ví dụUser::where('id', 1)->toSql()
Toby Mellor

24

Nếu bạn sử dụng laravel 5.1 và MySQL, bạn có thể sử dụng chức năng này do tôi thực hiện:

/*
 *  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;
}

Là một tham số đầu vào, bạn có thể sử dụng một trong hai

Chiếu sáng \ Cơ sở dữ liệu \ Eloquent \ Builder

Chiếu sáng \ Cơ sở dữ liệu \ Eloquent \ Quan hệ \ HasMany

Chiếu sáng \ Cơ sở dữ liệu \ Truy vấn \ Builder


Câu trả lời được cải thiện để bao gồm tất cả các nhận xét được thực hiện trong các ý kiến. Cảm ơn rât nhiều.
Yevgeniy Afanasyev

13

Trước tiên, bạn sẽ cần kích hoạt nhật ký truy vấn bằng cách gọi:

DB::enableQueryLog();

sau khi truy vấn bằng mặt tiền DB, bạn có thể viết:

dd(DB::getQueryLog());

đầu ra sẽ như dưới đây:

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

câu trả lời rất hữu ích
Anoop PS

hi tôi đã sử dụng $ result = DB :: select ('select * từ sqrt_user_modules trong đó user_id =: id', ['id' => $ user]); DB :: enableQueryLog (); nhưng không nhận được bất kỳ dd đầu ra nào (DB :: getQueryLog ());
Anoop PS

chúng ta có cần bao gồm bất kỳ thư viện nào không
Anoop PS

1
Bước 1: DB :: enableQueryLog (); bước 2: $ result = DB :: select ('select * từ sqrt_user_modules trong đó user_id =: id', ['id' => $ user]); bước 3: dd (DB :: getQueryLog ());
Ravi Mane

12

Đây là giải pháp tốt nhất mà tôi có thể đề xuất cho bất kỳ ai để gỡ lỗi truy vấn cuối cùng hoặc truy vấn cuối cùng mặc dù điều này cũng đã được thảo luận:

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

Cách thứ nhất:

Đơn giản là bạn có thể làm những thứ sau bằng toSql()phương pháp,

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

echo $query->toSql();

Nếu nó không hoạt động, bạn có thể thiết lập mọi thứ từ tài liệu laravel .

Cách thứ hai:

Một cách khác để làm điều đó là

DB::getQueryLog()

nhưng nếu nó trả về một mảng trống thì theo mặc định nó bị vô hiệu hóa, hãy truy cập vào đây ,

chỉ cần kích hoạt DB::enableQueryLog()và nó sẽ hoạt động :)

để biết thêm thông tin, hãy truy cập Github Vấn đề để biết thêm về nó.

Hy vọng nó giúp :)


10

Một thay thế 'vĩ mô' để có được truy vấn SQL với các ràng buộc.

  1. Thêm hàm macro bên dưới trong phương thức.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. Thêm một bí danh cho Eloquent Builder. ( Ấu trùng 5,4+ )

    \Illuminate\Database\Eloquent\Builder::macro('toRawSql', function(){
        return ($this->getQuery()->toRawSql());
    });
  3. Sau đó gỡ lỗi như bình thường. ( Ấu trùng 5,4+ )

    Ví dụ: Trình tạo truy vấn

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

    Ví dụ: Trình tạo Eloquent

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

Lưu ý: từ Laravel 5.1 đến 5.3, vì Eloquent Builder không sử dụng Macroableđặc điểm này, không thể thêm toRawSqlbí danh vào Eloquent Builder khi đang di chuyển. Thực hiện theo ví dụ dưới đây để đạt được điều tương tự.

Ví dụ: Trình tạo Eloquent ( Laravel 5.1 - 5.3 )

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

Rất tiếc, tôi đến muộn. Chỉ muốn gửi câu trả lời bằng Macro. Đây là câu trả lời đẹp nhất. Nên là câu trả lời được chấp nhận: D
nmfzone

Bạn có thể trừu tượng hóa cái sau trong một phạm vi trên Mô hình cơ sở
Ogier Schelvis


7

Từ laravel 5.2trở đi. bạn có thể sử dụng DB::listenđể có được các truy vấn thực hiện.

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

Hoặc nếu bạn muốn gỡ lỗi một Builderthể hiện thì bạn có thể sử dụng toSqlphương thức.

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

1
Điều nghe là hữu ích, khai báo nó trước khi chạy truy vấn và loại bỏ sql & ràng buộc trong phương thức. Không hoàn hảo nhưng hoạt động nhanh hơn / dễ dàng hơn các câu trả lời khác.
Andrew

7

Cách dễ nhất là phạm sai lầm có chủ ý . Ví dụ: tôi muốn xem toàn bộ truy vấn SQL của mối quan hệ sau:

 public function jobs()
        {
            return $this->belongsToMany(Job::class, 'eqtype_jobs')
                   ->withPivot(['created_at','updated_at','id'])
                   ->orderBy('pivot_created_at','desc');
        }

Tôi chỉ để tạo một cột không được tìm thấy, ở đây tôi chọn created_atvà tôi đã thay đổi nó thành created_atsbằng cách thêm dấu svào:

public function jobs()
            {
                return $this->belongsToMany(Job::class, 'eqtype_jobs')
                       ->withPivot(['created_ats','updated_at','id'])
                       ->orderBy('pivot_created_at','desc');
            }

Vì vậy, trình gỡ lỗi sẽ trả về lỗi sau:

(4/4) ErrorException SQLSTATE [42S22]: Cột không tìm thấy: 1054 Unknown column 'eqtype_jobs.created_ats' trong 'danh sách trường' (SQL: select jobs*,. eqtype_jobs. set_idNhư pivot_set_id, eqtype_jobs. job_idNhư pivot_job_id, eqtype_jobs. created_ats Như pivot_created_ats, eqtype_jobs. updated_atNhư pivot_updated_at, eqtype_jobs. idNhư pivot_idtừ jobstham gia bên trong eqtype_jobsvào jobs. id= eqtype_jobs. job_idwhere eqtype_jobs. set_id= 56 thứ tự theo pivot_created_atgiới hạn desc 20 offset 0) (Xem: /home/said/www/factory/resource/view/set/show.blade.php)

Thông báo lỗi trên trả về truy vấn SQL đầy đủ với lỗi

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

Bây giờ, chỉ cần loại bỏ phần bổ sung stừ created_at và kiểm tra SQL này như bạn muốn trong bất kỳ trình soạn thảo SQL nào như trình soạn thảo SQL phpMyAdmin!

Để ý:

Giải pháp đã được thử nghiệm với Laravel 5.4 .


2
Đây là câu trả lời tốt nhất cho đến nay! Quá đơn giản! :)
Picard

Điều này sẽ không hiển thị truy vấn với các ràng buộc, tức là các ràng buộc sẽ hiển thị như thế:id
Chaiha Kumara

@ShanthaKumara Thật vậy, tôi không biết phiên bản hoặc cấu hình của Laravel mà bạn đã sử dụng là gì. Tuy nhiên, mọi đoạn mã hoặc mã trong câu trả lời của tôi đã được sao chép và dán từ đầu ra mã thực của dự án Laravel 5.4.
SaidbakR

6

Để xem Truy vấn được thực hiện của Laravel, hãy sử dụng nhật ký truy vấn laravel

DB::enableQueryLog();

$queries = DB::getQueryLog();

6

Kể từ phiên bản Laravel 5.8.15, trình xây dựng truy vấn hiện có dddumpcác phương thức để bạn có thể thực hiện

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

Cảm ơn. dd hoạt động thực sự tốt. Bảng DB :: ('dữ liệu') -> trong đó ('a', 1) -> dd ();
Waqas

Tốt hơn so với các câu trả lời khác được liệt kê.
Hamees A. Khan

5

Đây là chức năng, tôi đặt trong lớp mô hình cơ sở của tôi. Chỉ cần truyền đối tượng xây dựng truy vấn vào nó và chuỗi SQL sẽ được trả về.

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

Đối với ấu trùng 5.5.X

Nếu bạn muốn nhận từng truy vấn SQL được thực hiện bởi ứng dụng của mình, bạn có thể sử dụng phương thức nghe. Phương pháp này rất hữu ích để ghi nhật ký truy vấn hoặc gỡ lỗi. Bạn có thể đăng ký người nghe truy vấn của bạn trong một nhà cung cấp dịch vụ:

<?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()
    {
        //
    }
}

Nguồn


4

Thêm chức năng này vào ứng dụng của bạn và chỉ cần gọi.

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

Đầu ra : "select * from userwhere lang= 'en' và status= '1' thứ tự theo updated_atgiới hạn desc 25 offset 0"


3

Bạn có thể sử dụng gói này để nhận tất cả các truy vấn đang thực hiện khi bạn tải trang của mình

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

Gói đó là tốt khi bạn không có lỗi truy vấn. Nếu bạn gặp lỗi SQL, nó sẽ không hiển thị bất cứ điều gì
lewis4u

3

In truy vấn cuối cùng

DB::enableQueryLog();

$query        = DB::getQueryLog();
$lastQuery    = end($query);
print_r($lastQuery);

2

Nếu bạn không sử dụng Laravel mà sử dụng gói Eloquent thì:

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

bạn có thể sử dụng đồng hồ

Clockwork là một tiện ích mở rộng của Chrome để phát triển PHP, mở rộng Công cụ dành cho nhà phát triển với bảng điều khiển mới cung cấp tất cả các loại thông tin hữu ích để gỡ lỗi và định hình các ứng dụng PHP của bạn, bao gồm thông tin về yêu cầu, tiêu đề, nhận và đăng dữ liệu, cookie, dữ liệu phiên, truy vấn cơ sở dữ liệu, các tuyến đường, trực quan hóa thời gian chạy ứng dụng và nhiều hơn nữa.

nhưng cũng hoạt động trong firefox


2

Tôi đã tạo một số hàm đơn giản để lấy SQL và các ràng buộc từ một số truy vấn.

/**
 * 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;
}

Sử dụng:

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

Nhiều như tôi yêu khung này, tôi ghét khi nó hoạt động như tào lao.

DB::enableQueryLog()là hoàn toàn vô dụng. DB::listencũng vô dụng không kém. Nó cho thấy một phần của truy vấn khi tôi nói $query->count(), nhưng nếu tôi làm $query->get(), nó không có gì để nói.

Giải pháp duy nhất có vẻ hoạt động ổn định là cố ý đặt một số cú pháp hoặc lỗi khác trong các tham số ORM, như tên cột / bảng không tồn tại, chạy mã của bạn trên dòng lệnh trong khi ở chế độ gỡ lỗi và nó sẽ phát sinh lỗi SQL với truy vấn đầy đủ của frickin cuối cùng. Nếu không, hy vọng lỗi xuất hiện trong tệp nhật ký nếu chạy từ máy chủ web.


Nhật ký truy vấn hoạt động tốt với tôi ít nhất. Bạn sẽ có một số lỗi khác trong ứng dụng của mình
user1415066

1

Nếu bạn đang sử dụng tinker và muốn đăng nhập truy vấn SQL được hình thành, bạn có thể làm

$ 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

Thử cái này:

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

Lưu ý: get () đã được thay thế bằng toSql () để hiển thị truy vấn SQL thô.


1

Cách của tôi để làm điều này, dựa trên chế độ xem nhật ký, chỉ cần sửa đổi tệp app/Providers/AppServiceProvider.php:

  1. Thêm mã này vào 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. Mã xử lý sql của tôi:
$users = DB::table('users')
    ->select(DB::raw('count(*) as user_count, username '))
    ->where('uid', '>=', 10)
    ->limit(100)
    ->groupBy('username')
    ->get()
;
dd($users);
  1. Xem nhật ký 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} 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.