Elad Elad - 4 months ago 25
PHP Question

Laravel exceptions handler

I'm working on a project with Laravel, exceptions are getting catched in the

Exceptions\Handler.php
inside the render function like so:

public function render($request, Exception $e){
switch(get_class($e)){
case SOME_EXCEPTION::class:
do something..
...
...
default:
do something..
}


The problem as you can see it's getting ugly and messy code with lot of cases

How to fix this?

Answer

Ok, found a way to make it look better. If anyone would like to improve his Exceptions handler in laravel follow this:

Under app/providers create your new service-provider, lets call it ExceptionServiceProvider.php

    class ExceptionServiceProvider extends ServiceProvider {

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(ExceptionFactory::class);
    }

    public function boot(ExceptionFactory $factory){
        $factory->addException(UnauthorizedException::class, JsonResponse::HTTP_NOT_ACCEPTABLE);
        $factory->addException(ConditionException::class, JsonResponse::HTTP_NOT_ACCEPTABLE, "Some Fixed Error Message");

    }
}

Create somewhere on your project the ExceptionFactory class which contain the addException method and getters for the code&messages

class ExceptionFactory{


private $exceptionsMap = [];
private $selectedException;

public function addException($exception, $code, $customMessage = null) {
    $this->exceptionsMap[$exception] = [$code, $customMessage];
}

public function getException($exception){
    if(isset($this->exceptionsMap[$exception])){
        return $this->exceptionsMap[$exception];
    }
    return null;
}

public function setException($exception){
    $this->selectedException = $exception;
}

public function getCode(){
    return $this->selectedException[0];
}

public function getCustomMessage(){
    return $this->selectedException[1];
}

}

Then all left to do is inside the Exceptions/handler.php in the render function:

private $exceptionFactory;

    public function __construct(LoggerInterface $log, ExceptionFactory $exceptionFactory){
        parent::__construct($log);
        $this->exceptionFactory = $exceptionFactory;
    }

public function render($request, Exception $e){
        $error = new \stdClass();
        $customException = $this->exceptionFactory->getException(get_class($e));

        if(isset($customException)){
            $this->exceptionFactory->setException($customException);
            $error->code = $this->exceptionFactory->getCode();
            $error->message = $e->getMessage();
            $customMessage = $this->exceptionFactory->getCustomMessage();
            if(isset($customMessage)){
                $error->message = $customMessage;
            }
       }
       return new JsonResponse($error, $error->code);
 }
}

Last thing to remember is to put the ServiceProvider in the application settings under config/app.php just add:

\App\Providers\ExceptionServiceProvider::class

I hope you'll find this useful as I did.