2012-06-19 33 views
16

Tôi đang sử dụng PDO để viết lại giao diện trang web cho cơ sở dữ liệu. Tôi sử dụng để sử dụng phần mở rộng mysql, nhưng tôi chưa bao giờ làm phiền với xử lý lỗi, và một vài trình xử lý lỗi mà tôi đã có được về cơ bản là sao chép-dán.Câu hỏi ngoại lệ PDO - Cách bắt chúng

Bây giờ tôi muốn làm điều này đúng. Tuy nhiên, tôi đang gặp vấn đề bắt lỗi như thế nào tôi muốn (lỗi như "Duplicate Entry", "Null Value" vv trong MySQL). Bao nhiêu tuyên bố của tôi cần phải ở trong khối thử? Tất cả có nên ở trong đó không? Tôi đang sử dụng một Include() để kết nối với DB của tôi (trong đó có xử lý lỗi riêng của nó), do đó, nó chỉ thực hiện truy vấn có lỗi trong mã này. Tôi không thể tìm ra lý do tại sao nó không gặp lỗi khi thực thi mã sau:

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(); 
} 

Vì vậy, câu hỏi của tôi: CÓ TẤT CẢ CÓ phải trong khối thử không? Tôi có thể đặt lệnh thực hiện trong khối thử không? Nó sẽ bắt lỗi Duplicate value "John" in key "name", nhưng thay vào đó là thông báo thành công. (Khi cố gắng thêm hai người dùng "John"). Tôi đã kiểm tra trong PHPMyAdmin; chỉ mục này là duy nhất và có lỗi như mong đợi, không sử dụng mã này.

+3

Nếu bạn chưa có, bạn sẽ cần đặt 'PDO :: ATTR_ERRMODE' thành' PDO :: ERRMODE_EXCEPTION' để nó ném ngoại lệ về lỗi. – FtDRbwLXw6

+0

Bạn nên kiểm tra tài liệu hoặc mã nguồn và xem các hàm nào sẽ ném 'PDOException'. Sau đó, bạn sẽ biết những phần mã nào được đặt trong khối try :) –

+0

Tôi cảm thấy ngớ ngẩn .. thiết lập 'ATTR_ERRMODE' đã sửa nó. Vì vậy, bao nhiêu của các tuyên bố nên được trong khối thử? Mã này có thể được tái sử dụng (chỉ có thể một vài câu lệnh bindValue() sẽ thay đổi, sau đó thực thi). Có bất kỳ lợi ích nào để có toàn bộ câu lệnh trong khối thử hay chỉ là lệnh execute() cần thiết? – StuckAtWork

Trả lời

10

Bạn nên xem tài liệu. Nhưng nếu bạn không tìm thấy bất kỳ điều gì, bạn có thể thêm một cảnh cáo khác:

<?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(); 
} 
?> 

Điều này phải hoạt động vì tất cả ngoại lệ của các bổ sung PHP từ lớp PHP gốc ngoại lệ. (Kể từ 5.0 nếu bộ nhớ của tôi là tốt).

+1

Tôi đã xem xung quanh, nhưng tôi đoán tôi đã giả định rằng PDO đã ném ra các ngoại lệ theo mặc định. Hóa ra bạn cần phải làm như @drrcknlsn nói trong bình luận đầu tiên. Cả hai phiên bản ('Exception NOR PDOException') đều bị lỗi khi nó bị thay đổi. Tuy nhiên, đây không phải là một ý tưởng tồi (có thể có các lỗi khác xảy ra) – StuckAtWork

+1

@StuckAtWork: :: bindValue hoặc :: bindParam có thể thất bại nếu bạn gửi các đối tượng hoặc mảng. Đừng quên rằng việc sử dụng $ _POST trực tiếp sẽ không ngăn cản bạn tiêm XSS khi gửi mảng ở đây. (PS: Tôi chỉ viết bình luận đó ở đây chứ không phải ở trên vì một lý do không rõ, tôi không thể thêm bình luận vào bài viết yêu cầu của bạn? _?) Xin lỗi vì điều đó. – niconoe

+0

Tôi nên bọc $ _POST của mình như thế nào để mã hóa chính xác? – StuckAtWork

10

PDO Exception Câu hỏi - Làm thế nào để Catch Them

Như một quy luật -

DO NOT catch them.

Ví dụ, mã của bạn ở đây nên được viết theo cách này

$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']; 

mà không cần bất kỳ thử hoặc bắt cuộc gọi. Bởi vì bạn không có trường hợp cụ thể để xử lý một ngoại lệ ở đây (một tiếng vang đơn giản hiếm khi được tính là một kịch bản xử lý).

Thay vào đó, hãy để nó bong bóng lên đến trình xử lý lỗi của ứng dụng (đừng sợ bởi thuật ngữ này, PHP đã có sẵn một trình sẵn).

Tuy nhiên, tôi đang gặp sự cố khi bắt lỗi như thế nào (các lỗi như "Nhập trùng lặp", "Giá trị không chính xác" vv trong MySQL).

Chỉ trong trường hợp nếu bạn có một kịch bản nhất định, bạn phải sử dụng toán tử try-catch, nhưng bạn phải luôn kiểm tra, cho dù lỗi bạn đã có được một bạn mong đợi. Nếu không là một ngoại lệ phải được tái ném:

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; 
    } 
} 

và tất nhiên (vì nó bật ra được vấn đề Vere cho câu hỏi này), bạn phải thiết lập PDO trong chế độ ngoại lệ, hoặc trong một tham số constructor chỉ cần thêm mã

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

ngay sau khi kết nối.

+0

Tôi tin rằng '23000' là' getCode() 'sẽ trả về trong ví dụ cụ thể này, được điền vào' $ e-> errorInfo [0] 'hy vọng cho tất cả các trình điều khiển (thử nghiệm MySQL và MS SQL Server). Mã '1062' sẽ được điền trong' $ e-> errorInfo [1] 'cho MySQL và MS SQL Server điền vào' 2627' trong '$ e-> errorInfo [1]' –

Các vấn đề liên quan