4

或任何有關此事的框架。MVC架構中何處記錄數據庫錯誤

使用Zend Framework 2作爲一個例子,我有以下表類:

<?php 

namespace Contact\Model; 

use Zend\Db\TableGateway\TableGateway; 
use Zend\Db\TableGateway\AbstractTableGateway; 
use Zend\Log\Logger; 

class UserContactsTable extends AbstractTableGateway 
{ 
    protected $tableGateway; 

    /** 
    * 
    * @var \Zend\Log\Logger Instance 
    */ 
    protected $logger; 

    public function __construct(TableGateway $tableGateway, Logger $logger) 
    { 
     $this->tableGateway = $tableGateway; 
     $this->logger  = $logger; 
    } 

    /** 
    * Save a contact 
    * 
    * @param \Sms\Model\UserContact $userContact 
    */ 
    public function saveUserContact(UserContact $userContact) 
    { 
     $data = array(
      'user_id'  => $userContact->user_id, 
      'contact_id' => $userContact->contact_id 
     ); 

     try { 
      $this->tableGateway->insert($data); 
     } catch (\Exception $e) { 
        //log 
      $this->logger->crit($omeErrMsg); 

     } 
    } 
} 
?> 

我應該記錄在這裏?我應該將記錄器綁定到表類嗎? 如果插入失敗,我應該讓saveUserContact函數拋出一個異常並捕獲控制器並在那裏登錄?

什麼是最佳實踐?

我最初的想法是創建一個包含一些常量錯誤消息的類,例如記錄器在表類中使用的插入和更新失敗,但我不確定這裏的正確過程是什麼。

這實際上並不僅限於PHP或Zend Framework 2,而恰恰是我正在使用的語言。

回答

5

我認爲系統的各個組件應儘可能分離。所以在這個例子中,如果saveUserContact發生故障,那麼它可能會導致拋出異常,因爲這不是預期的行爲。這個類不需要知道'進一步上游'會發生什麼,比如錯誤記錄。

正如你所提到的,最好拋出異常並將其捕獲到控制器(或者其他形式的監聽器)中,然後處理日誌記錄。

這種方法的好處是您的系統將更容易測試,因爲在構建要測試的UserContactsTable(模擬)對象時,存儲對象的存根會更少。

+0

我擔心這將是我的記錄器對象傳遞給我所有的表格,然後在那裏記錄而不是在控制器中的答案。該死的。感謝澄清。 –

+2

絕對同意@RobMasters。如果您使用經典的多層架構:Web MVC - 服務層 - 持久層,那麼您的數據庫持久層應與日誌邏輯解耦。正如RobMasters所建議的那樣,我會在控制器級別捕獲異常,然後將處理委派給根據異常類型的日誌服務,根據必要的邏輯記錄必要的信息(電子郵件,寫入文件,另一個專用數據庫......) – yechabbi

2

一般來說,我覺得你應該日誌失敗,他們發生(除非他們預期,在這種情況下,這是嘈雜),但傳播異常堆棧向上(或包裝除外),所以調用者可以決定是否忽略/重試/失敗(並記錄它自己的更多與業務邏輯相關的消息)。