Wie kann ich den Abfrage-Generator veranlassen, seine unformatierte SQL-Abfrage als Zeichenfolge auszugeben?

544

Gegeben den folgenden Code:

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

Ich möchte die unformatierte SQL-Abfragezeichenfolge abrufen, die der obige Builder für Datenbankabfragen generiert. In diesem Beispiel wäre es SELECT * FROM users.

Wie mache ich das?

Meiryo
quelle
14
Laravel Eloquent ORM erhalten rohe Anfrage:echo User::where('status', 1)->toSql();
Muhammad Shahzad
Ich verwende ein Paket für Laravel - Telescope, es protokolliert alle Abfragen und erledigt viele weitere Dinge.
Vinsa

Antworten:

660

Um die zuletzt ausgeführten Abfragen auf dem Bildschirm auszugeben, können Sie Folgendes verwenden:

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

// Your Eloquent query executed by using get()

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

Ich glaube, die neuesten Abfragen werden am Ende des Arrays angezeigt.

Sie werden so etwas haben:

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

(Dank Joshuas Kommentar unten.)

jfortunato
quelle
2
hmm ich bin nicht sicher, aber Sie können möglicherweise mit einem Komponistenpaket stackoverflow.com/a/17339752/813181
jfortunato
9
Vielleicht ist es sogar besser, es mit der folgenden LogKlasse in das Protokoll Ihrer Anwendung Log::debug(DB::getQueryLog())
auszugeben
35
Möglicherweise müssen Sie dies aktivieren, da es jetzt standardmäßig deaktiviert ist. Sie können diesen Befehl verwenden, um ihn vorübergehend DB::enableQueryLog();
Joshua Fricke
5
Ich habe deine Antwort versucht. Was ich versucht habe ist, DB::enableQueryLog(); dd(DB::getQueryLog());aber es kehrt nur zurück []...
Ich bin die dümmste Person
6
Wenn Sie mehrere Datenbanken haben, müssen Sie möglicherweise tunDB::connection('database')->getQueryLog()
Damien Ó Ceallaigh
745

Verwenden Sie die toSql()Methode für eine QueryBuilderInstanz.

DB::table('users')->toSql() würde zurückkehren:

Wählen Sie * unter "Benutzer"

Dies ist einfacher als das Verkabeln eines Ereignis-Listeners. Außerdem können Sie überprüfen, wie die Abfrage zu jedem Zeitpunkt während der Erstellung tatsächlich aussehen wird.

Steven Mercatante
quelle
6
Ich denke, dies ist der einfachste Weg, wenn Sie Eloquent außerhalb von Laravel verwenden
Gab
8
@Stormsson Das ist nicht möglich, da in PHP die Abfrage niemals durch die Bindungen ersetzt wird. Um die Abfragen vollständig zu erhalten, müssen Sie sie von MySQL aus protokollieren. Es gibt weitere Informationen hier: stackoverflow.com/questions/1786322/…
Matthew
40
@Stormsson können Sie getBindingsMethode verwenden. Dadurch werden die Bindungen zurückgegeben, damit sie an die SQL-Anweisung gebunden werden.
Danronmoon
2
Sehr hilfreich beim Debuggen komplizierter Abfragen, die Eloquent nicht ausführen möchte, da diese nicht im Abfrageprotokoll angezeigt werden.
BobChao87
34
Um eine Abfrage mit Bindinds zu erhalten$query = \DB::table('users')->where('id', 10); $sql = str_replace_array('?', $query->getBindings(), $query->toSql()); dd($sql);
Ennio Sousa
88

DB::QueryLog()Arbeiten Sie erst, nachdem Sie die Abfrage ausgeführt haben $builder->get(). Wenn Sie die Abfrage erhalten möchten, bevor Sie die Abfrage ausführen, können Sie die $builder->toSql()Methode verwenden. Dies ist das Beispiel, wie Sie die SQL erhalten und binden:

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

    $result = $builder->get();

ODER machen Sie einfach Ihren Abfragefehler wie das Aufrufen einer nicht vorhandenen Tabelle oder Spalte. In Ausnahme XD wird die generierte Abfrage angezeigt

