Laravel 5에서 쿼리를 실행하는 방법? 빈 배열을 반환하는 DB :: getQueryLog ()


172

쿼리 로그를 보려고하지만 DB::getQueryLog()빈 배열을 반환합니다.

$user = User::find(5);
print_r(DB::getQueryLog());

결과

Array
(
)

이 쿼리에 대한 로그를 보려면 어떻게해야합니까?


Laravel Debugbar 는 쿼리를 기록하는 훌륭한 도구입니다. 또한 다른 많은 멋진 기능이 있습니다.
totymedli

답변:


256

기본적으로 쿼리 로그는 Laravel 5에서 비활성화되어 있습니다 : https://github.com/laravel/framework/commit/e0abfe5c49d225567cb4dfd56df9ef05cc297448

다음을 호출하여 쿼리 로그를 활성화해야합니다.

DB::enableQueryLog();

또는 이벤트 리스너를 등록하십시오.

DB::listen(
    function ($sql, $bindings, $time) {
        //  $sql - select * from `ncv_users` where `ncv_users`.`id` = ? limit 1
        //  $bindings - [5]
        //  $time(in milliseconds) - 0.38 
    }
);  

몇 가지 팁

1. 여러 DB 연결

DB 연결이 둘 이상인 경우 로깅 할 연결을 지정해야합니다

하려면에 대한 쿼리 로그를 할 수 있습니다 my_connection:

DB::connection('my_connection')->enableQueryLog();

쿼리 로그를 얻을하려면 my_connection:

print_r(
   DB::connection('my_connection')->getQueryLog()
);

2. 쿼리 로그를 어디에서 활성화합니까?

HTTP 요청 라이프 사이클 handle의 경우 일부 BeforeAnyDbQueryMiddleware 미들웨어 의 메소드 에서 쿼리 로그를 사용 가능하게 한 다음 terminate동일한 미들웨어 의 메소드 에서 실행 된 쿼리를 검색 할 수 있습니다 .

class BeforeAnyDbQueryMiddleware
{
    public function handle($request, Closure $next)
    {
        DB::enableQueryLog();
        return $next($request);
    }

    public function terminate($request, $response)
    {
        // Store or dump the log data...
        dd(
            DB::getQueryLog()
        );
    }
}

미들웨어 체인은 장인 명령에 대해 실행되지 않으므로 CLI 실행을 위해 artisan.start이벤트 리스너 에서 쿼리 로그를 활성화 할 수 있습니다 .

예를 들어 bootstrap/app.php파일에 넣을 수 있습니다

$app['events']->listen('artisan.start', function(){
    \DB::enableQueryLog();
});

3. 기억

Laravel은 모든 쿼리를 메모리에 유지합니다. 따라서 많은 수의 행을 삽입하거나 많은 쿼리로 오래 실행되는 작업과 같은 일부 경우에는 응용 프로그램이 초과 메모리를 사용할 수 있습니다.

대부분의 경우 디버깅을 위해서만 쿼리 로그가 필요하며,이 경우 개발 용으로 만 활성화하는 것이 좋습니다.

if (App::environment('local')) {
    // The environment is local
    DB::enableQueryLog();
}

참고 문헌


6
시스템에서 둘 이상의 db 연결을 사용하는 경우이를 지정해야합니다. 그렇지 않으면 빈 배열을 반환 할 수 있습니다.\DB::connection('myconnection')->enableQueryLog(); print_r(\DB::connection('myconnection')->getQueryLog());
Diana R.

답변을 @DianaR로 게시하십시오.
Narendrasingh Sisodia

1
Laravel 5.2의 경우 다음을 참조하십시오 : laravel.com/docs/5.2/database#listening-for-query-events
Dmitri Chebotarev

Eloquent "NameController :: create ();"를 기록하도록 설정하는 방법 성명서?
Rubén Ruíz

2
Laravel 5.4에서는 DB::listen콜백 함수의 서명이 다릅니다. : 그것은 더이처럼 DB::listen(function($query) { $sql = $query->sql; $bindings = $query->bindings; $time = $query->time; ... });
racl101

