I am working with the Laravel 9 application. I have created a custom Exception. I want to report the General Exception to the sentry and this custom Exception to another vendor like Papertrail.
The Handler.php is not calling the reportable closure function when the application throws a custom exception i.e ServiceException.
By the way, the Laravel documentation for errors is also not understandable
Handler.php
<?php
namespace AppExceptions;
use IlluminateFoundationExceptionsHandler as ExceptionHandler;
use InertiaInertia;
use Throwable;
use Exception;
use AppExceptionsServiceException;
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that are not reported.
*
* @var array
*/
protected $dontReport = [
// ServiceException::class
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->reportable(function (Throwable $e) {
// this block is calling for Exception but not for custom Exception like ServiceException.
if ($this->shouldReport($e) && app()->bound('sentry')) {
app('sentry')->captureException($e);
}
});
$this->reportable(function (ServiceException $e) {
// this block is not calling when I throw ServiceException.
echo "Send this ServiceException to papertrail app."; // this line is never called.
die;
});
}
public function render($request, Throwable $e)
{
$response = parent::render($request, $e);
if ($request->isJson()) {
//prevent error for local and staging.
if (! app()->environment(['local', 'staging']) && in_array($response->status(), [500, 503, 404, 403])) {
Log::error('API Error Handler', [$response->getOriginalContent()]);
$message = trans('message.error_description_500');
if ($response->status() == 404) {
$message = trans('message.data_not_found');
} elseif ($response->status() == 403) {
$message = trans('message.you_are_not_allowed_perform');
} elseif ($response->status() == 503) {
$message = trans('message.error_description_503');
}
return response()->json([
'message' => $message,
], $response->status());
}
}
return $response;
}
}
ServiceException.php
<?php
namespace AppExceptions;
use Exception;
class ServiceException extends Exception
{
/**
* Report the exception.
*
* @return void
*/
public function report()
{
//
}
/**
* Render the exception into an HTTP response.
*
* @param IlluminateHttpRequest $request
* @return IlluminateHttpResponse
*/
public function render($request, $exception)
{
if (! $request->ajax()) {
// view('error_handler', compact('exception'));
}
return response()->json([
'code' => $exception->getCode(),
'status' => 'error',
'message' => $exception->getMessage(),
'data' => 'sample data',
]);
}
}
AnyController.php
public function anyFunction() {
// throw new Exception('Unhandled Exception.'); // It will call the $this->reportable(function (Throwable $e) { block.
// throw new ServiceException('Unhandled ServiceException.'); // It will call the $this->reportable(function (Throwable $e) { block.
try {
$this->service->aFunctionThatThrowException(); // this function will throw ServiceException.
} catch (Exception $e) {
Log::error('controller_fun_error', ['error' => $e->getMessage()]);
report($e);
return $this->failResponse();
}
}
AnyService.php
public function aFunctionThatThrowException() {
try {
throw new ServiceException('Throwing ServiceException...)');
} catch (ServiceException | Exception $e) {
Log::error('service_fun_error', ['error' => $e->getMessage()]);
throw $e;
}
}
2
Answers
I’m not intirely sure, but I don’t think the error will be reported if you put a try catch around it yourself.
Create a new helper functions file eg: app/Helpers/Common.php and create a service provider HelperServiceProvider in app/Providers/HelperServiceProvider.php use the code below :
Now copy the below mentioned code to the app/Helpers/Common.php file :
Now you can easily call the throwResponse function from anywhere in the project :
for normal response
or
or for exceptions simply pass the exception $e
The response will be
for example :
Change responses according to your need