Dado el siguiente código:
DB::table('users')->get();
Quiero obtener la cadena de consulta SQL sin procesar que generará el generador de consultas de base de datos anterior. En este ejemplo, sería SELECT * FROM users
.
¿Cómo hago esto?
Dado el siguiente código:
DB::table('users')->get();
Quiero obtener la cadena de consulta SQL sin procesar que generará el generador de consultas de base de datos anterior. En este ejemplo, sería SELECT * FROM users
.
¿Cómo hago esto?
Respuestas:
Para enviar a la pantalla las últimas consultas ejecutadas, puede usar esto:
DB::enableQueryLog(); // Enable query log
// Your Eloquent query executed by using get()
dd(DB::getQueryLog()); // Show results of log
Creo que las consultas más recientes estarán en la parte inferior de la matriz.
Tendrás algo así:
array(1) {
[0]=>
array(3) {
["query"]=>
string(21) "select * from "users""
["bindings"]=>
array(0) {
}
["time"]=>
string(4) "0.92"
}
}
(Gracias al comentario de Joshua a continuación).
Log
Log::debug(DB::getQueryLog())
DB::enableQueryLog();
DB::enableQueryLog(); dd(DB::getQueryLog());
Pero regresa solo []
...
DB::connection('database')->getQueryLog()
Use el toSql()
método en una QueryBuilder
instancia.
DB::table('users')->toSql()
volvería:
seleccione * de `usuarios`
Esto es más fácil que conectar un detector de eventos, y también le permite verificar cómo se verá la consulta en cualquier momento mientras la construye.
getBindings
método. Esto devolverá los enlaces para que estén vinculados a la instrucción SQL.
$query = \DB::table('users')->where('id', 10); $sql = str_replace_array('?', $query->getBindings(), $query->toSql()); dd($sql);
DB::QueryLog()
solo funciona después de ejecutar la consulta $builder->get()
. si desea obtener la consulta antes de ejecutarla, puede usar el $builder->toSql()
método este es el ejemplo de cómo obtener el sql y vincularlo:
$query = str_replace(array('?'), array('\'%s\''), $builder->toSql());
$query = vsprintf($query, $builder->getBindings());
dump($query);
$result = $builder->get();
O simplemente cometa su error de consulta como llamar a una tabla o columna inexistente, verá la consulta generada en la excepción XD
$query = vsprintf(str_replace(array('?'), array('\'%s\''), $builder->toSql()), $builder->getBindings());
LIKE
consulta o al formatear fechas. Tendrás que escapar de esos primero con signos de doble porcentaje.
$builder->getBindings()
?
Puede escuchar el evento 'illuminate.query'. Antes de la consulta, agregue el siguiente detector de eventos:
Event::listen('illuminate.query', function($query, $params, $time, $conn)
{
dd(array($query, $params, $time, $conn));
});
DB::table('users')->get();
Esto imprimirá algo como:
array(4) {
[0]=>
string(21) "select * from "users""
[1]=>
array(0) {
}
[2]=>
string(4) "0.94"
[3]=>
string(6) "sqlite"
}
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Event;
hacerlo, simplemente puedes hacerlo use Event;
ya que es una fachada .
Si está intentando obtener el Log usando Illuminate sin usar Laravel:
\Illuminate\Database\Capsule\Manager::getQueryLog();
También podría crear una función rápida como esta:
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;
}
EDITAR
Las versiones actualizadas parecen tener el registro de consultas deshabilitado de forma predeterminada (lo anterior devuelve una matriz vacía). Para volver a encenderlo, al inicializar el Administrador de cápsulas, tome una instancia de la conexión y llame al enableQueryLog
método
$capsule::connection()->enableQueryLog();
EDITAR DE NUEVO
Teniendo en cuenta la pregunta real, en realidad podría hacer lo siguiente para convertir la consulta única actual en lugar de todas las consultas anteriores:
$sql = $query->toSql();
$bindings = $query->getBindings();
'US/Eastern'
.
quick function
. Creo que el código subyacente utilizará los métodos prepare ( php.net/manual/en/mysqli.prepare.php ), razón por la cual solo ?
se requiere. Puede php.net/manual/en/function.is-numeric.php para determinar si encapsular o no la entrada entre comillas simples.
is_numeric
idea), ¡y funciona! Me encanta esto. Gracias.
Hay un método en elocuente para obtener una cadena de consulta.
toSql ()
en nuestro caso,
DB::table('users')->toSql();
regreso
select * from users
es la solución exacta que devuelve la cadena de consulta SQL ... Espero que esto sea útil ...
->where('foo', '=', 'bar')
bar no se mostrará en el sql
$data = User::toSql();
echo $data; //this will retrun select * from users. //here User is model
->toSql()
como lo haría si hubiera más argumentos después del modelo. Por ejemploUser::where('id', 1)->toSql()
Si usa laravel 5.1 y MySQL puede usar esta función hecha por mí:
/*
* 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;
}
Como parámetro de entrada puede usar cualquiera de estos
Iluminar \ Base de datos \ Eloquente \ Constructor
Iluminar \ Base de datos \ Elocuente \ Relaciones \ HasMany
Iluminar \ Base de datos \ Consulta \ Constructor
Primero, deberá habilitar el registro de consultas llamando a:
DB::enableQueryLog();
Después de las consultas que utilizan la fachada DB, puede escribir:
dd(DB::getQueryLog());
la salida tendrá gusto abajo:
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
]
]
Esta es la mejor solución que puedo sugerir a cualquiera para depurar la última consulta o consulta final elocuente, aunque esto también se ha discutido:
// query builder
$query = DB::table('table_name')->where('id', 1);
// binding replaced
$sql = str_replace_array('?', $query->getBindings(), $query->toSql());
// for laravel 5.8^
$sql = Str::replaceArray('?', $query->getBindings(), $query->toSql());
// print
dd($sql);
Simplemente puedes hacer lo siguiente usando el toSql()
método,
$query = DB::table('users')->get();
echo $query->toSql();
Si no funciona, puede configurarlo desde la documentación de laravel .
Otra forma de hacerlo es
DB::getQueryLog()
pero si devuelve una matriz vacía, por defecto está deshabilitada, visite este ,
solo habilitar con DB::enableQueryLog()
y funcionará :)
Para más información, visita Github Issue para saber más al respecto.
Espero eso ayude :)
Un reemplazo 'macroable' para obtener la consulta SQL con los enlaces.
Agregue debajo la función macro en el método.AppServiceProvider
boot()
\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());
});
Agregue un alias para Eloquent Builder. ( Laravel 5.4+ )
\Illuminate\Database\Eloquent\Builder::macro('toRawSql', function(){
return ($this->getQuery()->toRawSql());
});
Luego depure como de costumbre. ( Laravel 5.4+ )
Por ejemplo, generador de consultas
\Log::debug(\DB::table('users')->limit(1)->toRawSql())
Ej. Eloquent Builder
\Log::debug(\App\User::limit(1)->toRawSql());
Nota: de Laravel 5.1 a 5.3, dado que Eloquent Builder no hace uso del
Macroable
rasgo, no puede agregartoRawSql
un alias al Eloquent Builder sobre la marcha. Siga el siguiente ejemplo para lograr lo mismo.
Por ejemplo, Eloquent Builder ( Laravel 5.1 - 5.3 )
\Log::debug(\App\User::limit(1)->getQuery()->toRawSql());
De laravel 5.2
y en adelante. puede usar DB::listen
para obtener consultas ejecutadas.
DB::listen(function ($query) {
// $query->sql
// $query->bindings
// $query->time
});
O si desea depurar una sola Builder
instancia, puede usar el toSql
método.
DB::table('posts')->toSql();
La forma más fácil es cometer un error deliberado . Por ejemplo, quiero ver la consulta SQL completa de la siguiente relación:
public function jobs()
{
return $this->belongsToMany(Job::class, 'eqtype_jobs')
->withPivot(['created_at','updated_at','id'])
->orderBy('pivot_created_at','desc');
}
Solo para hacer que una columna no se encuentre, aquí elijo created_at
y la cambié created_ats
agregando el final s
para que sea:
public function jobs()
{
return $this->belongsToMany(Job::class, 'eqtype_jobs')
->withPivot(['created_ats','updated_at','id'])
->orderBy('pivot_created_at','desc');
}
Entonces, el depurador devolverá el siguiente error:
(4/4) ErrorException SQLSTATE [42S22]: La columna no encontrado: 1054 Desconocido columna 'eqtype_jobs.created_ats' en 'lista de campos' (SQL: select
jobs
*,.eqtype_jobs
.set_id
Comopivot_set_id
,eqtype_jobs
.job_id
Comopivot_job_id
,eqtype_jobs
.created_ats
Comopivot_created_ats
,eqtype_jobs
.updated_at
Comopivot_updated_at
,eqtype_jobs
.id
Comopivot_id
dejobs
unión internaeqtype_jobs
enjobs
.id
=eqtype_jobs
.job_id
whereeqtype_jobs
.set_id
= 56 orden porpivot_created_at
límite límite 20 offset 0) (Ver: /home/said/www/factory/resources/views/set/show.blade.php)
El mensaje de error anterior devuelve la consulta SQL completa con el error
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
¡Ahora, simplemente elimine el extra s
de created_at y pruebe este SQL como desee en cualquier editor de SQL como phpMyAdmin SQL editor!
Aviso:
La solución ha sido probada con Laravel 5.4 .
:id
DB::enableQueryLog();
$queries = DB::getQueryLog();
A partir de Laravel 5.8.15, el generador de consultas ahora tiene dd
y dump
métodos para que pueda hacer
DB::table('data')->where('a', 1)->dump();
Esta es la función que puse en mi clase de modelo base. Simplemente pase el objeto generador de consultas y se devolverá la cadena SQL.
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;
}
En mi opinión, este será el mejor enfoque como principiante:
echo "<pre>";
print_r($query->toSql());
print_r($query->getBindings());
Esto también se representa aquí. https://stackoverflow.com/a/59207557/9573341
Para laravel 5.5.X
Si desea recibir cada consulta SQL ejecutada por su aplicación, puede usar el método de escucha. Este método es útil para registrar consultas o depurar. Puede registrar su escucha de consultas en un proveedor de servicios:
<?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()
{
//
}
}
Agregue esta función a su aplicación y simplemente llame.
function getQuery($sql){
$query = str_replace(array('?'), array('\'%s\''), $sql->toSql());
$query = vsprintf($query, $sql->getBindings());
return $query;
}
Salida : "seleccionar * desde user
donde lang
= 'en' y status
= '1' ordenar por updated_at
límite límite 25 desplazamiento 0"
Puede usar este paquete para obtener todas las consultas que se ejecutan cuando carga su página
https://github.com/barryvdh/laravel-debugbar
Imprimir última consulta
DB::enableQueryLog();
$query = DB::getQueryLog();
$lastQuery = end($query);
print_r($lastQuery);
Si no está usando Laravel pero está usando el paquete Eloquent, entonces:
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);
puedes usar un reloj
Clockwork es una extensión de Chrome para el desarrollo de PHP, que extiende las Herramientas para desarrolladores con un nuevo panel que proporciona todo tipo de información útil para depurar y perfilar sus aplicaciones PHP, incluida información sobre solicitudes, encabezados, obtener y publicar datos, cookies, datos de sesión, consultas de bases de datos, rutas, visualización del tiempo de ejecución de la aplicación y más.
pero funciona también en firefox
He creado algunas funciones simples para obtener el SQL y los enlaces de algunas consultas.
/**
* 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;
}
Uso:
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 ],
// ]
Por mucho que ame este marco, odio cuando actúa como una mierda.
DB::enableQueryLog()
Es totalmente inútil. DB::listen
Es igualmente inútil. Mostró parte de la consulta cuando dije $query->count()
, pero si lo hago $query->get()
, no tiene nada que decir.
La única solución que parece funcionar consistentemente es poner intencionalmente alguna sintaxis u otro error en los parámetros ORM, como un nombre de columna / tabla inexistente, ejecutar su código en la línea de comando mientras está en modo de depuración, y escupirá el error SQL con la maldita consulta completa finalmente. De lo contrario, es de esperar que el error aparezca en el archivo de registro si se ejecuta desde el servidor web.
Si está utilizando tinker y desea registrar la consulta SQL formada, puede hacer
$ 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: "admin@example.com",
created_at: "2019-01-11 19:06:23",
updated_at: "2019-01-11 19:06:23",
}
>>>
Prueba esto:
$results = DB::table('users')->toSql();
dd($results);
Nota: get () ha sido reemplazado por toSql () para mostrar la consulta SQL sin procesar.
Mi forma de hacerlo, basada en la vista de registro, solo necesita modificar el archivo app/Providers/AppServiceProvider.php
:
app/Providers/AppServiceProvider.php
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
DB::listen(function ($query) {
$querySql = str_replace(['?'], ['\'%s\''], $query->sql);
$queryRawSql = vsprintf($querySql, $query->bindings);
Log::debug('[SQL EXEC]', [
"raw sql" => $queryRawSql,
"time" => $query->time,
]
);
});
}
$users = DB::table('users')
->select(DB::raw('count(*) as user_count, username '))
->where('uid', '>=', 10)
->limit(100)
->groupBy('username')
->get()
;
dd($users);
storage/logs/laravel-2019-10-27.log
:[2019-10-27 17:39:17] local.DEBUG: [SQL EXEC] {"raw sql":"select count(*) as user_count, username from `users` where `uid` >= '10' group by `username` limit 100","time":304.21}
echo User::where('status', 1)->toSql();