2012-06-19 2 views
16

저는 PDO를 사용하여 데이터베이스의 웹 사이트 인터페이스를 다시 작성하고 있습니다. 이전에 mysql 확장을 사용 했었지만 오류 처리에 신경을 쓰지 않았고 기본적으로 복사 - 붙여 넣기가 가능한 오류 처리기는 거의 없었습니다.PDO 예외 질문 - 캐치 방법

이제이 작업을 수행하고 싶습니다. 그러나, 내가 원하는 오류 (예 : "중복 항목", "Null 값"등의 오류)을 잡는 데 문제가 있습니다. 내 진술 중 어느 정도가 try 블록에 있어야합니까? 그것 모두가 거기에 있어야합니까? Include()을 사용하여 (자체 오류 처리 기능이있는) 내 DB에 연결하므로이 코드에 오류가있는 쿼리 만 실행됩니다.

try { 
    $stmt = $db->prepare("INSERT INTO tbl_user (id, name, password, question, answer) VALUES (NULL, :name, :password, :question, :answer)"); 
    $stmt->bindValue(":name", $_POST['name']); 
    $stmt->bindValue(":password", $_POST['password']); 
    $stmt->bindValue(":question", $_POST['question']); 
    $stmt->bindValue(":answer", $_POST['answer']); 
    $stmt->execute(); 
    echo "Successfully added the new user " . $_POST['name']; 
} catch (PDOException $e) { 
    echo "The user could not be added.<br>".$e->getMessage(); 
} 

그래서 내 질문 :이이 모든이 try 블록에있을 않는 다음 코드를 실행할 때이 오류를 잡는하지 왜 나는 알아낼 수 없습니다? execute 블록을 try 블록에 넣을 수 있습니까? 오류 Duplicate value "John" in key "name"을 catch해야하지만 대신 성공 메시지가 표시됩니다. (두 명의 "John"사용자를 추가하려고 할 때). PHPMyAdmin을 체크인했습니다. 색인은 고유하며이 코드를 사용하지 않고 예상대로 오류를 던집니다.

+3

'$ db'의''PDO :: ATTR_ERRMODE''를'PDO :: ERRMODE_EXCEPTION'으로 설정하여 에러시 예외를 던질 필요가 있습니다. – FtDRbwLXw6

+0

문서 또는 소스 코드를 확인하고 어떤 함수가'PDOException'을 던지는지 확인해야합니다. 그럼 당신은 코드의 어떤 부분을 try 블록에 넣을 지 알게 될 것입니다. –

+0

'ATTR_ERRMODE'를 고치면 바보가됩니다. 그러면 명령문의 어느 부분이 try 블록에 있어야합니까? 코드가 재사용 될 수 있습니다 (단지 몇 개의 bindValue() 문이 변경되고 execute가 변경 될 수 있습니다). try 블록에 전체 문장을 사용하면 어떤 이점이 있습니까? 아니면 execute() 만 필요합니까? – StuckAtWork

답변

10

설명서를 참조하십시오. 당신은 아무것도 찾을 해달라고하면, 당신은 다른 캐치를 추가 할 수 있습니다

<?php 
try { 
    $stmt = $db->prepare("INSERT INTO tbl_user (id, name, password, question, answer) VALUES (NULL, :name, :password, :question, :answer)"); 
    $stmt->bindValue(":name", $_POST['name']); 
    $stmt->bindValue(":password", $_POST['password']); 
    $stmt->bindValue(":question", $_POST['question']); 
    $stmt->bindValue(":answer", $_POST['answer']); 
    $stmt->execute(); 
    echo "Successfully added the new user " . $_POST['name']; 
} catch (PDOException $e) { 
    echo "DataBase Error: The user could not be added.<br>".$e->getMessage(); 
} catch (Exception $e) { 
    echo "General Error: The user could not be added.<br>".$e->getMessage(); 
} 
?> 

이 일을해야하기 때문에 예외 네이티브 PHP 클래스 PHP 플러그인의 herits의 모든 예외. (내 기억이 잘되면 5.0 이후).

+1

나는 보았습니다 하지만 PDO가 기본적으로 예외를 던 졌다고 잘못 추측 한 것 같습니다. 당신은 @drrcknlsn이 첫 번째 코멘트에서 말했던 것처럼해야한다고 밝혀졌습니다. 어떤 버전 ('예외 NOR PDOException')도 변경 될 때까지 오류를 던지고있었습니다. 그러나 이것은 나쁜 생각이 아닙니다 (다른 오류가 발생할 수 있습니다) – StuckAtWork

+1

@StuckAtWork :: bindValue 또는 :: bindParam은 객체 또는 배열을 전송하면 실패 할 수 있습니다. $ _POST를 직접 사용한다고해서 배열을 보낼 때 XSS 주입을 막을 수 있다는 것을 잊지 마십시오. (추신 : 나는 단지 그 이유를 여기에 적었습니다. 이유는 알 수 없기 때문에, 당신의 질문 - 게시물에 코멘트를 추가 할 수 없기 때문입니까? _?) 죄송합니다. – niconoe

+0

$ _POST를 올바르게 인코딩하려면 어떻게해야합니까? – StuckAtWork

10

PDO 예외 질문 - 원칙적으로 그들에게

을 캐치하는 방법 -

DO NOT catch them.

는 예를 들어, 다음 코드는이 방법으로 어떤 시도 나 캐치 콜없이

$stmt = $db->prepare("INSERT INTO tbl_user (id, name, password, question, answer) VALUES (NULL, :name, :password, :question, :answer)"); 
$stmt->bindValue(":name", $_POST['name']); 
$stmt->bindValue(":password", $_POST['password']); 
$stmt->bindValue(":question", $_POST['question']); 
$stmt->bindValue(":answer", $_POST['answer']); 
$stmt->execute(); 
echo "Successfully added the new user " . $_POST['name']; 

작성해야합니다. 여기서 예외를 처리하는 특정 시나리오가 없기 때문에 (간단한 반향은 처리 시나리오로 간주되지 않음).

대신 응용 프로그램 전반의 오류 처리기로 버블 링하십시오 (PHP는 이미 내장되어 있습니다).

그러나 나는 ("중복 항목", "Null 값"과 같은 오류 (MySQL의 경우) 오류) 캐치 문제가 있습니다.

만 경우에 당신은 당신이 시도 - 캐치 연산자를 사용해야하는 특정 시나리오이있는 경우, 그러나 당신이있어 오류가 예상 하나입니다 여부를 항상 확인해야합니다. 그렇지 않으면 예외가 다시 발생 될 수 있습니다

try { 
    $pdo->prepare("INSERT INTO users VALUES (NULL,?,?,?,?)")->execute($data); 
} catch (PDOException $e) { 
    if ($e->getCode() == 1062) { 
     // Take some action if there is a key constraint violation, i.e. duplicate name 
    } else { 
     throw $e; 
    } 
} 

물론을합니다 (이 질문에 대한 비어의 문제 알고 보니), 당신도 생성자 매개 변수, 예외 모드에서 PDO를 설정해야 코드를 추가하면됩니다.

$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

연결 직후입니다.

+0

이 예제에서'getCode()'가 리턴하는'23000'은'$ e-> errorInfo [0]'에 모든 드라이버 (테스트 된 MySQL과 MS SQL 서버)에 들어 있기를 희망한다고 생각합니다. '1062' 코드는 MySQL의 경우'$ e-> errorInfo [1]'에 채워지고 MS SQL Server는'$ e-> errorInfo [1]'에'2627'을 채 웁니다 –