45

당신이 정말로 신경 쓰는 것은 빠른 디버깅 목적의 실제 쿼리 (마지막 실행)입니다.

DB::enableQueryLog();

# your laravel query builder goes here

$laQuery = DB::getQueryLog();

$lcWhatYouWant = $laQuery[0]['query']; # <-------

# optionally disable the query log:
DB::disableQueryLog();

바인딩을 포함하여 전체 쿼리를 얻으려면 print_r()on $laQuery[0]을 수행하십시오 . ( $lcWhatYouWant위 의 변수는 변수를로 대체합니다 ??)

기본 mysql 연결 이외의 것을 사용하는 경우 대신 다음을 사용해야합니다.

DB::connection("mysql2")->enableQueryLog();

DB::connection("mysql2")->getQueryLog();

( "mysql2"가있는 연결 이름으로)


1
이 코드는 어디로 갑니까? (5.4) 컨트롤러, 모델을 시도하고 미들웨어를 보았습니다 .DB 오류가 발생하기 전에 컨트롤러를 어디에서 실행할지 확실하지 않습니다.
blamb

실행을 중지하는 쿼리를 실행할 때 오류가 발생하면 오류가 무엇인지 알려줍니다. 오류가 해제 된 경우 / storage / log / laravel 또는 이와 유사한 오류 로그를 확인할 수 있습니다. (현재 컴퓨터에 있지 않습니다.) 내 대답에서 제안한 코드를 실행하는 동안 오류가 발생했다면 코드를 실행할 때마다 DB 파사드를 포함해야합니다. 무엇을하려고하는지 확실하지 않지만 컨트롤러는 언급 한 옵션 중 가장 정확한 것 같습니다. (보통 별도의 도우미 클래스에서 쿼리를 실행합니다)
Skeets

14

routes.php 파일에 이것을 넣으십시오 :

\Event::listen('Illuminate\Database\Events\QueryExecuted', function ($query) {
    echo'<pre>';
    var_dump($query->sql);
    var_dump($query->bindings);
    var_dump($query->time);
    echo'</pre>';
});

이 페이지의 소스 코드 msurguy에 의해 제출되었습니다 . 주석에서 laravel 5.2에 대한이 수정 코드를 찾을 수 있습니다.


조금 더럽지 만 $ query-> bindings 및 $ query-> time 힌트에 +1
Paolo Stefan

산뜻한! 이를 사용하면 쿼리가 발생하는 바로 그 뷰에 결과가 표시됩니다!
Charles Wood

14

먼저 쿼리 로깅을 활성화해야합니다

DB::enableQueryLog();

그런 다음 간단히 다음과 같이 쿼리 로그를 얻을 수 있습니다.

dd(DB::getQueryLog());

응용 프로그램이 시작되기 전에 쿼리 로깅을 활성화하면 BeforeMiddleware에서 수행 한 다음 AfterMiddleware에서 실행 된 쿼리를 검색 할 수 있습니다.


11

Laravel 5.2에서 클로저 DB::listen는 단일 매개 변수 만받습니다.

DB::listenLaravel 5.2에서 사용하려면 다음과 같은 작업을 수행해야합니다.

DB::listen(
    function ($sql) {
        // $sql is an object with the properties:
        //  sql: The query
        //  bindings: the sql query variables
        //  time: The execution time for the query
        //  connectionName: The name of the connection

        // To save the executed queries to file:
        // Process the sql and the bindings:
        foreach ($sql->bindings as $i => $binding) {
            if ($binding instanceof \DateTime) {
                $sql->bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
            } else {
                if (is_string($binding)) {
                    $sql->bindings[$i] = "'$binding'";
                }
            }
        }

        // Insert bindings into query
        $query = str_replace(array('%', '?'), array('%%', '%s'), $sql->sql);

        $query = vsprintf($query, $sql->bindings);

        // Save the query to file
        $logFile = fopen(
            storage_path('logs' . DIRECTORY_SEPARATOR . date('Y-m-d') . '_query.log'),
            'a+'
        );
        fwrite($logFile, date('Y-m-d H:i:s') . ': ' . $query . PHP_EOL);
        fclose($logFile);
    }
);



