假設有一個模型對保存對象執行一些邏輯。這個邏輯由數據庫事務,一些外部服務調用組成。如何設計無重複的代碼來捕獲mvc框架中的錯誤?
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世界中處理錯誤(事務和其他)的最佳做法是什麼?我所提供的解決方案是最好的解決方案?
謝謝回答,我有幾個問題。 1)發生DBtransaction錯誤時是否回滾?或者我可以指定在哪個異常回滾發生? 2)是否有可能綁定回滾到與db無關的其他操作的異常,就像我在我的例子中寫的那樣? 3)僅在使用DBAL時在Doctrine中處理?或者我需要ORM嗎? – RuslanN
使用教義,您可以定義事務邊界,並指定何時需要回滾或不回滾。你需要一個ORM來做到這一點。 – Federkun
葉,但後來就變成普通的BeginTransaction /提交/回滾循環,我的問題是有關錯誤處理 – RuslanN