Search code examples
phplaravelexceptionexceptionhandler

Low-level exception class to target all exceptions


I'm trying to modify my App\Exceptions\Handler to pass the request (and therefore current URL) through to all exceptions. For this reason I need the lowest-level exception class I can get hold of to type-hint to the ->renderable() method.

Laravel/Symfony's HttpException works but only for HTTP errors, leaving out all non-HTTP exceptions. PHP's Exception class works when using getCode() instead of getStatusCode(), but always returns a "0" for both HTTP errors and exceptions. Is there another low-level exception class that will work for my purposes, or otherwise any other way to accomplish what I'm trying to do here?

public function register()
{

$this->renderable(function (Exception $exception, $request) {

    $url = $request->fullUrl();
    $status = $exception->getCode();

    Log::warning("Error $status when trying to visit $url. Received the following message: " . $exception->getMessage()); 

    return response()->view("errors.$status", [
        "exception" => $exception
        ],
    $status
    );    
    });
   
    }

}

For what it's worth, I'm using the following web routes to trigger exceptions and HTTP errors for testing:

if (app()->environment('local')) {
    Route::get("/exception", function (){
        throw new JsonException; // chosen because it's one of the few Laravel exceptions 
                                 // that doesn't seem to automatically resolve to a HTTP error
    });
}

if (app()->environment('local')) {
    Route::get("/fail/{status}", function ($status){
        abort($status);
    });
}

Solution

  • As requested, this is what I have in my Handler. I use some custom logging, and I want to make sure I grab the right code when it's an HTTP error.

    public function report(Throwable $e)
    {
        $code = match (get_class($e)) {
            'Symfony\Component\HttpKernel\Exception\NotFoundHttpException' => 404,
            \HttpException::class => $e->getStatusCode(),
            default => 'No Code',
        };
        // more stuff here 
     }
    

    You can use $e->getCode() for your default as well