如何有效地处理业务逻辑错误?

时间:2012-11-27 14:43:47

标签: php error-handling business-logic

假设我们有一些通过组合构建的对象层次结构。是否有任何模式可以在内部对象中注册业务逻辑错误并将它们传递给上层对象?

我只是厌倦了每个级别的所有 addErrors getErrors ,我觉得我做错了。

我知道异常,但在这种情况下我不介意如何使用它们。业务逻辑错误在技术上不是关键情况,这应该导致程序执行中断。实际上根本就没有中断,因为我们需要注册错误并继续前进。

提前感谢分享您的智慧和知识)

用于说明问题的小片段:

class ErrorContainer {
    private $errors = array();
    function addError($error) { if (!is_array($error)) { $this->errors[] = $error;} else { $this->errors = array_merge($this->errors, $error); } }
    function getErrors() { return $this->errors[]; }
    function hasErrors() { return !empty($this->errors); }
}

class Processor extends ErrorContainer {
    function process($account_id, $orders) {
        $account = new Account();
        if (!$account->loadById($account_id)) { $this->addErrors($account->getErrors);}

        foreach ($orders as $order_id) {
            $order = new Order();
            if (!$order->loadById($order_id)) { $this->addErrors($order->getErrors);}
        }
    }

    return $this->hasErrors();
}

class Account extends ErrorContainer {
    function loadById($account_id) {
        $account = select_from_database($account_id);
        if (!$account) { $this->addError("Account is missing"); }
        if (!$account['active']) { $this->addError("Account is inactive"); }
        // and so on, some checks may add errors in a cycle

        return $this->hasErrors();
    }
}

class Order extends ErrorContainer {} // very similar to Account, but has its own checks

//Usage:

$errors = array();
$items = load_items_from_xml($xml);
foreach ($items as $item) {
    $processor = new Processor();
    if (!$processor->process($item['account_id'], $item['orders'])) {
        $errors = array_merge($errors, $processor->getErrors());
    }
}

1 个答案:

答案 0 :(得分:0)

异常不仅仅用于危急情况,但在您的情况下,使用您现在拥有的错误系统并不是一个坏主意。您可以考虑使用常量而不是文本来表示错误,并在每个类中定义所有可能的错误常量。

class Account extends ErrorContainer {
    const ERR_ACC_MISSING = 0;
    const ERR_ACC_INACTIVE = 1;
    function loadById($account_id) {
        $account = select_from_database($account_id);
        if (!$account) { $this->addError(ERR_ACC_MISSING); }
        if (!$account['active']) { $this->addError(ERR_ACC_INACTIVE); }
        // and so on, some checks may add errors in a cycle

        return $this->hasErrors();
    }
}