5

다음 toSql()get()같이 사용하십시오 :

$users = User::orderBy('name', 'asc')->toSql();
echo $users;
// Outputs the string:
'select * from `users` order by `name` asc'

2

(Laravel 5.2) 가장 간단한 방법은 하나의 코드 줄을 추가하여 SQL 쿼리를 모니터링하는 것입니다.

\DB::listen(function($sql) {var_dump($sql); });

1

Laravel 5.2로 명백히 계속해서 DB :: listen의 클로저는 단일 매개 변수 만받습니다. 위 응답 .이 코드를 미들웨어 스크립트에 넣고 경로에서 사용할 수 있습니다.

또한 :

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$log = new Logger('sql');
$log->pushHandler(new StreamHandler(storage_path().'/logs/sql-' . date('Y-m-d') . '.log', Logger::INFO));

// add records to the log
$log->addInfo($query, $data);

어떤 부분을 미들웨어에 배치해야합니까? 어느 노선에서?
user1016265

1

이 코드는 다음과 같습니다.

  • 라 라벨 5.2
  • 명령문을 mysql 데이터베이스에 기록하십시오.

다음은 @milz의 답변을 기반으로하는 코드입니다.

    DB::listen(function($sql) {
        $LOG_TABLE_NAME = 'log';
        foreach ($sql->bindings as $i => $binding) {
            if ($binding instanceof \DateTime) {
                $sql->bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
            } else {
                if (is_string($binding)) {
                    $sql->bindings[$i] = "'$binding'";
                }
            }
        }
        // Insert bindings into query
        $query = str_replace(array('%', '?'), array('%%', '%s'), $sql->sql);
        $query = vsprintf($query, $sql->bindings);
        if(stripos($query, 'insert into `'.$LOG_TABLE_NAME.'`')===false){
            $toLog = new LogModel();
            $toLog->uId = 100;
            $toLog->sql = $query;
            $toLog->save();
        }
    });

핵심은 sql 문을 데이터베이스 if(stripos...에 삽입하는 재귀를 방지 하는 줄 insert into log입니다.


0

나는이 기사에있는 대답을 생각한다 : https://arjunphp.com/laravel-5-5-log-eloquent-queries/

쿼리 로깅을 달성하기 위해 빠르고 간단합니다.

DB 쿼리를 수신 AppServiceProvider하려면 boot메소드에 콜백 을 추가하면 됩니다 .

namespace App\Providers;

use DB;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        DB::listen(function($query) {
            logger()->info($query->sql . print_r($query->bindings, true));
        });
    }
}

0

다음 명령문의 SQL 쿼리를 인쇄한다고 가정하십시오.

$user = User::find(5);

다음과 같이하면됩니다.

DB::enableQueryLog();//enable query logging

$user = User::find(5);

print_r(DB::getQueryLog());//print sql query

Laravel에서 마지막으로 실행 된 쿼리를 인쇄합니다.


-3

laravel 5 이상에서는 DB :: getQueryLog () 만 사용하면되지 않습니다. 기본적으로이 값은

 protected $loggingQueries = false;

로 변경

protected $loggingQueries = true; 

쿼리 로깅을 위해 아래 파일에.

/vendor/laravel/framework/src/illuminate/Database/Connection.php 

그런 다음 DB::getQueryLog()쿼리를 인쇄 할 위치를 사용할 수 있습니다 .


1
vendor파일 을 편집하는 것은 좋지 않습니다 . 그들은 독창적으로 유지되어야합니다.
shukshin.ivan

@ shukshin.ivan 그렇습니다. 벤더 파일을 편집 할 필요는 없지만 정확한 쿼리를 얻으려면이 코드를 시간 동안 편집 한 다음 다시 변경할 수 있습니다.
Rupali Pemare
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.