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(同时附加用户标识符)以及仍然能够使用原始构造函数的优点。它使您可以自由地为不同的用例添加更多命名的构造函数。

仅供参考,请参阅