Как обрабатывать ошибки транзакции PDO, чтобы сообщить клиенту результат этого?

#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...;
  

Обратите внимание, что пользователь будет знать только, какой оператор не удался, а не почему он не удался.