Вопросы об исключении PDO - как их поймать

Я использую PDO для перезаписи интерфейса веб-сайта для базы данных. Я использовал расширение mysql, но я никогда не беспокоился об обработке ошибок, и несколько обработчиков ошибок, которые у меня были, были в основном копированием.

Теперь я хотел бы сделать это правильно. Однако у меня возникают проблемы с поиском ошибок, как мне хотелось бы (такие ошибки, как "Duplicate Entry", "Null Value" и т.д. В MySQL). Сколько из моего заявления должно быть в блоке try? Должно ли все это быть там? Я использую Include() для подключения к моей БД (у которой есть своя обработка ошибок), так что это только выполнение запроса, в котором есть ошибки в этом коде. Я не могу понять, почему он не поймал ошибку при выполнении следующего кода:

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? Могу ли я просто поместить выполнение в блок try? Он должен поймать ошибку Duplicate value "John" in key "name", но вместо этого проходит сообщение об успешном завершении. (При попытке добавить двух пользователей "Джон" ). Я проверил в PHPMyAdmin; индекс уникален и делает ошибку, как ожидалось, просто не используя этот код.

Ответ 1

Вы должны посмотреть документацию. Но если вы ничего не найдете, вы можете добавить еще один улов:

<?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 класса Exception. (Начиная с 5.0, если моя память хорошо).

Ответ 2

Вопросы об исключении PDO - как их уловить

Как правило -

НЕ поймать их.

Например, ваш код здесь должен быть написан следующим образом

$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 уже имеет встроенный).

Однако у меня возникают проблемы с поиском ошибок, как мне хотелось бы (такие ошибки, как "Duplicate Entry", "Null Value" и т.д. в MySQL).

Только в случае, если у вас есть определенный сценарий, вам нужно использовать оператор try-catch, но вы всегда должны проверить, есть ли у вас ошибка, которую вы ожидали. В противном случае исключение должно быть повторно выбрано:

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

сразу после подключения.

Ответ 3

<?php
    $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']);
    $inserted = $stmt->execute();

    if($inserted)
        echo "Successfully added the new user " . $_POST['name'];
    else
        echo "Somethig get wrong";
?>