Is sending error report from PHP Exception __destr

2019-05-11 10:48发布

问题:

I am designing an error handling system for my application. I want to base it on exceptions, and I want to get notified by email about every exception which I had not expected.

I thought of a class:

class My_Exception extends Exception {

    private $sendErrorReport = true;

    public function __destruct() {
        if ($this->sendErrorReport) {
              // send the error report by email
        }            
    }

    public function cancelErrorReport() {
        $this->sendErrorReport = false;
    }

} 

And I want to do something like this:

try { 
   do_something_that_can_throw_exception();
catch (My_Exception $e) {
   if ($e->getCode() == I_KNOW_WHAT_TO_DO ) {
        react_to_exception();
        $e->cancelErrorReport();   
   } else {
        show_error_message($e->getMessage());
   }
}

So, basically, when exception happens, and the system kows what to do, it does not bother me as a developer. But when there is something the system can't handle, then I am notified. I do not want to place the code that notifies me in the catch clause, cause I'm sure I WILL forget it somewhere...

Can I be sure that the exception __destuct method will be called?

Is the __destruct method of exception a good way to achieve this goal?

Is there a better way I could achieve that?

回答1:

No, it's not a good idea.

Your best option is to replace the unhandled exception handler. See set_exception_handler. If you catch an exception and then change your mind and want to leave the exception to the exception handler (like you do in your example, upon analyzing the error code), you can always re-throw the exception. Of course, a better option would be to subclass the exception instead of relying on the error code.



回答2:

Why don't you simply add a method to the Exception class to send an email when it's called? Something like:

class My_Exception extends Exception {

    private $sendErrorReport = true;

    public function __destruct() {
        if ($this->sendErrorReport) {
              // send the error report by email
        }            
    }

    public function cancelErrorReport() {
        $this->sendErrorReport = false;
    }

    public function sendEmail()
    {
        mail(....., $this->getMessage());
    }

} 

and then you do something like:

try { 
   do_something_that_can_throw_exception();
catch (My_Exception $e) {
   if ($e->getCode() == I_KNOW_WHAT_TO_DO ) {
        react_to_exception();
        $e->cancelErrorReport();   
   } else {
        $e->sendEmail();
   }
}