#php #mysql #sql #pdo #error-handling
#php #mysql #sql #pdo #обработка ошибок
Вопрос:
Как вы знаете, транзакция состоит из нескольких подготовленных операторов, которые выполняются один за другим, если один из этих операторов завершается с ошибкой, он выдает исключение PDOException, вы можете перехватить его и получить сообщение об ошибке, но это сообщение об ошибке предназначено для «разработчика», мне нужно показать конкретную ошибкуконечному пользователю, например: «Транзакция завершилась неудачно, потому что ….», это «….» является причиной, по которой мне нужно показать клиенту.
У меня есть идея решить эту проблему, и она использует массив с именем 'query_trace'
, этот массив поместит ключ для выполняемого запроса и результат этого выполнения, например:
// prepare statement, bindParams....
$query_trace['query1_insert_user'] = "OK"
// prepare statement, bindParams....
$query_trace['query2_insert_user_more_information'] = "OK"
// prepare statement, bindParams....
$query_trace['query3_create_user_account'] = "FAILED"
(Эта НЕУДАЧНАЯ строка сохраняется в catch:
} catch (PDOException $e)
{ $query_trace['query3_create_user_account'] = "FAILED" }
return $query_trace; ...
Затем в контроллере, когда я получу ответ query_trace, я проверю:
if ($query_trace['query1_insert_user'] != "OK")
echo "The data for the user is not valid";
else
if ($query_trace['query2_insert_user_more_information'] != "OK")
echo "The additional information of the user is not valid";
else
if ($query_trace['query3_create_user_account'] != "OK")
echo "The username is not valid or actually exists";
else
echo "The transaction was great!";
Вопрос в том, что это хороший способ и / или PDO предлагает некоторые функции / методы для «автоматической трассировки» этого?
Спасибо.
Ответ №1:
Судя по сообщениям об ошибках, вам не нужны ни транзакция, ни несколько операторов.
Просто проверьте ввод пользователя перед выполнением каких-либо вставок, затем вставьте пользовательские данные в однопользовательский файл talbe без каких-либо транзакций.
Единственный возможный случай, о котором вы хотели бы сообщить пользователю, — это дублирующее имя пользователя. В этом конкретном случае вы можете перехватить ошибку, проверить, является ли это дубликатом ключа, и если да, то сообщить об этом пользователю. В противном случае просто повторно создайте исключение и позвольте обработчику ошибок на более широком сайте сообщить пользователю, что что-то пошло не так.
Комментарии:
1. На самом деле вы должны выполнять транзакцию, когда у вас есть строки для вставки в несколько таблиц: что, если MySQL отключится или исчезнет во время процесса? В итоге вы получите наполовину сохраненные данные, независимо от того, были ли они действительными.
2. Но вам не нужно несколько таблиц. Вам нужен только один. Не усложняйте вещи. Но в случае, когда вам действительно нужна транзакция, вам все равно не нужно специальное сообщение об ошибке для пользователя. Нет смысла говорить им, что половина их данных была обработана — это было бы вводящим в заблуждение и неправильным. Вместо этого просто отправьте им общую ошибку 500
3. Тем не менее, ваша таблица «дополнительная информация о пользователе», мягко говоря, своеобразна
4. это пример, показывающий, что я хочу сделать, я считаю, что транзакции необходимы, и я использую его. Я считаю, что решение — сначала проверить все, я не вижу другого пути.
Ответ №2:
Это не имеет особого смысла, поскольку транзакция превращает кучу запросов в один «атомарный» запрос. Поэтому попытка получить информацию о субатомных элементах довольно странная.
Поэтому я не знаю ни одного «простого способа» сделать это.
Вы также можете выполнять a SELECT
перед каждым оператором (но это может быть сложно, если SELECT
это оператор, который не удался). Вероятно PROCEDURE
, это тоже сработало бы.
SELECT "The user creation failed";
INSERT INTO user (...) VALUES (?,...,?);
SELECT "The user subinfos save failed";
INSERT INTO user_subinfos...;
Обратите внимание, что пользователь будет знать только, какой оператор не удался, а не почему он не удался.