[php] PDO 데이터베이스 쿼리를 디버깅하는 방법?

PDO로 이동하기 전에 문자열을 연결하여 PHP에서 SQL 쿼리를 작성했습니다. 데이터베이스 구문 오류가 발생하면 최종 SQL 쿼리 문자열을 에코하고 데이터베이스에서 직접 시도하여 오류를 수정할 때까지 조정 한 다음 코드에 다시 넣을 수 있습니다.

준비된 PDO 문은 더 빠르고 안전하며 안전하지만 한 가지가 나를 귀찮게합니다. 최종 쿼리가 데이터베이스로 전송되는 것을 보지 못했습니다. Apache 로그 또는 사용자 정의 로그 파일의 구문에 대한 오류가 발생하면 ( catch블록 내에 오류를 기록함 ) 오류 를 일으킨 쿼리를 볼 수 없습니다.

PDO가 데이터베이스로 보낸 전체 SQL 쿼리를 캡처하여 파일에 기록하는 방법이 있습니까?



답변

당신은 이것을 말합니다 :

데이터베이스로 전송되는 최종 쿼리를 보지 못했습니다.

실제로, 준비된 명령문을 사용할 때 final query ” 와 같은 것은 없습니다 .

  • 먼저, 성명서를 DB로 보내어 준비한다
    • 데이터베이스는 쿼리를 구문 분석하고 쿼리의 내부 표현을 작성합니다.
  • 그리고 변수를 바인드하고 명령문을 실행할 때 변수 만 데이터베이스로 전송됩니다.
    • 데이터베이스는 값을 명령문의 내부 표현에 “주입”합니다.

따라서 귀하의 질문에 대답하려면 :

PDO가 데이터베이스로 보낸 전체 SQL 쿼리를 캡처하여 파일에 기록하는 방법이 있습니까?

아니요 : ” 전체 SQL 쿼리 “가 어디에도 없으므로이를 캡처 할 방법이 없습니다.

디버깅 목적으로 수행 할 수있는 최선의 방법은 값을 명령문의 SQL 문자열에 삽입하여 “실제”SQL 쿼리를 “재구성”하는 것입니다.

이런 종류의 상황에서 내가 보통하는 일은 다음과 같습니다.

  • 자리 표시 자와 함께 명령문에 해당하는 SQL 코드를 에코합니다.
  • 매개 변수의 값을 표시하기 위해 직후에 var_dump (또는 이에 상응하는) 사용
  • 실행할 수있는 “실제”쿼리가없는 경우에도 일반적으로 가능한 오류를 볼 수 있습니다.

이것은 디버깅과 관련하여 훌륭하지는 않지만 준비된 명령문의 가격과 장점입니다.


답변

데이터베이스 로그를 보면

하지만 파스칼 마틴은 PDO 번에 모든 데이터베이스의 전체 쿼리를 전송하지 않습니다 정확한지, ryeguy DB를의 로깅 기능을 사용하기의 제안은 실제로 조립 및 데이터베이스에 의해 실행 나를는 전체 쿼리를 볼 수있었습니다.

방법은 다음과 같습니다 (이 지침은 Windows 컴퓨터의 MySQL에 대한 것입니다-마일리지는 다를 수 있음)

  • 에서는 my.ini의 아래 [mysqld]절의 경우, 추가 log등의 명령을log="C:\Program Files\MySQL\MySQL Server 5.1\data\mysql.log"
  • MySQL을 다시 시작하십시오.
  • 해당 파일의 모든 쿼리를 기록하기 시작합니다.

해당 파일은 빠르게 커지므로 테스트가 끝나면 파일을 삭제하고 로깅을 해제하십시오.


답변

물론이 모드를 사용하여 디버깅 할 수 {{ PDO::ATTR_ERRMODE }}
있습니다. 쿼리 앞에 새 줄을 추가하면 디버그 줄이 표시됩니다.

$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$db->query('SELECT *******');  


답변

아마도 원하는 것은 명령문 핸들에서 debugDumpParams () 를 사용하는 것입니다 . 준비된 쿼리에 값을 바인딩 한 후 언제라도이를 실행할 수 있습니다 ( execute()문이 필요 없음 ).

준비된 문장을 작성하지는 않지만 매개 변수를 표시합니다.


답변

오래된 게시물이지만 아마도 누군가 유용 할 것입니다.

function pdo_sql_debug($sql,$placeholders){
    foreach($placeholders as $k => $v){
        $sql = preg_replace('/:'.$k.'/',"'".$v."'",$sql);
    }
    return $sql;
}


답변

다음은 php.net의 “Mark”에 의해 주석에서 수정 된 효과적인 SQL이 무엇인지 확인하는 함수입니다 .

function sql_debug($sql_string, array $params = null) {
    if (!empty($params)) {
        $indexed = $params == array_values($params);
        foreach($params as $k=>$v) {
            if (is_object($v)) {
                if ($v instanceof \DateTime) $v = $v->format('Y-m-d H:i:s');
                else continue;
            }
            elseif (is_string($v)) $v="'$v'";
            elseif ($v === null) $v='NULL';
            elseif (is_array($v)) $v = implode(',', $v);

            if ($indexed) {
                $sql_string = preg_replace('/\?/', $v, $sql_string, 1);
            }
            else {
                if ($k[0] != ':') $k = ':'.$k; //add leading colon if it was left out
                $sql_string = str_replace($k,$v,$sql_string);
            }
        }
    }
    return $sql_string;
}


답변

아니요. PDO 쿼리는 클라이언트 쪽에서 준비되지 않았습니다. PDO는 단순히 SQL 쿼리 및 매개 변수를 데이터베이스 서버로 보냅니다. 데이터베이스 (의 대체를 무엇이다 ?‘들). 두 가지 옵션이 있습니다.

  • DB의 로깅 기능을 사용하십시오 (그러나 그럼에도 Postgres에서는 적어도 두 개의 별도 명령문 (예 : “최종이 아님”으로 표시됨))
  • SQL 쿼리와 매개 변수를 출력하고 직접 조각하십시오.