Kakashi
quelle
3
Dies ist bei weitem die beste Antwort, einfach und direkt auf den Punkt. Danke :)
Sobakus
18
Als $query = vsprintf(str_replace(array('?'), array('\'%s\''), $builder->toSql()), $builder->getBindings());
Einzeiler
Dies sollte als native Funktion in das Framework aufgenommen werden. Danke
Tomáš Mleziva
Beachten Sie, dass dies nicht funktioniert, wenn Ihre Abfrage bereits Prozentzeichen aufweist, z. B. für eine LIKEAbfrage oder beim Formatieren von Daten. Sie müssen diesen zuerst mit doppelten Prozentzeichen entkommen.
The Unknown Dev
Gibt es dabei Sicherheitsbedenken? Kommen die Bindungen desinfiziert $builder->getBindings()?
Solidau
56

Sie können das Ereignis 'illuminate.query' anhören. Fügen Sie vor der Abfrage den folgenden Ereignis-Listener hinzu:

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

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

Dies wird etwas ausdrucken wie:

array(4) {
  [0]=>
  string(21) "select * from "users""
  [1]=>
  array(0) {
  }
  [2]=>
  string(4) "0.94"
  [3]=>
  string(6) "sqlite"
}
Rubens Mariuzzo
quelle
1
Ich erhalte den Aufruf einer undefinierten Methode Illuminate \ Database \ Query \ Builder :: listen () in Laravel 4
Miguel Stevens
2
Danke das ist toll. Es ist gut zu beachten, dass dd eine Funktion ist, die einen Dump der angegebenen Variablen erzeugt und die Ausführung des Skripts beendet, und dass zum Importieren eines Ereignissesuse Illuminate\Support\Facades\Event;
radtek
1
@radtek: Stattdessen use Illuminate\Support\Facades\Event;kannst du es einfach machen, use Event;da es eine Fassade ist .
TachyonVortex
50

Wenn Sie versuchen, das Protokoll mit Illuminate ohne Laravel abzurufen, verwenden Sie:

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

Sie können auch eine schnelle Funktion wie folgt aktivieren:

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

BEARBEITEN

In aktualisierten Versionen scheint die Abfrageprotokollierung standardmäßig deaktiviert zu sein (oben wird ein leeres Array zurückgegeben). Um sich beim Initialisieren des Capsule Managers wieder einzuschalten, greifen Sie auf eine Instanz der Verbindung zu und rufen Sie die enableQueryLogMethode auf

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

WIEDER BEARBEITEN

Unter Berücksichtigung der eigentlichen Frage können Sie Folgendes tun, um die aktuelle Einzelabfrage anstelle aller vorherigen Abfragen zu konvertieren:

$sql = $query->toSql();
$bindings = $query->getBindings();
Luke Snowden
quelle
Ich erhalte diese Art der Rückgabe von der Abfrage "name = [{" name ":" rifat "}]" Was muss ich tun, um nur "name = rifat" zu erhalten?
unkörperlich
Ich würde Ihre Bindungen ausdrucken, sieht aus, als würden Sie ein Array anstelle einer Zeichenfolge übergeben
Luke Snowden
Dies ist ein hilfreicher Anfang, aber es scheint zu vernachlässigen, einfache Anführungszeichen um parametrisierte Werte hinzuzufügen, z. B. wenn ich eine Zeichenfolge wie z 'US/Eastern'.
Ryan
1
@ Ryan das ist wahr, deshalb habe ich angegeben quick function. Ich glaube, dass der zugrunde liegende Code Vorbereitungsmethoden ( php.net/manual/en/mysqli.prepare.php ) verwenden wird, weshalb nur die ?erforderlich sind. Sie können php.net/manual/en/function.is-numeric.php verwenden , um zu bestimmen, ob die Eingabe in einfache Anführungszeichen eingeschlossen werden soll oder nicht.
Luke Snowden
1
@LukeSnowden Deine Antwort ist genial! Ich habe mir endlich die Zeit genommen, Ihre neue Version auszuprobieren (die ich oben bearbeitet habe, um Ihre is_numericIdee aufzunehmen), und sie funktioniert! Ich liebe es. Vielen Dank.
Ryan
36

In eloquent gibt es eine Methode zum Abrufen von Abfragezeichenfolgen.

toSql ()

in unserem Fall,

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

Rückkehr

select * from users

