如何设计代码没有重复捕捉错误在mvc框架


How to design code without repetitions to catch errors in mvc framework?

让我们假设有一个模型对保存对象执行一些逻辑。该逻辑由db事务、一些外部服务调用组成。

class ExampleModel {
  //some field
  //constructor and getters with setters
  public function save() {
    $db->beginTransaction();
    $db->somequery();
    $db->anotherone();
    $object->externalApiCall();
    $object->saveToCache();
  }

}

我的问题是捕获错误并进行回滚的最佳方法是什么?

解决方案# 1 捕获模型中的所有内容,在那里回滚,记录一些信息并将错误重新抛出到控制器。将看起来像这样:

class ExampleModel {
  //some field
  //constructor and getters with setters
  public function save() {
    try {
     $db->beginTransaction();
     $db->somequery();
     $db->anotherone();
     $object->externalApiCall();
     $object->saveToCache();
    } catch (DbException $e) {
      $db->rollback();
      $logger->log($e->getMessage());
      throw $e
    }
     catch (ApiExcetpion $e) {
       somelogic();
       throw $e;
     }
  }

}

我对这种方法的主要担忧是,在编写try/catch块时有很多冗余。对于每个复合方法都有一个try catch块。

# 2的解决方案在模型中抛出错误,在控制器中处理回滚/日志记录等。这个我不喜欢,因为它打破了MVC模式,控制器变胖了。

# 3

解决方案将错误监听器绑定到应用实例,这样它们就会根据自己的逻辑处理异常。例子:

class ExampleModel {
  //some field
  //constructor and getters with setters
  public function save() {
    $db->beginTransaction();
    $db->somequery();
    $db->anotherone();
    $object->externalApiCall();
    $object->saveToCache();
  }

}
$app->bind_error_handler("DbTransactionException", function () {
     rollback();
     log();
     return View::render("some error");
});
总的来说,我喜欢这种方法,因为没有大量的try/catch块。控制器是瘦的,错误逻辑与其他一切都是分离的。我对最后一种方法的关注是它是否被认为是最佳实践。这种方法是否灵活,是否会给我第一种方法的灵活性?整体问题:

在MVC世界中,处理错误(事务性和其他)的最佳实践是什么?从我提供的解决方案中哪一个是最好的?

使用ORM(如Doctrine),并让工作单元负责事务处理。

所有INSERT/UPDATE/DELETE操作都排队,直到您调用YOUR_ORM::flush。当出现异常时,事务将自动回滚。