0

我一直在努力實現沒有運氣在Laravel 5.3一些自定義的例外。Laravel自定義異常配置

我創建了一個擴展Exception類的AppException。這個想法是,我想附加一個用戶到我的例外,所以我知道誰絆倒它,並可以記錄它。

所以我建立了我的自定義異常這樣的:

class AppException extends Exception{ 

    protected $userId; 

    public function __construct($message = '', $userId=0) 
    { 
     parent::__construct($message); 
     $this->userId = $userId; 
    } 
} 

現在我想的是使用嘗試捕捉在我的控制器功能,然後捕獲異常,然後重新拋出的應用程序異常,所以我可以附加用戶。就像這樣:

try{ 
    << code here >> 
} 
catch(Exception $e){ 
    throw new AppException($e->getMessage, $request->user()->id); 
} 

我所發現的是,我無法獲得良好的跟蹤堆棧,因爲我從我的異常記錄行是從重新拋出的搭上了線,而不是從實際的異常。

什麼是設置此正確的方式?我試圖以一種可以利用Laravel附帶的Handler.php文件的方式來完成這項工作,而不必在每次嘗試中都加入日誌代碼。

謝謝!

回答

0

Exception類有一個previous的說法,您可以使用檢索以前所有的異常。

class AppException extends Exception 
{ 
    private $userId; 

    public function __construct($userId, $message = '', $code = 0, Exception $previous = null) 
    { 
     $this->userId = $userId; 

     parent::__construct($message, $code, $previous); 
    } 

    public static function fromUserId($userId, Exception $previous = null) 
    { 
     return new static($userId, sprintf('Exception thrown from `%s` userid', $userId), 0, $previous); 
    } 

    public function getUserId() 
    { 
     return $this->userId; 
    } 
} 

或者只是

class AppException extends Exception 
{ 
    public static function fromUserId($userId, Exception $previous = null) 
    { 
     return new static(sprintf('Exception thrown from `%s` userid', $userId), 0, $previous); 
    } 
} 

你抓住AppException後,您可以遍歷所有的例外是這樣的:

do { 
    printf("%s:%d %s (%d) [%s]\n", $e->getFile(), $e->getLine(), $e->getMessage(), $e->getCode(), get_class($e)); 
} while($e = $e->getPrevious()); 

例子:

try { 
    try{ 
     throw new RuntimeException('Something bad happened.'); 
    } 
    catch(Exception $e){ 
     throw AppException::fromUserId(123, $e); 
    } 
} catch(AppException $e) { 
    do { 
     printf("%s:%d %s (%d) [%s]\n", $e->getFile(), $e->getLine(), $e->getMessage(), $e->getCode(), get_class($e)); 
    } while($e = $e->getPrevious()); 
} 
0

嘗試實際的異常連接到拋出的異常,例如像這樣:

class AppException extends \Exception 
{ 
    /** 
    * @var int 
    */ 
    private $userId; 

    /** 
    * @param \Exception $exception 
    * @param int  $userId 
    * 
    * @return self 
    */ 
    public static function fromExceptionAndUserId(\Exception $exception, $userId) 
    { 
     $instance = new self(
      $exception->getMessage(), 
      0, 
      $exception 
     ); 

     $instance->userId = $userId; 

     return $instance; 
    } 

    /** 
    * @return null|int 
    */ 
    public function userId() 
    { 
     return $this->userId; 
    } 
} 

然後在你的控制器:

try { 
    // ... 
} catch (\Exception $exception) { 
    throw AppException::fromExceptionAndUserId(
     $exception, 
     $request->user()->id 
    ); 
} 

的想法是不僅要以實際的異常信息,但也要附上作爲$previous例外的實際例外。

使用命名構造函數爲您提供了可以控制如何構造異常消息AppException(同時附加用戶標識符)以及仍然能夠使用原始構造函數的優點。它使您可以自由地爲不同的用例添加更多命名的構造函數。

僅供參考,請參閱