【问题标题】:How to handle PDO transaction errors to inform to the client the result of it?如何处理 PDO 事务错误以通知客户端它的结果?
【发布时间】:2017-02-07 08:42:22
【问题描述】:

如你所知,一个事务是由多个prepared statements组成的,一一执行,如果其中一个语句失败,它会抛出一个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"

(那个 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 提供了一些功能/方法来“自动跟踪”这个?

谢谢。

【问题讨论】:

    标签: php mysql sql pdo error-handling


    【解决方案1】:

    根据错误消息判断,您既不需要事务也不需要多个语句。

    只需在进行任何插入之前验证用户输入,然后将用户数据插入单个用户表,无需任何事务。

    您希望向用户报告的唯一可能情况是用户名重复。在这种特殊情况下,您可能想要捕获错误,检查它是否是重复键,如果是,则将该报告报告给用户。否则只需重新抛出异常并让站点范围内的错误处理程序告诉用户出现问题。

    【讨论】:

    • 当您在多个表中插入行时,您实际上应该执行一个事务:如果 MySQL 在此过程中关闭或消失怎么办?无论数据是否有效,您最终都会得到一半保存的数据。
    • 但是你不需要多个表。你只需要一个。不要把事情复杂化。但是,如果您确实需要交易,那么无论如何您都不需要为用户提供特殊的错误消息。告诉他们一半的数据已被处理是没有意义的——这将是误导和错误的。只需将一般 500 错误发送给他们
    • 不过,至少可以说,您的“更多用户信息”表是特殊的
    • 这是一个展示我想要做什么的例子,我相信交易是必要的,我正在使用它。我相信解决方案是首先验证,我没有看到其他方法。
    【解决方案2】:

    这没什么意义,因为事务将一堆请求变成了一个“原子”请求。因此,试图获取有关亚原子元素的信息非常奇怪。

    所以我不知道有任何“简单的方法”可以做到这一点。

    您也可以在每个语句之前执行SELECT(但如果SELECT 是失败的语句,则可能会变得很棘手)。它可能也适用于PROCEDURE

    SELECT "The user creation failed";
    INSERT INTO user (...) VALUES (?,...,?);
    SELECT "The user subinfos save failed";
    INSERT INTO user_subinfos...;
    

    请注意,用户只会知道哪个语句失败,而不知道失败的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-25
      • 2017-02-12
      • 2018-05-28
      • 1970-01-01
      • 2018-03-21
      • 1970-01-01
      相关资源
      最近更新 更多