使用PDO对象的库

时间:2013-12-23 12:01:11

标签: php pdo

我正在编写一个需要数据库连接的库,因此它要求用户将PDO对象作为构造函数的参数传递。

但正如你们许多人所知,PDO有3种不同的错误报告机制:静默模式,警告模式和异常模式(http://www.php.net/manual/en/pdo.error-handling.php)。

问题是每种模式都需要不同类型的错误处理代码。接受我不能强迫用户使用我的首选模式,我认为我的选择是:

  1. 在输入的PDO对象上设置我的首选模式,并且不用担心
  2. 克隆输入的PDO对象,然后设置我的首选模式
  3. 为所有3种模式编写错误处理代码,然后在PDO :: getAttribute()方法的帮助下检测并使用适当的模式
  4. 在每次方法调用之前设置我的首选模式,然后在每次方法调用之后将其撤消
  5. 因此1可以破坏用户的代码,2看起来像不必要的重复,3非常尴尬,4不是那么尴尬但仍然很尴尬,仍然容易破坏用户的代码。

    所以我要求那里的图书馆作家,你怎么处理这个?

1 个答案:

答案 0 :(得分:1)

好的,不确定这是否是适合此类问题的网站,但首先,让我向您简要介绍一下您的选项,并告诉您哪些 IMO 更好选项。然后我会在将来的编辑中解释所有这些。

  1. 这不是前进的方向。用户正在用户的背后传递一个实例,然后将其更改。 不要改变不属于你的
  2. 不要克隆数据库连接。只是不要
  3. 库不应该处理用户代码导致的错误。这是用户的问题/错误,他们也应该处理它。 lib无法预测每一种可能的滥用行为
  4. 不,真的......这只是一种无声的方式,可以做你在第1点所做的事情:改变你从未真正拥有的对象。
  5. 那么,我该怎么办?简单:为数据库连接提供一个API,它本身可以有一个PDO实例,但至少用户有一个明确的API,并且知道可能的错误的结果是什么(例如{{1} } + PDO =>您的API将始终抛出异常


    现在,为什么你的第一个选择不是一个可行的方法? (再次:这是我的意见
    假设我要使用你的代码,并且有类似的东西:

    setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)

    现在,如果您将PDO设置为抛出异常,我就不会抓住任何异常。我的代码没有以处理//code $this->db = new PDO($dsn, $usr, $pass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT)); $this->dependency = new Your\Lib\Stuff($this->db); //code $this->db->query('bad query'); 实例的方式写入,因此它会导致整个应用程序停止运行。更重要的是,当发生这种情况时,谁会说我不会在调试时添加此行:

    PDOException

    这不是一条安全的道路,所以不要这样做。


    下一步:克隆$this->dependency = new Your\Lib\Stuff($this->db); $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);//override your setting 只是行不通。如果你有一个愚蠢的人写自己的课程从PDO扩展,这是可能的:

    PDO

    在这种情况下,class BadIdea extends PDO { public function __clone() {//disable clone return false; } } 仍将作为$db = new BadIdea()的实例传递(测试PDO,然后调用function foo(PDO $arg){echo 'argument is instance of PDO';}工作) 。现在你无法克隆,你的lib就失败了。


    lib或框架应该写得足够通用,以便重用它。如果您正在编写代码,在考虑特定用例时,您可能会发现每次要再次使用它时都要编辑代码。
    除非您打算创建自己的lib(在这种情况下,用户无论如何都不必传递自制的DB连接),错误处理不应该是您的lib的任务。

    您的代码应该在发生意外的事件时抛出异常。您不能期望编写处理所有这些情况的代码:

    foo(new BadIdea)

    或者更糟:

    $yourInstance->pass('Invalid query');
    $yourInstance->select('INSERT ...');//valid query, wrong method
    $your instance->query(array('invalid', 'argument'));
    

    当您处理lib内部的错误时,您的用户将如何处理这些情况?事务是用户做出的一个有意识的决定,在事务期间可能发生的任何异常,无论是查询中的错误还是第三方方法抛出的异常都可能导致事务不得不回滚。
    您的lib范围不够广泛,无法了解用户代码中引发的异常。