Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This is a question about best practices. I have a project I am building and I have the following base Exception class:

Namespace Project;
class Exception extends \Exception{


    //=============== BASE EXCEPTIONS 0 - 1000 ===============//
    /**
     * placeholder for unknown exeptions - the default type
     * @var number
     */
    const UNKNOWN_ERROR                 = 0;

    //===================== GENERAL =======================//

    const NOT_YET_IMPLIMENTED           = 1001;
    const NON_UNIQUE_EXCEPTION          = 1002;



    /**
     * 
     * @param string $message
     * @param number $code
     * @param \Exception $previous
     */
    public function __construct( $message="", $code = 0, \Exception $previous = null ){

        if( $previous && $previous->getCode() == $code ){
            //we do some appending we don't wan't to re-append when re-throwing with the same code
            $message = $previous->getMessage();
        }else{
            $message = $this->getCustomMessage($code, $message);
        }
        parent::__construct($message, $code, $previous);
    }

    /**
     * Convert the __CLASS__::* constants into a basic error message and add
     * the extra bit for some more granularity
     * @param int $code
     * @param string $extra
     * @return string
     */
    public function getCustomMessage( $code, $extra ){
        $extra = trim( $extra );
        //get an array of class constants
        $ReflectionObj = new \ReflectionObject( $this );
        $constants = $ReflectionObj->getConstants();
        //find the constant by value ( values must be unique )
        $message = array_search($code, $constants);
        //format the message
        $message = ucwords( strtolower( str_replace("_", " ", $message)));
        $message .=  ( $extra == '' ) ? '' : ': '.$extra  ;
        return $message;
    }

}

This all works as desired and allows me to use the error constants as the message, such as:

 throw new Exception();
 throw new Exception('', Exception::UNKNOWN_ERROR);
 throw new Exception('I know what this error is', Exception::UNKNOWN_ERROR);

Which for the $e->message is:

- 'Unkown Error';
- 'Unkown Error';
- 'Unkown Error: I know what this error is';

Etc...

What I would like to do is by employing the magical power of eval (with the appropriate safeguards of course):

eval( "
    namespace Project\Exception;
    class $classname extends \Project\Exception{}
");

Where $classname would also be the error constant. So that I could essentially throw exceptions with an appropriate class for each without having to actually create the minimalistic class for each one.

An example would be:

try{
    $error = Exception::UNKNOWN_ERROR; // I know this is a number but for example sake we will say it equates to 'UNKNOWN_ERROR'
    throw new $error;
}catch( \Project\Exception\UNKNOWN_ERROR $e ){

}

Thus I would be able to catch the errors by checking the class names, not the error codes, while still maintaining a small code-base for the exception handler (I plan to have a lot of exceptions). My fear is that when extending exceptions I may lose track of the error numbers and may have some exception classes with conflicting error numbers, which I want to be unique for the whole project. So by employing this method, I have only the one main class to store my constants in but still get the benefits of having many exception classes.

Here is a little update on a new test I just ran. It seems that it is quite possible to throw a dynamic exception from the controller of the parent exception. This is pretty fantastic. To achieve this, a few special steps must be taken but nothing to radical.

share|improve this question

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.