답변:
마지막 쿼리가 실행 된 화면으로 출력하려면 다음을 사용할 수 있습니다.
DB::enableQueryLog(); // Enable query log
// Your Eloquent query executed by using get()
dd(DB::getQueryLog()); // Show results of log
가장 최근의 쿼리는 배열의 맨 아래에 있다고 생각합니다.
당신은 그런 것을 가질 것입니다 :
array(1) {
[0]=>
array(3) {
["query"]=>
string(21) "select * from "users""
["bindings"]=>
array(0) {
}
["time"]=>
string(4) "0.92"
}
}
( 아래 Joshua의 의견에 감사드립니다 .)
Log
클래스를 사용하여 응용 프로그램의 로그에 출력하는 것이 더 나을 수도 있습니다 . Log::debug(DB::getQueryLog())
DB::enableQueryLog();
DB::enableQueryLog(); dd(DB::getQueryLog());
그러나 그것은 단지 돌아온다 []
....
DB::connection('database')->getQueryLog()
인스턴스 에서 toSql()
메소드를 사용하십시오 QueryBuilder
.
DB::table('users')->toSql()
돌아올 것이다 :
`users`에서 *를 선택하십시오
이것은 이벤트 리스너를 연결하는 것보다 쉬우 며, 쿼리를 작성하는 동안 언제라도 쿼리가 실제로 어떻게 보이는지 확인할 수 있습니다.
getBindings
방법 을 사용할 수 있습니다 . 바인딩이 SQL 문에 바인딩되도록 바인딩을 반환합니다.
$query = \DB::table('users')->where('id', 10); $sql = str_replace_array('?', $query->getBindings(), $query->toSql()); dd($sql);
DB::QueryLog()
쿼리를 실행 한 후에 만 작동합니다 $builder->get()
. 쿼리를 실행하기 전에 쿼리를 얻으려면 $builder->toSql()
method 를 사용할 수 있습니다 . 다음은 SQL을 가져 와서 바인딩하는 방법의 예입니다.
$query = str_replace(array('?'), array('\'%s\''), $builder->toSql());
$query = vsprintf($query, $builder->getBindings());
dump($query);
$result = $builder->get();
또는 존재하지 않는 테이블이나 열을 호출하는 것과 같은 쿼리 오류를 만들면 예외 XD에서 생성 된 쿼리가 표시됩니다.
$query = vsprintf(str_replace(array('?'), array('\'%s\''), $builder->toSql()), $builder->getBindings());
LIKE
있거나 날짜 형식을 지정할 때이 기능은 작동하지 않습니다 . 이중 퍼센트 부호로 먼저 탈출해야합니다.
$builder->getBindings()
되었습니까?
'illuminate.query'이벤트를들을 수 있습니다. 조회 전에 다음 이벤트 리스너를 추가하십시오.
Event::listen('illuminate.query', function($query, $params, $time, $conn)
{
dd(array($query, $params, $time, $conn));
});
DB::table('users')->get();
다음과 같은 내용이 인쇄됩니다.
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;
Laravel을 사용하지 않고 Illuminate를 사용하여 로그를 얻으려고 시도하는 경우 :
\Illuminate\Database\Capsule\Manager::getQueryLog();
다음과 같이 빠른 기능을 사용할 수도 있습니다.
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;
}
편집하다
업데이트 된 버전은 기본적으로 쿼리 로깅을 사용하지 않는 것으로 보입니다 (위는 빈 배열을 반환 함). 다시 켜려면 Capsule Manager를 초기화 할 때 연결 인스턴스를 잡고 enableQueryLog
메소드를 호출하십시오.
$capsule::connection()->enableQueryLog();
다시 편집
실제 질문을 고려하면 실제로 모든 이전 쿼리 대신 현재 단일 쿼리를 변환하기 위해 다음을 수행 할 수 있습니다.
$sql = $query->toSql();
$bindings = $query->getBindings();
'US/Eastern'
.
quick function
입니다. 기본 코드는 준비 ( php.net/manual/en/mysqli.prepare.php ) 메소드를 사용한다고 믿기 때문에 이것이 ?
필요한 것입니다. php.net/manual/en/function.is-numeric.php 를 사용하여 입력을 작은 따옴표로 묶을 지 여부를 결정할 수 있습니다.
is_numeric
아이디어 를 포함하기 위해 위에서 편집 한 ) 작동합니다! 나는 이것을 좋아한다. 감사합니다.
$data = User::toSql();
echo $data; //this will retrun select * from users. //here User is model
->toSql()
모델 뒤에 더 많은 인수가있는 경우처럼 추가 할 수 있습니다 . 예 :User::where('id', 1)->toSql()
laravel 5.1 및 MySQL을 사용하는 경우이 기능을 사용할 수 있습니다.
/*
* 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;
}
입력 매개 변수로 다음 중 하나를 사용할 수 있습니다.
조명 \ 데이터베이스 \ Eloquent \ Builder
조명 \ 데이터베이스 \ Eloquent \ Relations \ HasMany
조명 \ 데이터베이스 \ 쿼리 \ 빌더
먼저 다음을 호출하여 쿼리 로그를 활성화해야합니다.
DB::enableQueryLog();
DB 파사드를 사용한 쿼리 후 다음과 같이 작성할 수 있습니다.
dd(DB::getQueryLog());
출력은 다음과 같습니다.
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
]
]
이것이 또한 논의되었지만 웅변적인 마지막 쿼리 또는 최종 쿼리를 디버깅하기 위해 어느 하나에게 제안 할 수있는 가장 좋은 솔루션입니다.
// 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);
단순히 toSql()
방법을 사용하여 다음 작업을 수행 할 수 있습니다 .
$query = DB::table('users')->get();
echo $query->toSql();
작동하지 않으면 laravel documentation 에서 설정할 수 있습니다 .
또 다른 방법은
DB::getQueryLog()
그러나 빈 배열을 반환하면 기본적으로 this을 방문 할 수 없습니다 .
그냥 사용 DB::enableQueryLog()
하면 작동합니다 :)
자세한 내용은 Github Issue 를 방문 하여 자세한 내용을 확인하십시오.
그것이 도움이되기를 바랍니다 :)
'macroable' 교체 바인딩과 함께 SQL 쿼리를 얻을 수 있습니다.
방법에 아래 매크로 기능을 추가하십시오 .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());
});
Eloquent Builder의 별명을 추가하십시오. (라 라벨 5.4+ )
\Illuminate\Database\Eloquent\Builder::macro('toRawSql', function(){
return ($this->getQuery()->toRawSql());
});
그런 다음 평소대로 디버그하십시오. (라 라벨 5.4+ )
예를 들어 쿼리 빌더
\Log::debug(\DB::table('users')->limit(1)->toRawSql())
예 : Eloquent Builder
\Log::debug(\App\User::limit(1)->toRawSql());
참고 : Laravel 5.1에서 5.3까지, Eloquent Builder는
Macroable
특성 을 사용하지 않으므로 EloquenttoRawSql
Builder에 즉시 별칭을 추가 할 수 없습니다 . 아래 예제를 따라 동일한 결과를 얻으십시오.
예 : Eloquent Builder ( Laravel 5.1-5.3 )
\Log::debug(\App\User::limit(1)->getQuery()->toRawSql());
라 라벨 5.2
부터. DB::listen
실행 된 쿼리를 얻는 데 사용할 수 있습니다 .
DB::listen(function ($query) {
// $query->sql
// $query->bindings
// $query->time
});
또는 단일 Builder
인스턴스 를 디버깅 하려면 toSql
method 를 사용할 수 있습니다 .
DB::table('posts')->toSql();
가장 쉬운 방법은 고의적 인 실수 를하는 것 입니다. 예를 들어 다음 관계에 대한 전체 SQL 쿼리를보고 싶습니다.
public function jobs()
{
return $this->belongsToMany(Job::class, 'eqtype_jobs')
->withPivot(['created_at','updated_at','id'])
->orderBy('pivot_created_at','desc');
}
열을 찾을 수 없도록 만들기 위해 여기에서 선택 created_at
하고 created_ats
후행 s
을 다음 과 같이 변경했습니다 .
public function jobs()
{
return $this->belongsToMany(Job::class, 'eqtype_jobs')
->withPivot(['created_ats','updated_at','id'])
->orderBy('pivot_created_at','desc');
}
따라서 디버거는 다음 오류를 반환합니다.
(4/4) ErrorException SQLSTATE [42S22]없는 칼럼 : "필드에서 '1054 알 열의 eqtype_jobs.created_ats'(SQL : 선택
jobs
*,.eqtype_jobs
.set_id
등pivot_set_id
,eqtype_jobs
.job_id
등pivot_job_id
,eqtype_jobs
.created_ats
등pivot_created_ats
,eqtype_jobs
.updated_at
등pivot_updated_at
,eqtype_jobs
.id
같이pivot_id
행jobs
내부 조인eqtype_jobs
onjobs
.id
=eqtype_jobs
.job_id
여기서eqtype_jobs
.set_id
= 56pivot_created_at
desc limit 20 offset 0으로 정렬) (보기 : /home/said/www/factory/resources/views/set/show.blade.php)
위의 오류 메시지는 실수로 전체 SQL 쿼리를 반환합니다.
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
이제 s
phpMyAdmin SQL 편집기와 같은 SQL 편집기에서와 같이 created_at 에서 여분의 것을 제거 하고이 SQL을 테스트하십시오!
주의:
이 솔루션은 Laravel 5.4 에서 테스트되었습니다 .
:id
쿼리 빌더 Laravel 5.8.15 기준으로 지금 가지고 dd
와 dump
방법 당신은 할 수 있습니다
DB::table('data')->where('a', 1)->dump();
제 생각에는 이것이 초보자로서 가장 좋은 방법입니다.
echo "<pre>";
print_r($query->toSql());
print_r($query->getBindings());
이것은 또한 여기에 묘사되어 있습니다. https://stackoverflow.com/a/59207557/9573341
라 라벨 5.5.X
애플리케이션에서 실행 한 각 SQL 쿼리를 수신하려면 listen 메소드를 사용할 수 있습니다. 이 방법은 쿼리 로깅 또는 디버깅에 유용합니다. 서비스 제공자에 쿼리 리스너를 등록 할 수 있습니다.
<?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()
{
//
}
}
Laravel을 사용하지 않고 Eloquent 패키지를 사용하는 경우 :
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);
일부 쿼리에서 SQL 및 바인딩을 가져 오는 간단한 함수를 만들었습니다.
/**
* 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;
}
용법:
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 ],
// ]
내가이 틀을 좋아하는 한, 나는 그것이 쓰레기처럼 행동 할 때 싫어한다.
DB::enableQueryLog()
완전히 쓸모가 없습니다. DB::listen
똑같이 쓸모가 없습니다. 내가 말했을 때 쿼리의 일부를 보여 주 $query->count()
었지만$query->get()
하면 말할 것도 없습니다.
일관되게 작동하는 유일한 해결책은 존재하지 않는 열 / 테이블 이름과 같이 ORM 매개 변수에 일부 구문 또는 기타 오류를 의도적으로 넣고 디버그 모드에서 명령 행에서 코드를 실행하면 SQL 오류가 발생하는 것입니다. 마지막으로 전체 frickin '쿼리와 함께. 그렇지 않으면 웹 서버에서 실행 된 경우 오류가 로그 파일에 나타납니다.
어설프게 사용하고 있고 SQL 쿼리를 기록하려면 다음을 수행하십시오.
$ 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",
}
>>>
로그보기에 따라이 작업을 수행하는 방법은 파일을 수정하기 만하면됩니다 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();