0

Disclaimer : I come on this topic after it has been recommended to me on my previous closed SO topic (see closed one : https://stackoverflow.com/questions/64338968/how-to-effectively-manage-a-large-number-of-exceptions-i18n-problematic).

Also, you'll see that event after a little bit of research and reading about the subject, I fail to found any consensual answer to this problematic.

So to begin I've been told that handling user inputs error by stoping work flow throwing Exception is a (very) bad idea. Some references to these topics :

So Even though there's a lot of debate around this question, I've make my opinion to not use Exception to stop propagation and take control over the work flow.

First I was thinking that it's a standard way to proceed. Throwing an exception to stop the process and let the controller decide the message to display. It was even possible to filter Exception by using inheritance.

I was even comforted in this idea by the "Fail early" principle. So basically I create all of my service arround this concept of throwing exception if a problem occurs. And then my controller catch my personnal exception (like LogicException) and display it nicely to the view like :

namespace App\Controller;

class ProductController{
   private ProductServiceInterface $productService;
   public function __construct(ProductServiceInterface $productService){
      $this->_productService = $productService;
   }
   
   public function show($id){
      try{
         $product = $this->_productService->getProductById($id);
      }catch(_LogicException $e){
         $this->addFlash($e->getStatus, $e->getMessage());
         if ($e->getRedirectRoute()) return $this->redirectToRoute($e->getRedirectRoute());
      }
   }
}

But the more I use this pattern, the more I see it looks wrong in many way :

  • Controller have responsibility to handle exceptions and returning a Response to a request (Breaking single responsibility principle).
  • Service should have the responsibility to handle exception, as they got some usefull context to provide to exceptions.
  • Keeps the controller as simple as possible ! (One of the best topics about this subject)
  • I have to dupplicate the handing exception logic on every function, for every controller. And dupplicate code is never a good idea. Even though I could just extends all controller on a base class, I still have to surround with try/catch on every functions for every controller. And if I change the exception handling logic I have dependecy on every Controller so I have to change it everywhere arround the application. (Encapsulate What May Change).

I think that many of tutorial propose as an exercice to try/catch incorrect user input so it may lead many misguided peoples (like me) to think that Exception can be use to control wrok flow when a user input is incorrect. Always following the "Fail early" principles, it seams easy to stop the process with an exception, and so I adopt it as a standard way to proceed.

Of course, if you encouter critical error (database connection unavailable, mailer dsn unavailable...), you still have to throw an exception. This is especially true for technical errors. You should've two different behavior, one in debug mode so Exception is thrown and you can debug it easily. And a no debug mode (for production environment...) where technical Exception are stored in a log file, and then a user friendly message display "Something went wrong" and for instance will proceed to redirect user to security.

So finally, I'm going to use a solution based on this solution : https://gist.github.com/javiereguiluz/a66f084a4f2cf11cf0ee#gistcomment-1308966

This is a verry elegant solution to me. Using a event dispatcher and a event listener have a lot of advantages :

  • Giving the responsibility to handle error message to a Event listener.
  • Can access to context through the Event object passed to dispatcher.
  • Can use inheritance to have translation logic inside one EventHelper class.
  • All error message in one place. If a message is needed to be change, there is no need to search for it everywhere.

Tutorial about event listener

What do you think about this solution, please let me know.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.