1

I've been searching for an existing question that already asks this, but I wasn't able to find any questions that quite ask what I'm trying to figure out. The most similar question I could find was this: php 5.3 avoid try/catch duplication nested within foreach loop (code sandwich)

Okay so the place I work at has a web application with a PHP back end. We use an MVC type structure. I'm writing a controller that has multiple methods and in each of my methods I'm wrapping my code with identical try / catch code. In the catch, I pass the exception, a reference to the class, and a reference to the function to a method that builds an error message so that the error messages are formatted the same across the application. It looks something this:

class MyController {

    public function methodA() {
        try {
            // code for methodA
        } catch(Exception $e) {
            $errorMessage = Tasks::buildErrorMessage($e, __CLASS__, __FUNCTION__);
            throw new Exception($errorMessage);
        }
    }

    public function methodB() {
        try {
            // code for methodB
        } catch(Exception $e) {
            $errorMessage = Tasks::buildErrorMessage($e, __CLASS__, __FUNCTION__);
            throw new Exception($errorMessage);
        }
    }

    public function methodC() {
        try {
            // code for methodC
        } catch(Exception $e) {
            $errorMessage = Tasks::buildErrorMessage($e, __CLASS__, __FUNCTION__);
            throw new Exception($errorMessage);
        }
    }

}

So the buildErrorMessage function prevents each method from repeating the code that formats the error message, but there is something that really bothers me about have the same code spread through out every method in the class. I know that PHP doesn't support python-like decorator syntax, but just to demonstrate what I'm envisioning conceptually; I want the code to behave something more like this:

class MyController {

    @DefaultErrorHandling()
    public function methodA() {
        // code for methodB
    }

    @DefaultErrorHandling()
    public function methodB() {
        // code for methodB
    }

    @DefaultErrorHandling()
    public function methodC() {
        // code for methodC
    }

}

Where the @DefaultErrorHandling decorator would wrap each method in that standard try / catch. Is there a way I could achieve this behavior so I don't have to have all of these methods that have repeated code? Or am I thinking about error handling incorrectly?

Thanks to anyone who takes the time to answer this.

Kevin Aud
  • 378
  • 2
  • 12

3 Answers3

1

Have you looked at a writing a custom exception handler and using set_exception_handler?

What you are doing seems a bit like reinventing the wheel. Does the Exception not already have the info you are collecting in the trace? See: Exception::getTrace

Maybe buildErrorMessage does more? Anyway, I assume a custom exception handler is what you are after.

ficuscr
  • 6,975
  • 2
  • 32
  • 52
0

Not sure if there is a better way to solve this or not, but I created a logging class that formatted the log for me. Then just called this in my catch block.

To log the correct Class and Method, I the debug_backtrace() function. See this answer for more information.

shortchng
  • 66
  • 5
0

Entry point that calls controller methods can wrap those calls with try / catch. That being said, if you are planning to use different type of error handlers on those methods then you can implement something in your base controller (or use trait) that keeps track of which handler should be invoked on each particular method. Something like

<?php

class MyController extends Controller
{
    function __construct()
    {
        $this->setActionErrorHandler('function_name', 'handler');
    }
}

Or just call it at the beginning of action method body. Keeping this type of configuration within class itself will help with readability. Not as neat as python example but better than somewhere in configuration files.

More generic error handlers can be implemented in php by using set_exception_handler mentioned by others.

I'm not really getting why there is such a requirement.

featherbits
  • 790
  • 6
  • 24