phpdynamic-sqlatk4

PHP Exception Arguments


I am working on a PHP library, which may be used in various environments by different PHP projects and I'm trying to be as minimalistic as possible.

In some circumstances I have to throw exceptions, for instance.

throw Exception('template has invalid tag');

The error like that is not very useful without the name of the tag:

throw Exception('template has invalid tag: '.$tag);

This would would be hard to localize and may result all sorts of injection problems.

QUESTION: What is the best way to pass extra variables with Exception in PHP?

(note: my library perform SQL Query building and I would prefer it to focus on the task, not solving problems with Exceptions)


Solution

  • The internationalization is not the responsibility of your library. Create one or more Exception classes for your project (throwing \Exception is not recommended as it is too generic) and let them store the parameters in properties.

    Let the error messages as they are now but also pass the values as arguments to the constructors of the new exceptions. Provide getters for them. The error messages are for the developers. The code that uses your library must catch the exceptions and display the error messages that are appropriate for them. They should not display the raw message you provide, anyway.

    For example, you declare in your library:

    class InvalidTagException extends \Exception
    {
        protected $tag;
    
        public function __construct($message, $tag, $code = 0, Throwable $previous = NULL)
        {
            // Let the parent class initialize its members
            parent::__construct($message, $code, $previous);
            // Initialize own members
            $this->tag = $tag;
        }
    
        public function getTag()
        {
            return $tag;
        }
    }
    
    // Declare other Exception classes in a similar fashion, for each kind of exception you throw
    class InvalidValueException extends \Exception
    {
        // ...
    }
    

    The application that uses your library:

    try {
        // call your library code here
    } catch (InvalidTagException $e) {
        // Handle in application specific way
    
    } catch (InvalidValueException $e) {
        // A different type of exception requires a different type of handling
    }