【问题标题】:try-catch inside or around the function & use try-catch on each query execution or not?函数内部或周围的 try-catch 并在每次查询执行时使用 try-catch?
【发布时间】:2016-01-25 18:08:48
【问题描述】:

我已经阅读了有关这些问题的几个关于 stackoverflow 的帖子:

  1. 我应该在“查询”函数内部还是周围使用 try-catch?
  2. 是否应该在每次查询执行时使用 try-catch?

而且,老实说,我不确定我是否理解答案——有人说是,有人说不是。所以,我想举一个实际的例子来说明我是怎么做的……如果你能给我这两个问题的答案。

数据库.php:

try {
    $connection= new PDO(DB_DNS, DB_USER, DB_PASS);
    $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(Exception $e) {
    echo "Error: ".$e->getMessage();
    die();
}

user.php:

class User {
    public function pronadjiSveUsere() {
        global $connection;
        $sql= $connection->prepare("SELECT * FROM users");
        $result = $sql->execute();
        return $result ;
    }

    public function find_by_id($id=0) {
        global $connection;
        $sql= $connection->prepare("SELECT * FROM users WHERE id = :id");
        $result = $sql->execute(array($id));
        return $result->fetch(PDO::FETCH_OBJ);   
    }
}

如您所见 - 类用户有两种方法。我的问题是:

1.在这些情况下我应该使用 try-catch 吗? 2. 如果答案是肯定的 - 我应该放在方法中吗,例如:

    public function find_by_id($id=0) {
        try {
            global $connection;
            $sql= $connection->prepare("SELECT * FROM users WHERE id = :id");
            $result = $sql->execute(array($id));
            return $result->fetch(PDO::FETCH_OBJ);
        } catch(Exception $e) {
            echo $e->getMessage();
            die();
        }
    }

或周围,每当我使用这些方法时,例如

try {
    user->find_by_id($id);
} catch(Exception $e) {
    echo $e->getMessage();
    die();
}

提前谢谢你!

【问题讨论】:

  • 我会将它们放在函数中,这样您就不必在调用方法时一次又一次地编写它。附言不要在我们有属性的类中使用global
  • 只是一个小点:PDO 生成一个 PDOException 现在,如果不在 catch (PDOException $e) 中处理,这将回退到标准异常,但有时您可能想要区分标准异常和 PDOException .所以最好捕获 PDOException。这也使您的代码更具自我记录性。
  • 考虑抛出异常或使用trigger_errorstackoverflow.com/questions/7063053/…
  • 在类中也使用global完全破坏封装,不推荐

标签: php function pdo try-catch execute


【解决方案1】:

如果您需要在每次查询失败并抛出异常时停止应用程序 - 尝试使用 php 函数 set_exception_handler 并删除代码中 PDO 的所有 try...catch 块。此函数为所有未捕获的异常注册全局处理程序。但 例如

<?php
    set_exception_handler(function ($e) {
        // Processing only PDOExceptions
        if ($e instanceof PDOException) {
            echo $e->getMessage();
            die();
        } else {
            throw $e;//do not process other exceptions
        }
    });
    ?>

您需要在任何 Sql 查询之前调用此函数。

【讨论】:

    【解决方案2】:

    你可以写关于那个主题的书。事实上,我相信有 本书是关于这个主题的。所以我会保持非常简短。
    对于你所有的代码 sn-ps 我会说不 - 最后一个有一个可能异常。
    第一个:database.php 不应该决定是否继续。因此,catch/die 块甚至可能被认为是邪恶的。特别是。当无条件打印“真实”错误信息时。一些上层可能想尝试另一个连接。或者打印更高级的“抱歉,出了点问题。我们正在尽最大努力带回 yaddayadda”消息。或者在没有数据库的情况下尽其所能。 (也许这是可能的。这不是如果 database.php 让 php 实例死掉)。
    您的班级用户的相同论点。除非用户内部的代码可以对异常进行处理(智能),否则它应该避免处理它。 [打印错误消息 + die 是处理异常]。
    同样,方法本身不太可能(尽管并非不可能)合理地缓解问题 - 所以,远离异常;无论如何,其他一些上层必须处理它。

    所以,只有在你可以真正处理它的情况下处理它。
    编辑:但有时将实际异常“转换”为上层感兴趣的东西是个好主意。然后你会有一个 catch 块,它不会真正处理异常,而是构建一个新异常(如果可能的话,包括原始异常)并抛出它。

    【讨论】:

    • 嗯,刚才我正在看一些 Lynda 教程,作者使用 try-catch around require_once('../includes/database.php'); 所以,就他而言,他的database.php 没有 try-catch,但每当他需要该文件时 - 他使用 try-catch... 因为,正如他所说(引用):当使用 pdo 连接到数据库时,您应该始终使用try catch... 而且,这对于受密码保护的数据库尤其重要,因为未捕获的 PDO 异常可能会暴露您的用户名和密码。
    • 如果没有其他顶级 catch 块(即 pdo 异常将运行到默认的未处理异常处理程序中),是的。但问题是:为什么没有其他异常处理程序?数据库连接以某种方式是应用程序配置层的一部分,该层应该以某种方式处理(或委托)“资源不可用”异常。
    • 谢谢你,Volker,我必须承认我仍然对此感到困惑,所以我在这里在 codereview 上创建了一个新线程:link - 如果你有时间更正该代码或告诉我如何你会吗?
    猜你喜欢
    • 2012-12-22
    • 1970-01-01
    • 2021-11-25
    • 1970-01-01
    • 1970-01-01
    • 2012-05-27
    • 1970-01-01
    • 2021-05-02
    • 2012-11-25
    相关资源
    最近更新 更多