我应该在自己的数据库类中使用PDO抛出异常吗?

时间:2015-08-20 23:03:40

标签: php mysql exception pdo

嘿,我有一个带有PDO的数据库类和一些面向对象论坛的其他类:

class Database {

    private $databaseConnection;

    function __construct($path = "", $dbUsername = "", $dbPassword = ""){
        $parts = explode('.',$path);
        $documentType = array_pop($parts);

        if(($path == "") || ((strcmp($documentType, "sq3") !== 0) && (strcmp($documentType, "sqlite") !== 0))) {
            throw new Exception("The Database must bee .sq3 or .sqlite and Path must be stated");
        }

        $this->databaseConnection = new PDO('sqlite:' . $path, $dbUsername, $dbPassword);
        $this->databaseConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->databaseConnection->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

        self::query('CREATE TABLE...)');
    }

    function query($sql, $params = NULL){
    ...
    }

    function getObjects($objectTable, $searchedForAttribute, $attributeValue){
    ...
    }


    function insertObject($object){
    ...
    }

    function updateObject($object){
    ...
    }

    function removeObject($object){
    ...
    }

    ...//some other methods

    function __destruct(){
        unset($this->databaseConnection);
    }
}

我应该使用例外吗?如:

    function insertObject($object){
    try {
       ...
    }catch(PDOException $e){
            throw new Exception($e->getMessage());
         }
    }

因此,我必须在其他地方捕获此异常并以不同的方式将其分发出去。例如:我有一个类用户和一个表用户。因此,如果填写了新的注册,我必须验证新用户的信息。因此,如果一个expactant User选择一个已经在数据库中的名称,我会抛出一个Exception,尽管我只需要一条消息给User,说明该名称已被分配。

所以我觉得如果我这样做会更好:

    function insertObject($object){
    try {
       ...
    }catch(PDOException $e){
            return "Username already assigned";
         }
    }

当然,我并不总是知道为什么会抛出异常,但在这种情况下,我会使用if-block验证数据。

那么在这种情况下我应该如何使用异常处理?

2 个答案:

答案 0 :(得分:2)

你的问题很简单,但同时又很庞大(恕我直言)。

首先,如果您想通过ORM /模型"进行简单的数据库抽象,我建议您使用Doctrine或其他现成的ORM软件包。或者是一个框架。

如果(像我一样)你是一个像这样从头开始做事的真正的傻瓜,那么我会从痛苦的先前经历中得到一些建议。

  1. 返回字符串(就像你在问题末尾所建议的那样)是一个真正糟糕的想法(TM)。字符串适用于串行的东西 - 没有定义从一段代码到另一段代码的响应。定义的常量(使用,比如说,整数值)对于这条路线更好 - 恕我直言。
  2. 例外在这里很有意义 - 你想说"我没有做你对我的要求,我需要你处理它"。
  3. 如果你选择沿着异常路线走下去(I'专业人员 - 最初来自C / C ++背景)使用字符串值作为字符串位(给出例外的人性化​​消息来显示)和也给它一个机器友好的属性(对于将捕获它的代码)。

    \PDOException自然而然地指出数据库失败刚刚发生,例如"我失去了连接"或者" MySQL borked"。您可能希望让这些异常自行回到调用您的代码......

    对于特定于模型的错误,我要创建适当的异常类。字面上:

    class UserModelException extends \Exception {
     ... // Optional stuff here
    }
    

    然后,您可以在调用代码中捕获不同的排序错误:

    try {
     ...
    } catch (\UserModelException $e) {
     ...
    } catch (\PDOException $e) {
     ...
    }
    

    当然,您可能希望捕获模型中的PDO异常,以确定某个类似于唯一键约束的内容是否爆炸 - 即指示用户名已存在。在这种情况下,您可能(在您的模型中)想要:

    try {
     ...
    } catch (\PDOException $e) {
       if (...) { // unique constraint error - username already taken
          throw new \UserModelException(...);
       } else {
          throw $e;
       }
    }
    

    这是否有意义,是否有任何帮助?

    我无法思考(在我的头脑中)我建议抛出文字\Exception对象的情况 - 我总是在每个上下文中继承它基础。

答案 1 :(得分:1)

  

我应该使用例外吗

肯定是的。这是唯一的方法。

  

如:

}catch(PDOException $e){
        throw new Exception($e->getMessage());
     }

进行这样的重新投掷绝对没有意义。为什么不单独留下PDOException?

  

我应该在自己的数据库类中使用PDO抛出异常吗?

是的,你应该。

  

那么在这种情况下我应该如何使用异常处理?

你必须先了解两件事。

  1. 例外不同。这是故意的。是的,您可以对运行时错误和用户验证使用异常。但这将是不同的例外,完全不同的处理
  2. 任何数据库处理类都不应验证用户数据。这是不同的课程。
  3. 对于运行时异常(如查询失败),所需的处理不多。编写一个常见的异常处理程序,它正在执行一些记录消息和显示借口页面的常见工作。当然不应该向用户显示真正的错误消息。只是一个普遍的借口。

    但是对于用户验证,请使用try..catch通过捕获您自己的UserValidationException 来查看是否所有数据都已经过验证。

    换句话说,程序员的例外情况和用户的例外情况。你必须以不同的方式对待它们。 A"数据库必须是.sq3或.sqlite和Path必须说明"一个程序员,不应该向用户显示。相反,它必须被记录以供程序员参考,必须向用户显示借口页面并且必须停止程序。

    A"用户名已经采取"是一个供用户使用,必须向他们展示。

    要区分这两种类型的例外,必须使用不同的异常类。

    这两种类型可能遇到的唯一情况是来自数据库的某些错误,可用于验证目的。在这种情况下,必须实现条件块,如另一个答案中所示。

    但是,异常可能不便于验证用户输入,因为您可能希望收集所有可能的错误,而不是一个。在这种情况下,不要使用异常进行数据验证,而是逐个运行验证并将错误添加到数组中。

相关问题