Comment faire pour que le constructeur de requêtes affiche sa requête SQL brute sous forme de chaîne de caractères?

avec le code suivant:

php prettyprint-override">DB::table('users')->get();

je veux obtenir la chaîne de requête SQL brute que le constructeur de requête ci-dessus générera, donc dans cet exemple ce serait SELECT * FROM users .

Comment faire?

316
demandé sur mega6382 2013-08-14 19:43:54

23 réponses

pour afficher à l'écran les dernières requêtes lancées vous pouvez utiliser ce

dd(DB::getQueryLog());

je crois que les requêtes les plus récentes seront au bas du tableau.

vous aurez quelque chose comme ça:

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

comme dans Joshua commentaire ci-dessous, Ceci est désactivé par défaut maintenant. Pour l'utiliser, vous devrez l'activer manuellement en utilisant:

DB::enableQueryLog();
377
répondu jfortunato 2017-05-23 11:55:03

utilisez la méthode toSql() sur une instance QueryBuilder .

DB::table('users')->toSql() serait de retour:

sélectionner * De `utilisateurs`

c'est plus facile que de brancher un écouteur d'événements, et vous permet également de vérifier à quoi ressemblera réellement la requête à n'importe quel moment pendant que vous la construisez.

525
répondu Steven Mercatante 2014-03-03 03:57:27

, Vous pouvez écouter le 'éclairer.requête de l'événement. Avant la requête ajouter l'écouteur d'événement suivant:

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

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

ceci imprimera quelque chose comme:

array(4) {
  [0]=>
  string(21) "select * from "users""
  [1]=>
  array(0) {
  }
  [2]=>
  string(4) "0.94"
  [3]=>
  string(6) "sqlite"
}
50
répondu Rubens Mariuzzo 2013-08-14 16:14:58

si vous essayez D'obtenir le journal en utilisant Illuminate sans Laravel utiliser:

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

vous pouvez également vous procurer une fonction rapide comme cela:

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

MODIFIER

les versions mises à jour semblent avoir désactivé la journalisation des requêtes par défaut (le tableau ci-dessus renvoie un tableau vide). Pour revenir, lors de l'initialisation du Gestionnaire de capsules, saisir une instance de la connexion et appeler le enableQueryLog méthode

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

ÉDITER À NOUVEAU

en prenant la question actuelle en considération, vous pourriez en fait faire ce qui suit pour convertir la requête simple actuelle au lieu de toutes les requêtes précédentes:

$sql = $query->toSql();
$bindings = $query->getBindings();
39
répondu Luke Snowden 2017-07-25 17:10:34

DB::QueryLog() ne fonctionne qu'après l'exécution de la requête $builder->get() . si vous voulez obtenir la requête avant d'exécuter la requête, vous pouvez utiliser la méthode $builder->toSql() . c'est l'exemple pour obtenir le sql et le lier:

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

    $result = $builder->get();
34
répondu Kakashi 2018-03-20 11:59:53

il y a une méthode dans eloquent pour obtenir la chaîne de requête.

toSql ()

dans notre cas,

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

retour

select * from users

est la solution exacte qui renvoie la chaîne de requête SQL..Espérons que cela est utile...

31
répondu CelinVeronicca 2016-04-13 11:05:41
$data = User::toSql();
echo $data; //this will retrun select * from users. //here User is model
22
répondu Kuldeep Mishra 2017-08-25 08:38:15

si vous utilisez laravel 5.1 et MySQL vous pouvez utiliser cette fonction faite par moi:

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

comme paramètre d'entrée vous pouvez utiliser l'un ou l'autre de ces

Éclairer\Database\Éloquent\Builder

Éclairer\Database\Éloquent\Relations\HasMany

Illuminate\Database\Query\Builder

20
répondu Yevgeniy Afanasyev 2017-07-25 23:45:31

Première manière:

simplement vous pouvez faire des choses suivantes en utilisant toSql() méthode,

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

echo $query->toSql();

si cela ne fonctionne pas, vous pouvez configurer la chose à partir de laravel documentation .

Deuxième manière:

une autre façon de le faire est

DB::getQueryLog()

mais s'il retourne un tableau vide alors par défaut il est désactivé visitez ce ,

il suffit d'activer avec DB::enableQueryLog() et ça marche :)

pour plus d'information visitez GitHub Issue pour en savoir plus.

Espère que cela aide :)

8
répondu Sagar Naliyapara 2017-04-25 05:45:00

de laravel 5.2 et plus. vous pouvez utiliser DB::listen pour obtenir des requêtes exécutées.

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

ou si vous voulez déboguer une seule instance Builder , vous pouvez utiliser la méthode toSql .

DB::table('posts')->toSql(); 
6
répondu Zayn Ali 2017-08-02 17:01:59

C'est la fonction, j'ai placé dans ma classe de modèle de base. Il suffit de passer l'objet query builder à l'intérieur et la chaîne SQL sera retournée.

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
répondu BoogieBug 2016-12-28 08:59:41

pour laravel 5.5.X