ist die genaue Lösung, die die SQL-Abfragezeichenfolge zurückgibt.

CelinVeronicca
quelle
11
Was ist mit den Abfragebindungen? zB wenn Sie ->where('foo', '=', 'bar')Bar nicht in der SQL zeigen
Toskan
28
$data = User::toSql();
echo $data; //this will retrun select * from users. //here User is model
Kuldeep Mishra
quelle
Dies ist viel präziser, kontrollierter und entspricht den Anforderungen der Frage.
Benjamin
Danke für deinen Kommentar.
Kuldeep Mishra
2
Sie können wie gewohnt anhängen ->toSql(), wenn nach dem Modell weitere Argumente vorhanden sind. zBUser::where('id', 1)->toSql()
Toby Mellor
24

Wenn Sie Laravel 5.1 und MySQL verwenden, können Sie diese von mir erstellte Funktion verwenden:

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

Als Eingabeparameter können Sie einen dieser Parameter verwenden

Beleuchten Sie \ Database \ Eloquent \ Builder

Beleuchten Sie \ Database \ Eloquent \ Relations \ HasMany

Beleuchten Sie \ Database \ Query \ Builder

Jewgenij Afanasjew
quelle
Die Antwort wurde verbessert und enthält alle Anmerkungen in den Kommentaren. Vielen Dank.
Jewgenij Afanasjew
13

Zuerst müssen Sie das Abfrageprotokoll aktivieren, indem Sie Folgendes aufrufen:

DB::enableQueryLog();

Nach Abfragen über die DB-Fassade können Sie schreiben:

dd(DB::getQueryLog());

Die Ausgabe wird wie folgt aussehen:

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
  ]
]
Ravi Mane
quelle
sehr hilfreiche Antwort
Anoop PS
Hallo, ich habe $ result = DB :: select verwendet ('select * from sqrt_user_modules where user_id =: id', ['id' => $ user]); DB :: enableQueryLog (); aber keine Ausgabe dd erhalten (DB :: getQueryLog ());
Anoop PS
Anoop PS
1
Schritt 1: DB :: enableQueryLog (); Schritt 2: $ result = DB :: select ('select * from sqrt_user_modules where user_id =: id', ['id' => $ user]); Schritt 3: dd (DB :: getQueryLog ());
Ravi Mane
12

Dies ist die weitaus beste Lösung, die ich jedem empfehlen kann, um beredte letzte oder letzte Abfragen zu debuggen, obwohl dies ebenfalls diskutiert wurde:

// 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);
justnajm
quelle
10

Erster Weg:

Einfach können Sie folgende Dinge mit toSql()Methode tun ,

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

echo $query->toSql();

Wenn es nicht funktioniert, können Sie das Ding aus der Laravel-Dokumentation einrichten .

Zweiter Weg:

Ein anderer Weg ist es

DB::getQueryLog()

aber wenn es ein leeres Array zurück dann standardmäßig ist es deaktiviert Besuch dieses ,

einfach aktivieren mit DB::enableQueryLog()und es wird funktionieren :)

Weitere Informationen finden Sie in der Github- Ausgabe , um mehr darüber zu erfahren.

Ich hoffe es hilft :)

Sagar Naliyapara
quelle
10

Ein 'makroable' Ersatz, um die SQL-Abfrage mit den Bindungen zu erhalten.

  1. Fügen Sie unten die Makrofunktion in der Methode hinzu.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. Fügen Sie einen Alias ​​für den Eloquent Builder hinzu. ( Laravel 5.4+ )

    \Illuminate\Database\Eloquent\Builder::macro('toRawSql', function(){
        return ($this->getQuery()->toRawSql());
    });
  3. Dann wie gewohnt debuggen. ( Laravel 5.4+ )

    ZB Query Builder

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

    ZB Eloquent Builder

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

Hinweis: Da Eloquent Builder von Laravel 5.1 bis 5.3 das MacroableMerkmal nicht verwendet , kann toRawSqldem Eloquent Builder im laufenden Betrieb kein Alias hinzugefügt werden . Befolgen Sie das folgende Beispiel, um dasselbe zu erreichen.

ZB Eloquent Builder ( Laravel 5.1 - 5.3 )

