Comment puis-je obtenir le générateur de requête pour sortir sa requête SQL brute en tant que chaîne?

Vu le code suivant:

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

Je veux obtenir la chaîne de requête SQL brute que le générateur de requêtes ci-dessus va générer, donc dans cet exemple, il s’agira des SELECT * FROM users .

Comment puis-je faire cela?

Pour sortir à l’écran les dernières requêtes lancées, vous pouvez l’utiliser

 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"]=> ssortingng(21) "select * from "users"" ["bindings"]=> array(0) { } ["time"]=> ssortingng(4) "0.92" } } 

Selon le commentaire de Joshua ci-dessous, ceci est désactivé par défaut maintenant. Pour l’utiliser, vous devez l’activer manuellement en utilisant:

 DB::enableQueryLog(); 

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

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

sélectionnez * dans `users`

C’est plus facile que de câbler un écouteur d’événement et vous permet également de vérifier à quoi ressemblera la requête à tout moment pendant que vous la construisez.

Vous pouvez écouter l’événement ‘illuminate.query’. Avant la requête, ajoutez 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(); 

Cela va imprimer quelque chose comme:

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

Si vous essayez d’utiliser le journal avec Illuminate sans utiliser Laravel:

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

Vous pouvez également créer une fonction rapide comme celle-ci:

 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 une journalisation des requêtes désactivée par défaut (ce qui précède renvoie un tableau vide). Pour enableQueryLog , lors de l’initialisation du gestionnaire de capsules, récupérez une instance de la connexion et appelez la méthode enableQueryLog

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

MODIFIER ENCORE

En tenant compte de la question, vous pouvez effectuer les opérations suivantes pour convertir la requête unique actuelle au lieu de toutes les requêtes précédentes:

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

DB::QueryLog() ne fonctionne que lorsque vous exécutez la requête $builder->get() . Si vous voulez obtenir la requête avant d’exécuter la requête, vous pouvez utiliser la $builder->toSql() . Voici l’exemple de comment obtenir le SQL et le lier:

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

Il existe une méthode eloquent pour obtenir la chaîne de requête.

toSql ()

dans notre cas,

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

revenir

 select * from users 

est la solution exacte qui renvoie la chaîne de requête SQL.

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

Si vous utilisez laravel 5.1 et MySQL, vous pouvez utiliser cette fonction:

 /* * 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) === "ssortingng") { $replace = ' "'.addslashes($replace).'" '; } $sql = substr_replace($sql, $replace, $pos, strlen($needle)); } } return $sql; }; $sql = $replace($model->toSql(), $model->getBindings()); return $sql; } 

En tant que paramètre d’entrée, vous pouvez utiliser l’un ou l’autre de ces parameters.

Illuminer \ Database \ Eloquent \ Builder

Illuminer \ Base de données \ Eloquent \ Relations \ HasMany

Illuminer \ Database \ Query \ Builder

Premier moyen:

Simplement, vous pouvez faire les choses suivantes en utilisant la méthode toSql() ,

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

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

Deuxième voie:

Une autre façon de le faire est

DB::getQueryLog()

mais si elle retourne un tableau vide, par défaut, il est désactivé cette visite ,

il suffit d’activer avec DB::enableQueryLog() et cela fonctionnera 🙂

pour plus d’informations, visitez Github Issue pour en savoir plus.

J’espère que cela aide 🙂

De laravel 5.2 et suivants. 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 souhaitez déboguer une seule instance de toSql vous pouvez utiliser la méthode toSql .

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

C’est la fonction, j’ai placé dans ma classe de modèle de base. Transmettez simplement l’object de générateur de requêtes et la chaîne SQL sera renvoyé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; } 

Pour laravel 5.5.X

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

 sql // $query->bindings // $query->time }); } /** * Register the service provider. * * @return void */ public function register() { // } } 

La source

Pour voir Laravel Executed Query, utilisez le journal de requêtes laravel

 DB::enableQueryLog(); $queries = DB::getQueryLog(); 

compositeur a besoin de “barryvdh / laravel-debugbar”: “2.3. *”

tu verras entrer la description de l'image ici

Vous pouvez utiliser ce paquet pour obtenir toutes les requêtes en cours d’exécution lorsque vous chargez votre page

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

Si vous n’utilisez pas Laravel mais utilisez le package Eloquent 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('\'Ymd H:i:s\''); } else if (is_ssortingng($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); 

vous pouvez utiliser des rouages

Clockwork est une extension de Chrome pour le développement PHP, qui étend Developer Tools avec un nouveau panneau fournissant toutes sortes d’informations utiles pour déboguer et profiler vos applications PHP, notamment des informations sur les requêtes, les en-têtes, les routes, visualisation de l’exécution de l’application et plus encore.

mais fonctionne aussi dans firefox

J’ai créé des fonctions simples pour obtenir le SQL et les liaisons 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; } 

Usage:

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

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 "ssortingng": 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, ça va. Il tente de générer la requête liée avec plus ou moins de fiabilité. Cependant, ne vous y fiez pas complètement, les moteurs de firebase database échappent aux valeurs différemment que cette fonction courte n’implémente pas. Alors, prenez le résultat avec soin.

Le moyen le plus simple est de faire des erreurs délibérées . 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 viens de faire une colonne pour ne pas être trouvé, ici je choisis created_at et je l’ai changé en created_ats en ajoutant les s trailing 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 Colonne inconnue ‘eqtype_jobs.created_ats’ dans ‘liste des champs’ (SQL: jobs sélectionnés. *, eqtype_jobs . set_id comme pivot_set_id , eqtype_jobs . job_id comme pivot_job_id , eqtype_jobs . created_ats as pivot_created_ats , eqtype_jobs . updated_at comme pivot_updated_at , eqtype_jobs . id as pivot_id des jobs eqtype_jobs join eqtype_jobs sur les jobs . id = eqtype_jobs . job_ideqtype_jobs . set_id = 56 order par pivot_created_at desc limit 20 offset 0) /www/factory/resources/views/set/show.blade.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, supprimez simplement les éléments supplémentaires de created_at et testez ce code SQL comme vous le souhaitez dans n’importe quel éditeur SQL tel que phpMyAdmin SQL editor!

Remarquer:

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

Vous devez d’abord activer le journal des requêtes en appelant:

 DB::enableQueryLog(); 

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

 dd(DB::getQueryLog()); 

la sortie va aimer 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

Bien 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() , cela n’a rien à dire.

La seule solution qui semble fonctionner de manière cohérente consiste à placer intentionnellement une syntaxe ou une autre erreur dans les parameters ORM, comme un nom de colonne / table inexistant, à exécuter votre code sur la ligne de commande en mode débogage et à générer l’erreur SQL. avec la requête complète frickin ‘enfin. Sinon, j’espère que l’erreur apparaît dans le fichier journal si elle est exécutée à partir du serveur Web.