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
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 .
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
DB::enableQueryLog(); $queries = DB::getQueryLog();
compositeur a besoin de “barryvdh / laravel-debugbar”: “2.3. *”
tu verras
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
commepivot_set_id
,eqtype_jobs
.job_id
commepivot_job_id
,eqtype_jobs
.created_ats
aspivot_created_ats
,eqtype_jobs
.updated_at
commepivot_updated_at
,eqtype_jobs
.id
aspivot_id
desjobs
eqtype_jobs
joineqtype_jobs
sur lesjobs
.id
=eqtype_jobs
.job_id
oùeqtype_jobs
.set_id
= 56 order parpivot_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!
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.