Si vous souhaitez recevoir chaque requête SQL exécutée par votre application, vous pouvez utiliser l'écouter méthode. Cette méthode est utile pour la journalisation des requêtes ou de débogage. Vous pouvez enregistrer votre écouteur de requêtes dans un fournisseur de services:

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

Source

4
répondu scre_www 2017-09-06 09:53:20

pour voir Laravel Exécuted Query utiliser laravel query log

DB::enableQueryLog();

$queries = DB::getQueryLog();
4
répondu Jasim Juwel 2017-11-21 05:37:49

vous devez d'abord activer le journal des requêtes en appelant:

DB::enableQueryLog();

après les requêtes utilisant la façade DB vous pouvez écrire:

dd(DB::getQueryLog());

la sortie sera comme ci-dessous:

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

Blockquote

4
répondu Ravi Mane 2018-08-31 04:29:41

compositeur besoin "barryvdh/laravel-debugbar": "2.3.* "

vous verrez enter image description here

3
répondu 潘庆强 2017-07-18 08:09:28

vous pouvez utiliser ce paquet pour obtenir toutes les requêtes qui s'exécutent lorsque vous téléchargez votre page ""

https://github.com/barryvdh/laravel-debugbar
2
répondu Lucky Saini 2015-07-14 14:01:26

si vous n'utilisez pas Laravel mais plutôt Eloquent package alors:

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
répondu Salman Ahmed 2015-11-24 09:29:02

vous pouvez utiliser clockwork

Clockwork est une extension de Chrome pour le développement de PHP, l'extension des outils de développement avec un nouveau panneau fournissant toutes sortes d'informations utiles pour le débogage et le profilage de vos applications PHP, y compris des informations sur la demande, en-têtes, obtenir et post données, cookies, données de session, requêtes de base de données, routes, visualisation de l'exécution de l'application et plus encore.

mais fonctionne aussi en firefox

2
répondu wdog 2015-12-11 16:39:03

j'ai créé quelques fonctions simples pour obtenir le SQL et les fixations à partir de certaines requêtes.

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

Utilisation:

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
répondu blablabla 2016-03-01 10:55:18

la façon la plus facile est de faire erreur délibérée . Par exemple, je veux voir la requête SQL complète de la relation suivante:

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

je juste pour faire une colonne à ne pas trouver, ici je choisis created_at et je l'ai changé en created_ats en ajoutant traînant s pour être:

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

ainsi, le débogueur retournera l'erreur suivante:

(4/4) ERROREXCEPTION SQLSTATE[42S22]: colonne introuvable: 1054 Unknown la colonne " eqtype_jobs.created_ats 'dans' field list' (SQL: select jobs .* , eqtype_jobs . set_id comme pivot_set_id , eqtype_jobs . job_id comme pivot_job_id , eqtype_jobs . created_ats comme pivot_created_ats , eqtype_jobs . updated_at comme pivot_updated_at , eqtype_jobs . id comme pivot_id à partir de jobs intérieure inscrivez eqtype_jobs sur jobs . id = eqtype_jobs . job_ideqtype_jobs . set_id = 56 ordre par pivot_created_at desc limite 20 offset 0) (voir: /home/dit/www/usine/resources/views/set/montrer.lame.php)

le message d'erreur ci-dessus renvoie la requête SQL complète avec l'erreur

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

maintenant, il suffit de supprimer le supplément s de created_at et tester ce SQL comme vous le souhaitez dans n'importe quel éditeur SQL tel que phpMyAdmin SQL editor!

Avis:

la solution a été testée avec Laravel 5.4.

1
répondu SaidbakR 2018-06-08 19:34:12

Voici la solution que j'utilise:

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

s'il vous Plaît, lisez les commentaires dans le code. Je sais, ce n'est pas parfait mais pour mon débogage quotidien, C'est OK. Il essaie de construire la requête liée avec plus ou moins de fiabilité. Cependant, ne lui faites pas entièrement confiance, les moteurs de base de données échappent aux valeurs différemment que cette fonction courte ne met pas en œuvre. Prenez donc le résultat avec soin.

0
répondu Csongor Halmai 2017-07-05 07:55:43

Imprimer la dernière requête

DB::enableQueryLog();

$query        = DB::getQueryLog();
$lastQuery    = end($query);
print_r($lastQuery);
0
répondu Sohomdeep Paul 2018-10-01 07:18:12

autant que j'aime ce cadre, je déteste quand il agit comme de la merde.

DB::enableQueryLog() est totalement inutile. DB::listen est tout aussi inutile. Il a montré une partie de la requête quand j'ai dit $query->count() , mais si je fais $query->get() , il n'a rien à dire.

la seule solution qui semble fonctionner de manière cohérente est de mettre intentionnellement une syntaxe ou une autre erreur dans les paramètres ORM, comme un nom de colonne/table inexistant, exécuter votre code sur le ligne de commande en mode de débogage, et il va cracher l'erreur SQL avec la requête complète frickin ' enfin. Sinon, il est à espérer que l'erreur apparaîtra dans le fichier log si elle est exécutée à partir du serveur web.

-1
répondu Spencer Williams 2018-06-14 22:17:26