Comment faire pour que le constructeur de requêtes affiche sa requête SQL brute sous forme de chaîne de caractères?
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();
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.
, 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"
}
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();
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();
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...
$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 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
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 :)
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();
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;
}
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()
{
//
}
}
pour voir Laravel Exécuted Query utiliser laravel query log
DB::enableQueryLog();
$queries = DB::getQueryLog();
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
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
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);
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
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 ],
// ]
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
commepivot_set_id
,eqtype_jobs
.job_id
commepivot_job_id
,eqtype_jobs
.created_ats
commepivot_created_ats
,eqtype_jobs
.updated_at
commepivot_updated_at
,eqtype_jobs
.id
commepivot_id
à partir dejobs
intérieure inscrivezeqtype_jobs
surjobs
.id
=eqtype_jobs
.job_id
oùeqtype_jobs
.set_id
= 56 ordre parpivot_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.
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.
Imprimer la dernière requête
DB::enableQueryLog();
$query = DB::getQueryLog();
$lastQuery = end($query);
print_r($lastQuery);
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.