it-swarm.com.de

Wie kann ich den Query Builder dazu bringen, seine Raw SQL-Abfrage als String auszugeben?

Gegeben der folgende Code:

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

Ich möchte die unformatierte SQL-Abfragezeichenfolge abrufen, die der Datenbank-Abfrage-Generator oben generiert. In diesem Beispiel wäre es SELECT * FROM users.

Wie mache ich das?

355
meiryo

Um die letzten durchgeführten Abfragen auf dem Bildschirm auszugeben, können Sie dies verwenden

dd(DB::getQueryLog());

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

Sie werden so etwas haben:

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

Gemäß dem untenstehenden Kommentar von Joshua ist dieser jetzt standardmäßig deaktiviert. Zur Verwendung müssen Sie es manuell aktivieren, indem Sie Folgendes verwenden:

DB::enableQueryLog();
421
jfortunato

Verwenden Sie die toSql()-Methode für eine QueryBuilder-Instanz.

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

wählen Sie * aus "Benutzer" aus

Dies ist einfacher als das Verdrahten eines Ereignis-Listeners. Außerdem können Sie überprüfen, wie die Abfrage tatsächlich aussehen wird, wenn Sie sie erstellen.

578

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 drucken wie:

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

Wenn Sie versuchen, das Protokoll mit Illuminate ohne Laravel zu erhalten, verwenden Sie Folgendes:

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

Sie könnten auch eine schnelle Funktion wie die folgende:

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

EDIT

anscheinend ist in den aktualisierten Versionen die Abfrageprotokollierung standardmäßig deaktiviert (oben wird ein leeres Array zurückgegeben). Um es wieder einzuschalten, greifen Sie beim Initialisieren des Capsule Managers auf eine Instanz der Verbindung und rufen Sie die enableQueryLog-Methode auf

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

WIEDER BEARBEITEN

Wenn Sie die tatsächliche Frage in Betracht ziehen, können Sie die aktuelle Einzelabfrage anstelle der vorherigen Abfragen folgendermaßen konvertieren:

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

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

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

    $result = $builder->get();
41
Kakashi

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 den SQL-Abfrage-String zurückgibt. Hoffentlich hilfreich ...

34
CelinVeronicca
$data = User::toSql();
echo $data; //this will retrun select * from users. //here User is model
26
Kuldeep Mishra

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

Illuminate\Database\Eloquent\Builder

Illuminate\Database\Eloquent\Relations\HasMany

Illuminate\Database\Query\Builder

23

Erster Weg:

Sie können einfach mit den Methoden toSql()

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

echo $query->toSql();

Wenn es nicht funktioniert, können Sie das Ding aus laravel Dokumentation einrichten.

Zweiter Weg:

Ein anderer Weg ist es

DB::getQueryLog()

wenn es jedoch ein leeres Array zurückgibt, ist es standardmäßig deaktiviert besuchen Sie dieses ,

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

weitere Informationen finden Sie unter Github Issue , um mehr darüber zu erfahren.

Ich hoffe es hilft :)

10

Von Laravel 5.2 und weiter. Sie können DB::listen verwenden, um ausgeführte Abfragen abzurufen.

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

Wenn Sie eine einzelne Builder-Instanz debuggen möchten, können Sie die toSql-Methode verwenden.

DB::table('posts')->toSql(); 
8
Zayn Ali

verwenden Sie das Debugbar-Paket 

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

 enter image description here

5
潘庆强

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

DB::enableQueryLog();

$queries = DB::getQueryLog();
5
Jasim Juwel

Dies ist die Funktion, die ich in meine Basismodellklasse gestellt 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;
}
5
BoogieBug

Dies ist die weitaus beste Lösung, die ich jedem empfehlen kann, um eloquente letzte oder abschließende Abfragen zu debuggen, obwohl dies auch besprochen wurde:

// query builder
$query = DB::table('table_name')->where('id', 1);

// binding replaced
$sql = str_replace_array('?',$query->getBindings(), $query->toSql());

// print
dd($sql);
5
justnajm

Ein 'Makroable' Replacement, um die SQL-Abfrage mit den Bindungen abzurufen.

  1. Fügen Sie die Makrofunktion in derAppServiceProviderboot()Methode hinzu.

    \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 debuggen wie gewohnt. ( Laravel 5.4+ )

    Z.B. Abfrage Ersteller

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

    Z.B. Eloquent Builder

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

Anmerkung: Von Laravel 5.1 bis 5.3 kann Eloquent Builder nicht die Eigenschaft Macroable verwenden. Daher kann toRawSql kein Alias ​​zum Eloquent Builder hinzugefügt werden. Folgen Sie dem Beispiel unten, um dasselbe zu erreichen.

Z.B. Eloquent Builder ( Laravel 5.1 - 5.3 )

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

Für Laravel 5.5.X

Wenn Sie jede SQL-Abfrage erhalten möchten, die von Ihrer Anwendung ausgeführt wird, 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

4
scre_www

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

DB::enableQueryLog();

nach Abfragen mit der 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
  ]
]
4
Ravi Mane

Der einfachste Weg ist, absichtlichen Fehler zu machen . Ich möchte zum Beispiel die vollständige SQL-Abfrage der folgenden Beziehung anzeigen:

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