\Log::debug(\App\User::limit(1)->getQuery()->toRawSql());
Ijas Ameenudeen
quelle
Hoppla, ich bin spät gekommen. Ich möchte nur eine Antwort mit Makro senden. Dies ist die schönste Antwort. Sollte die akzeptierte Antwort sein: D
nmfzone
Sie können letztere in einem Bereich auf dem Basismodell
Ogier Schelvis
8

Verwenden Sie das Debugbar-Paket

composer require "barryvdh/laravel-debugbar": "2.3.*"

Geben Sie hier die Bildbeschreibung ein

panqingqiang
quelle
7

Ab Laravel 5.2und weiter. Sie können verwenden DB::listen, um ausgeführte Abfragen zu erhalten.

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

Wenn Sie eine einzelne BuilderInstanz debuggen möchten, können Sie die toSqlMethode verwenden.

DB::table('posts')->toSql(); 
Zayn Ali
quelle
1
Das Listen-Ding ist nützlich, deklarieren Sie es, bevor Sie die Abfrage ausführen, und geben Sie die SQL & Bindings innerhalb der Methode aus. Unvollkommen, funktioniert aber schneller / einfacher als andere Antworten.
Andrew
7

Am einfachsten ist es, absichtliche Fehler zu machen . Zum Beispiel möchte ich die vollständige SQL-Abfrage der folgenden Beziehung sehen:

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

Ich möchte nur eine Spalte erstellen, die nicht gefunden wird. Hier wähle ich sie aus created_atund ändere sie created_atsdurch Hinzufügen von Trailing szu:

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

Der Debuger gibt also den folgenden Fehler zurück:

(4/4) Error SQLSTATE [42S22]: Column nicht gefunden: 1054 Unknown column 'eqtype_jobs.created_ats' in 'field list' (SQL: select jobs*,. eqtype_jobs. set_idWie pivot_set_id, eqtype_jobs. job_idSo pivot_job_id, eqtype_jobs. created_ats Wie pivot_created_ats, eqtype_jobs. updated_atWie pivot_updated_at, eqtype_jobs. , idWie pivot_idaus jobsinnere Verbindung eqtype_jobsauf jobs. id=eqtype_jobs . job_idwhere eqtype_jobs. set_id= 56 order by pivot_created_atdesc limit 20 offset 0) (Ansicht: /home/said/www/factory/resources/views/set/show.blade.php)

Die obige Fehlermeldung gibt die vollständige SQL-Abfrage mit dem Fehler zurück

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

Entfernen Sie jetzt einfach das Extra saus created_at und testen Sie dieses SQL, wie Sie möchten, in einem beliebigen SQL-Editor wie dem phpMyAdmin SQL-Editor!

Beachten:

Die Lösung wurde mit Laravel 5.4 getestet .

SaidbakR
quelle
2
Dies ist bei weitem die beste Antwort! So einfach! :)
Picard
Dies wird nicht die Abfrage mit Bindungen zeigen, dh Bindungen werden wie:id
Shantha Kumara
@ShanthaKumara In der Tat weiß ich nicht, welche Version oder Konfiguration von Laravel Sie verwendet haben. Jedes Snippet oder jeder Code in meiner Antwort wurde jedoch aus der realen Code-Ausgabe des Laravel 5.4-Projekts kopiert und eingefügt.
SaidbakR
6

Verwenden Sie das Laravel-Abfrageprotokoll, um die ausgeführte Laravel-Abfrage anzuzeigen

DB::enableQueryLog();

$queries = DB::getQueryLog();
Jasim Juwel
quelle
6

Ab Laravel 5.8.15 der Query Builder jetzt hat dd und dumpMethoden so können Sie tun

DB::table('data')->where('a', 1)->dump();
Greg
quelle
Vielen Dank. dd funktioniert wirklich gut. DB :: table ('data') -> where ('a', 1) -> dd ();
Waqas
Besser als andere Antworten.
Hamees A. Khan
5

Dies ist die Funktion, die ich in meine Basismodellklasse eingefügt habe. Übergeben Sie einfach das Query Builder-Objekt und die SQL-Zeichenfolge wird zurückgegeben.

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;
}
BoogieBug
quelle
4

Für Laravel 5.5.X.

