本文介绍了PHP中的日志自定义异常的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义异常(可能会在其他自定义异常中进一步扩展)。我的项目需要记录发生的所有customException(及其所有下级)。我有一个可以记录customException(和其他任何东西)的记录器。这样做的方法之一是在处理异常时按如下方式显式记录异常。

I have a custom exception (which is further extended in may other custom exceptions). My project requires log all the customExceptions (and all of its decendents) that occurs. I have a logger that can log customException (and anything else). One of the way of doing so is explicitly log the exception whenever it is being handled as follows.

try{
    //some exception occur
}
catch(customeException $e)
{
     $log->logException($e);
     $e->showMessage(); // or do anything that we have to do with the error.
}

由于我们记录了所有customException,因此我可以想到另一种方式,更新customException构造函数并将异常记录在构造函数中。这样,可以确保记录所有customException。但是,如果我们走这条路,我的问题是:

Since we are logging all the customExceptions, the other way I can think of, updating the customException constructor and log the exception right there inside the constructor. In that way, it ensure that all the customException is logged. However, if we go down to this path, my questions is:


  1. 如何将记录器注入customException?

  2. 会违反SRP原则吗?

  3. 会在OOP意义上考虑不良做法还是最佳做法?


推荐答案

我认为将记录器注入CustomException是不正确的,因为(如您所指出的那样)它会破坏SRP并增加

I think that injecting logger into the CustomException is not right, cause (as you pointed) it breaks SRP and increase the complexity of your exceptions classes.

我建议您将Exception与ExceptionHandler分开。异常类应该只包含有关哪里(哪里出错)的信息。 ExceptionHandler负责记录异常(并根据需要执行其他一些工作)。

I'll suggest you to separate Exception from ExceptionHandler. Exception class should only contain information about "what (and where) went wrong". ExceptionHandler is responsible for logging exception (and doing some other work with exception if needed).

因此,您可以设置一个全局 ExceptionHandler (使用和或某些基于框架的异常处理机制,例如),它将捕获所有未处理的异常。

So you can setup one global ExceptionHandler (using set_exception_handler and set_error_handler or some framework-based exception handling mechanism like symfony's ExceptionListener), that will catch all unhandled exceptions.

<?php

class ExceptionHandler {
  /**
   * @var Logger
   */
  private $logger;

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

  public function handle(Throwable $e)
  {
    $this->logger->logException($e);
  }
}

在应用程序代码中,您仍然可以抛出并捕获异常。我认为有4种常见情况。

In application code you can still throw and catch exceptions. I think there are 4 common situations.

这是处理可恢复的异常的一般方法–在这种情况下,您根本不想失败,但是在发生此类异常时需要采取一些措施。

This is general way for handling recoverable exceptions – such situations when you don't want to fail at all, but you need to do something when such exception occurs.

<?php

try {
  $methodThatThrowsException();
}
catch (DoesNotMatterException $e) {
  // do some stuff and continue the execution
  // note, that this exception won't be logged
}



可记录的可恢复异常



Recoverable logged exception

The same as previous, but you want to log this exception.

<?php

try {
  $methodThatThrowsException();
}
catch (NonCriticalExceptionThatShouldBeLogged $e) {
  $this->exceptionHandler->handle($e); // log exception
  // do some stuff and continue the execution
}



finalizer不可恢复的异常



您要执行一些特定的业务逻辑然后失败。您可以捕获该异常,对其进行处理,然后再次将其引发。全局异常处理程序将处理此异常并将其记录。

Non-recoverable exceptions with "finalizer"

You want to execute some specific business logic and then fail. You can catch the exception, process it and then throw it again. Global exception handler will handle this exception and log it.

<?php

try {
  $methodThatThrowsException();
}
catch (CriticalException $e) {
  // do some stuff like cleanup/transaction rollback
  throw $e;
}



不可恢复的异常



如果只想记录异常并失败,则可以抛出该异常,全局异常处理程序将捕获并记录它。

Non-recoverable exceptions

If you want to just log the exception and fail, you can just throw this exception and global exception handler will catch and log it.

<?php

$methodThatThrowsException();

// ExceptionHandler::handle will be executed

这篇关于PHP中的日志自定义异常的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 09:55