Um nur eine Spalte nicht gefunden zu bekommen, wähle ich hier created_at und änderte es in created_ats, indem ich folgende s hinzufügte:

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) ErrorException SQLSTATE [42S22]: Spalte nicht gefunden: 1054 unbekannt Spalte 'eqtype_jobs.created_ats' in 'Feldliste' (SQL:.. wählen .__ jobs *, eqtype_jobs.set_id als pivot_set_id, .__ eqtype_jobs.job_id als pivot_job_id, eqtype_jobs.created_ats.__ als pivot_created_ats, eqtype_jobs.updated_at as.. . .__ pivot_updated_at, eqtype_jobs.id als pivot_id von jobs inneren .__ verbinden eqtype_jobs auf jobs.id = eqtype_jobs.job_id wo .__ eqtype_jobs.set_id = 56 order by pivot_created_at desc Grenze 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 nun einfach die zusätzliche s von created_at und testen Sie diese SQL nach Belieben in einem beliebigen SQL-Editor wie dem SQL-Editor phpMyAdmin!

Beachten:

Die Lösung wurde mit Laravel 5.4 getestet.

3
SaidbakR

Wenn Sie nicht Laravel verwenden, sondern das Eloquent-Paket, 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);
2
Salman Ahmed

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

sie können Uhrwerk verwenden

Clockwork ist eine Chrome-Erweiterung für die Entwicklung von PHP, die Developer Tools um ein neues Panel erweitert, das alle Arten von Informationen enthält, die zum Debuggen und Profilieren Ihrer PHP -Anwendungen nützlich sind, einschließlich Informationen zu Anforderungen, Kopfzeilen, Abrufen und Bereitstellen von Daten. Cookies, Sitzungsdaten, Datenbankabfragen, Routen, Visualisierung der Anwendungslaufzeit und mehr.

funktioniert aber auch in Firefox

2
wdog

Sie können dieses Paket verwenden, um alle Abfragen abzurufen, die beim Laden Ihrer Seite ausgeführt werden

https://github.com/barryvdh/laravel-debugbar
2
Lucky Saini

So sehr ich diesen Rahmen liebe, ich hasse es, wenn er wie Mist wirkt.

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

Die einzige Lösung, die scheinbar beständig funktioniert, besteht darin, absichtlich einige Syntax- oder andere Fehler in die ORM-Parameter einzufügen, beispielsweise einen nicht vorhandenen Spalten-/Tabellennamen, den Code im Debug-Modus in der Befehlszeile auszuführen und den SQL-Fehler auszulösen mit der vollen frickin 'abfrage endlich. Andernfalls wird der Fehler hoffentlich in der Protokolldatei angezeigt, wenn er vom Webserver ausgeführt wurde.

1

Letzte Abfrage drucken

DB::enableQueryLog();

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

Hier ist die Lösung, die ich verwende: 

DB::listen(function ($sql, $bindings, $time) {
    $bound = preg_replace_callback("/\?/", function($matches) use ($bindings) {
        static $localBindings;
        if (!isset($localBindings)) {
            $localBindings = $bindings;
        }
        $val = array_shift($localBindings);

        switch (gettype($val)) {
            case "boolean":
                $val = ($val === TRUE) ? 1 : 0;  // mysql doesn't support BOOL data types, ints are widely used
                // $val = ($val === TRUE) ? "'t'" : "'f'";   // todo: use this line instead of the above for postgres and others
                break;

            case "NULL":
                $val = "NULL";
                break;

            case "string":
            case "object":
                $val = "'". addslashes($val). "'";   // correct escaping would depend on the RDBMS
                break;
        }
        return $val;
    }, $sql);
    array_map(function($x) { 
        (new \Illuminate\Support\Debug\Dumper)->dump($x); 
    }, [$sql, $bindings, $bound]);
});

Bitte lesen Sie die Kommentare im Code. Ich weiß, es ist nicht perfekt, aber für mein tägliches Debuggen ist es OK. Es wird versucht, die gebundene Abfrage mit mehr oder weniger Zuverlässigkeit zu erstellen. Vertrauen Sie dem jedoch nicht vollständig, die Datenbank-Engines entgehen den Werten anders, die diese kurze Funktion nicht implementiert. Also, nimm das Ergebnis sorgfältig.

0
Csongor Halmai

Benutzen:

$data = DB::select('select * from users where id = :id', ['id' => 1]);
print_r($data);

Ausgabe wird wie folgt aussehen:

Array ( [0] => stdClass Object ( [id] => 1 [name] => parisa [last] => naderi [username] => png [password] => 2132 [role] => 0 ) )
0
ParisaN

Wenn Sie basteln und die gebildete 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",
   }
>>>
0

Sie müssen der SQL-Ausgabe eine Bindung hinzufügen, damit sie lesbar ist. Sie können den folgenden Code verwenden, um unformatierte SQL-Abfragen zu drucken:

$users = User::where('status', 1);
$users_query = str_replace(array('?'), array('\'%s\''), $users->toSql());
$users_query = vsprintf($query, $users->getBindings());
dump($users_query);

$all_users = $users->get();
0
Dhananjay Kyada