Wenn Sie jede von Ihrer Anwendung ausgeführte SQL-Abfrage erhalten möchten, können Sie die Listen-Methode verwenden. Diese Methode ist nützlich zum Protokollieren von Abfragen oder zum Debuggen. Sie können Ihren Abfrage-Listener bei einem Dienstanbieter registrieren:

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

Quelle

scre_www
quelle
4

Fügen Sie diese Funktion Ihrer Anwendung hinzu und rufen Sie einfach an.

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

Ausgabe : " Wählen Sie * aus, userwobei lang= 'en' und status= '1' nach updated_atabsteigender Grenze 25 Offset 0 sortieren."

Dharmik
quelle
3

Mit diesem Paket können Sie alle Abfragen abrufen, die beim Laden Ihrer Seite ausgeführt werden

https://github.com/barryvdh/laravel-debugbar
Lakhwinder Singh
quelle
Dieses Paket ist gut, wenn Sie keine Abfragefehler haben. Wenn Sie einen SQL-Fehler haben, wird nichts
angezeigt
3

Letzte Abfrage drucken

DB::enableQueryLog();

$query        = DB::getQueryLog();
$lastQuery    = end($query);
print_r($lastQuery);
Sohomdeep Paul
quelle
2

Wenn Sie nicht Laravel verwenden, sondern das Eloquent-Paket verwenden, dann:

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);
Salman Ahmed
quelle
2

Sie können Uhrwerk verwenden

Clockwork ist eine Chrome-Erweiterung für die PHP-Entwicklung, die die Entwicklertools um ein neues Bedienfeld erweitert, das alle Arten von Informationen enthält, die zum Debuggen und Profilieren Ihrer PHP-Anwendungen nützlich sind, einschließlich Informationen zu Anforderungen, Headern, Abruf- und Postdaten, Cookies, Sitzungsdaten, Datenbankabfragen usw. Routen, Visualisierung der Anwendungslaufzeit und mehr.

funktioniert aber auch in Firefox

wdog
quelle
2

Ich habe einige einfache Funktionen erstellt, um SQL und Bindungen aus einigen Abfragen abzurufen.

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

Verwendungszweck:

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 ],
// ]
bla bla bla
quelle
2

So sehr ich diesen Rahmen liebe, ich hasse es, wenn er sich wie Mist verhält.

DB::enableQueryLog()ist völlig nutzlos. DB::listenist ebenso nutzlos. Es zeigte einen Teil der Abfrage, als ich sagte $query->count(), aber wenn ich es tue$query->get() , hat es nichts zu sagen.

Die einzige Lösung, die konsistent zu funktionieren scheint, besteht darin, absichtlich eine Syntax oder einen anderen Fehler in die ORM-Parameter einzufügen, z. B. einen nicht vorhandenen Spalten- / Tabellennamen, Ihren Code im Debug-Modus in der Befehlszeile auszuführen und den SQL-Fehler auszuspucken mit der vollen verdammten Abfrage endlich. Andernfalls wird der Fehler hoffentlich in der Protokolldatei angezeigt, wenn er vom Webserver ausgeführt wird.

Spencer Williams
quelle
Das Abfrageprotokoll funktioniert zumindest für mich einwandfrei. Sie sollten einige andere Fehler in Ihrer Anwendung haben
user1415066
1

Wenn Sie Tinker verwenden und die erstellte SQL-Abfrage protokollieren möchten, können Sie dies tun

$ 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: "[email protected]",
     created_at: "2019-01-11 19:06:23",
     updated_at: "2019-01-11 19:06:23",
   }
>>>
Prafulla Kumar Sahu
quelle
1

Versuche dies:

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

Hinweis: get () wurde durch toSql () ersetzt, um die unformatierte SQL-Abfrage anzuzeigen.

Nikhil Gyan
quelle
1

Meine Vorgehensweise, basierend auf der Protokollansicht, muss nur die Datei ändern app/Providers/AppServiceProvider.php:

  1. Fügen Sie diesen Code hinzu 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. Mein SQL-Handle-Code:
$users = DB::table('users')
    ->select(DB::raw('count(*) as user_count, username '))
    ->where('uid', '>=', 10)
    ->limit(100)
    ->groupBy('username')
    ->get()
;
dd($users);
  1. Siehe Protokoll 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} 
Lupguo
quelle