如果缺少数据库,则设计模式可以正常失败

时间:2012-03-05 16:52:24

标签: php oop design-patterns pdo

我正在开发一个应用程序,它使用数据库作为其功能的子集。在开发过程中,我们对数据库不可用的期望值高于正常值。一旦启动,即使存在数据库中断,我们仍然希望应用程序的主体能够正常工作。

我所有面向数据库的类都扩展了一个基类,它授予它们数据库访问权限,但是在具体的类中有一些直接执行selects的方法(意思是不通过基类方法)。

如果没有在if语句中包装每个数据库调用,如何在数据库不可用时优雅地降级功能?

修改

对此应用程序优先失败将显示“服务不可用”消息并阻止类尝试访问数据库(这将导致错误)。

3 个答案:

答案 0 :(得分:3)

恕我直言,这属于一般错误和异常处理的更广泛范围。

一些介绍...

数据库本质上是代码中的全局变量输入。如果它不可用,这就是意外的“特殊”条件的定义; 应该导致异常。当然,你明确地询问了如何处理这种情况“不能在if语句中包装每个数据库调用。”try/catch块中包装每个数据库操作基本上与包装相同if语句中的每个操作。

此外,mysql_connect函数除了在无法连接时返回FALSE之外还会引发PHP错误。你应该真的使用PDO而不是mysql恐龙,但这完全是另一个话题。希望您没有使用错误抑制运算符@或不报告E_WARNING错误来避免这种情况。

那么如何处理......

就个人而言,我与PHP中的错误处理无关。您应该使用set_error_handlerdocs定义一个自定义错误处理程序函数,它会在任何PHP错误上抛出异常并且处理异常而不是错误

当您以这种方式设置错误处理策略时,可以轻松地包装任何可能导致问题或意外抛出try块并处理catch块中的意外事件的功能。

既然你说过,“所有[你的]面向数据库的类扩展了一个基类,授予他们数据库访问权限,”我建议在基类中添加一个简单的布尔属性来表示作为数据库连接是否失败的标志。然后,在每次尝试查询数据库之前,只检查标志的值。如果你正确地在类中传递数据库实例(而不是破坏引用),那么他们在需要时都可以访问相同的属性。

如果数据库连接失败,您只需在try块中设置假设的$dbConn->connError = TRUE;标志。

因此,总而言之,虽然如何构建实际代码的具体细节取决于您正在做什么,但使用异常来处理错误条件是恕我直言,这是最有效的方法。

答案 1 :(得分:1)

AOP有可能吗?这可以允许您编写代码来拦截连接到数据库的代码的任何部分,并插入您的错误处理代码。

http://code.google.com/p/php-aop/

答案 2 :(得分:0)

我认为在项目中改造我的解决方案并不容易,但我这样做:

当我希望在我的应用程序中失败被识别为关键时,我使用了例外。在我的错误处理程序中,我有一些逻辑可以确定异常是否与像4xx这样的http状态代码匹配,如果不是生成通用500状态代码的话。

使用自定义结果类的破坏性较小的机制捕获非严重故障。它的基本结构类似于Exception,因为codemessage作为构造函数参数传递。此外,result-object可以作为可选参数传递。

Result-class如下所示:

class Result
{
    /**
     * @var int
     */
    protected $resultCode;

    /**
     * @var string
     */
    protected $resultMessage;

    /**
     * @var mixed
     */
    protected $resultObject;

    /**
     * Inject object values on construction.
     *
     * @param int $code
     * @param string $message
     * @param mixed $result
     */
    public function __construct($code = 0, $message = null, $result = null)
    {
        $this->resultCode = intval($code);
        $this->resultMessage = (string) $message;
        $this->resultObject = $result;
    }

    /**
     * Returns true when result is considered a success, determined by the
     * resultCode, otherwise false.
     *
     * @return bool
     */
    public function isSuccess()
    {
        if ($this->resultCode > 0) {
            return true;
        }
        return false;
    }


    /**
     * Returns true when result is considered an error, determined by the
     * resultCode, otherwise false.
     *
     * @return bool
     */
    public function isError()
    {
        if ($this->resultCode < 1) {
            return true;
        }
        return false;
    }

    /**
     * Returns the result message.
     *
     * @return string
     */
    public function getMessage()
    {
        return $this->resultMessage;
    }

    /**
     * Returns the actual result object.
     *
     * @return mixed
     */
    public function getResult()
    {
        return $this->resultObject;
    }
}

只需要结果代码。如果代码是&gt;则认为结果是成功的。 0,否则被认为是错误。结果对象可以是实际结果(如果成功),例如来自查询的行或行集或(如果错误)输入或输入的部分,它们是相关的,例如,你正在寻找的行ID。

由于此结果类不会触发errorHandler,因此可信任MVC应用程序来处理错误。通过抛出异常,或通过显示消息或作为结果对象传递的任何内容优雅地对失败结果作出反应。

如果我将此结果传递给我的观点,我可以回答$result->isSuccess()是真还是假,只是通过$result->getResult()得到实际结果,或者通过$result->getMessage()显示错误消息。