2

假設有一個模型對保存對象執行一些邏輯。這個邏輯由數據庫事務,一些外部服務調用組成。如何設計無重複的代碼來捕獲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世界中處理錯誤(事務和其他)的最佳做法是什麼?我所提供的解決方案是最好的解決方案?

回答

0

使用ORM(像學說),並讓Unit Of Work打理事務處理的。

所有INSERT/UPDATE/DELETE操作將排隊,直到您調用YOUR_ORM::flush。發生異常時,事務會自動回滾。

+0

謝謝回答,我有幾個問題。 1)發生DBtransaction錯誤時是否回滾?或者我可以指定在哪個異常回滾發生? 2)是否有可能綁定回滾到與db無關的其他操作的異常,就像我在我的例子中寫的那樣? 3)僅在使用DBAL時在Doctrine中處理?或者我需要ORM嗎? – RuslanN

+0

使用教義,您可以定義事務邊界,並指定何時需要回滾或不回滾。你需要一個ORM來做到這一點。 – Federkun

+0

葉,但後來就變成普通的BeginTransaction /提交/回滾循環,我的問題是有關錯誤處理 – RuslanN

相關問題