What are Exceptions and how should I create and organize them in PHP

11

I'm creating an MVC system and want to implement Exceptions on my system. But I've never used it particularly. So I wanted to know how the Exceptions should be applied, since I saw here in StackOverflow in Portuguese someone talking (I can not remember if in response or comment) that most people do not know how to use Exceptions correctly. So I saw myself in this group of people who do not know how to use Exceptions , or at least never gave much importance to them, but now I see a real need to use them.

As I'm developing a code that will be the basis for several projects , my future, both academically and even professionally, I need to standardize it and develop it in a way that really makes the development of some project something more "simple" or focused and that facilitates and does not hamper.

Exceptions go into the story to help in the debug part, I want the framework to give me the error trail, where it started to where it stopped. I need to know the reasons for the mistakes and also have them tell me how to correct them. And since I'm new to object-oriented programming, it's the first time I've seen myself creating Exceptions and not treating them. But enough of history, let's go to the code.

I already created a Exception , code :

<?php
namespace Core\Exception;
use \Exception;

class SystemException extends Exception {
   function __construct($code, $args = array(), Exception $previous = NULL ) {
      $language = (require BASE . 'language' . DS . LANG . DS . 'exceptions.php');
      $format = $language[$code];

      $message = vsprintf($format, $args);
      parent::__construct($message, $code, $previous);
   }
   // personaliza a apresentação do objeto como string
   // public function __toString() {
   //    return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
   // }
}

So my idea was to create this SystemException to log error logs and all the rest be extended from it, or something like that. (So far I do not know if this will work). Note that I also modified the builder type, I do not really know if this is a good practice, the idea is to facilitate the translation of the errors. But I do not know if I should leave this for the "system" that is developed instead of giving this responsibility to the framework .

And here's a way where I'm throwing the exception :

protected function register($params){
   if (empty($params['controller']))
      throw new SystemException(Exceptions::E_INVALIDPARAMETERVALUE, ['NULL', '$params[controller]']);
   if (empty($params['action']))
      throw new SystemException(Exceptions::E_INVALIDPARAMETERVALUE, ['NULL', '$params[action]']);
   if (empty($params['lang'])){
      $params['lang'] = (empty($_COOKIE['language']) ? LANG : $_COOKIE['language']);
      throw new SystemException(Exceptions::E_INVALIDPARAMETERVALUE, ['NULL', '$params[controller]']);
   }

}

When I'm throwing an exception I'm just creating it by entering a code, which fetches the messages in a language file and passes them as parameters in an array used in the message.

So I wanted to know if I understood the concept and I'm applying the exceptions correctly?

Then there are some points / questions about the creation and concept of Exceptions :

  • How to standardize the exceptions?
  • How to automatically log logs of the thrown exceptions?
  • What is the parameter previous in the PHP Exception ?
  • What good practices and bad practices about Exceptions ?

Note: The automaticity of logs registers would be the idea of a "parent" class log every time an exception is thrown from a class that inherits from it.

    
asked by anonymous 03.09.2015 / 22:06

2 answers

3

I can help you with the question: How could I standardize my exceptions and log logs of automatically thrown exceptions?

If I understand correctly, you would like to log when the exception thrown was from the instance of SystemException .

I believe that the set_exception_handler function can help you in this case. See:

set_exception_handler(function($exception)
{
      if ($exception instanceof SystemException) {
          file_put_contents('log.txt', (string)$exception, FILE_APPEND);
      }

     throw $e; // Outras exceções são tratadas de maneira padrão
});

In the case of your Core\Route::register method code, I think it is very general to use the SystemException exception.

I think a more elegant approach would be to create another class of exceptions, which inherits SystemException , to refer only to exceptions that can occur in Route ,

class RouteException extends SystemException
{}

Another fact is that because it is also the handling of the arguments, I would use exceptions like UnexpectedValueException or InvalidArgumentException . If this is the case, you could also create an inheritance exception of SystemException (which you want to use for logging) that is specific to informing the invalidity of arguments.

I say this, because PHP treats both expressions as TRUE , because of inheritance:

$e = new SystemException;

$re = new RouteException;

$e = instanceof SystemException; // True

$re instanceof RouteException; // True
    
04.09.2015 / 18:22
2

Here's an example of good practices for handling exceptions , as well as creating a componentization and documenting your system, let no one below destroy your operation:

namespace SuaClasse\Component {

    interface Exception
    {}

    class UnexpectedValueException 
          extends \UnexpectedValueException 
          implements Exception
    {}

    class ReportingExpection
    {
        public static function doSomething()
        {
           try {
                if ($somethingExceptionalHappens) {
                    throw new UnexpectedValueException('mensagem da exceção');
                }

           } catch (UnexpectedValueException $e) {
              error_log($e->getMessage(), 3, "/var/tmp/errors.log");
           } 
        }
    }

}

Now that you have your component, just use it:

SuaClasse\Component\ReportingExpection::doSomething();
    
16.09.2015 / 23:06