Hello, I’m a Rocket
This is the second day of my participation in Gwen Challenge
The introduction
- What is the Laravel framework for handling errors and exceptions
- How to customize the exception response at work
- How do I modify the exception Response page
- Let’s take you to a deeper understanding
1. When to register custom exception and error handlers
Refer to my last article when the kernel is loaded upon startup
\Illuminate\Foundation\Bootstrap\HandleExceptions Registers the exception error handler
public function bootstrap(Application $app) { $this->app = $app; error_reporting(-1); set_error_handler([$this, 'handleError']); Set_exception_handler ([$this, 'handleException']); Register_shutdown_function ([$this, 'handleShutdown']); // If (! $app->environment('testing')) { ini_set('display_errors', 'Off'); }}Copy the code
Converts conforming errors into exception classes
public function handleError($level, $message, $file = '', $line = 0, $context = []) { if (error_reporting() & $level) { throw new ErrorException($message, 0, $level, $file, $line); }}Copy the code
Exception Handling report + output page
public function handleException($e) { if (! $e instanceof Exception) {// FatalThrowableError $e = new FatalThrowableError($e); } try { $this->getExceptionHandler()->report($e); } catch (Exception $e) { // } if ($this->app->runningInConsole()) { $this->renderForConsole($e); } else { $this->renderHttpResponse($e); } } protected function renderForConsole(Exception $e) { $this->getExceptionHandler()->renderForConsole(new ConsoleOutput, $e); } protected function renderHttpResponse(Exception $e) { $this->getExceptionHandler()->render($this->app['request'], $e)->send(); }Copy the code
Listen for PHP script interrupts if there is an error and the error type contains convert from FatalErrorException and handle the exception
public function handleShutdown()
{
if (! is_null($error = error_get_last()) && $this->isFatal($error['type'])) {
$this->handleException($this->fatalExceptionFromError($error, 0));
}
}
protected function isFatal($type)
{
return in_array($type, [E_COMPILE_ERROR, E_CORE_ERROR, E_ERROR, E_PARSE]);
}
protected function fatalExceptionFromError(array $error, $traceOffset = null)
{
return new FatalErrorException(
$error['message'], $error['type'], 0, $error['file'], $error['line'], $traceOffset
);
}
Copy the code
Get the exception handler
Protected function getExceptionHandler () {/ / get the exception handling app/Exceptions/Handler. PHP return $this->app->make(ExceptionHandler::class); }Copy the code
App/Exceptions/Handler. PHP framework extension exception classes
class Handler extends ExceptionHandler { public function report(Exception $exception) { parent::report($exception); } public function render($request, Exception $exception) { return parent::render($request, $exception); }}Copy the code
The base exception class of the Illuminate Foundation Exceptions Handler framework implements the interface Illuminate\Contracts Debug\ExceptionHandler
Public function report($e) {if ($this->shouldntReport($e)) {if ($this->shouldntReport($e)) { return; } // If (method_exists($e, 'report')) {return $e->report(); } try { $logger = $this->container->make(LoggerInterface::class); } catch (Exception $ex) { throw $e; $logger->error($e->getMessage(), array_merge($this->context(), ['exception' => $e])); } protected function shouldntReport(Exception $e) { $dontReport = array_merge($this->dontReport, $this->internalDontReport); return ! is_null(Arr::first($dontReport, function ($type) use ($e) { return $e instanceof $type; })); } protected function context() { try { return array_filter([ 'userId' => Auth::id(), 'email' => Auth::user() ? Auth::user()->email : null, ]); } catch (Throwable $e) { return []; }}Copy the code
Error output
Public function render($request, Exception $e) {// If (method_exists($e, 'render') && $response = $e->render($request)) { return Router::toResponse($request, $response); $e->toResponse($request); $e->toResponse($request); $e->toResponse($request); $e = $this->prepareException($e); if ($e instanceof HttpResponseException) { return $e->getResponse(); } elseIf ($e instanceof AuthenticationException) {return $this->unauthenticated($request, $e); } elseif ($e instanceof thrown) {/ / verification abnormal return $this - > convertValidationExceptionToResponse ($e, $request); } return $request->expectsJson() ? $this->prepareJsonResponse($request, $e) : $this->prepareResponse($request, $e); } protected function prepareException(Exception $e) { if ($e instanceof ModelNotFoundException) { $e = new NotFoundHttpException($e->getMessage(), $e); } elseif ($e instanceof AuthorizationException) { $e = new AccessDeniedHttpException($e->getMessage(), $e); } elseif ($e instanceof TokenMismatchException) {//csrf token $e = new HttpException(419, $e->getMessage(), $e); } return $e; }Copy the code
prepareJsonResponse
Protected function prepareJsonResponse($request, Exception $e) { return new JsonResponse( $this->convertExceptionToArray($e), $this->isHttpException($e) ? $e->getStatusCode() : 500, $this->isHttpException($e) ? $e->getHeaders() : [], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ); } protected function convertExceptionToArray(Exception $e) { return config('app.debug') ? [ 'message' => $e->getMessage(), 'exception' => get_class($e), 'file' => $e->getFile(), 'line' => $e->getLine(), 'trace' => collect($e->getTrace())->map(function ($trace) { return Arr::except($trace, ['args']); })->all(), ] : [ 'message' => $this->isHttpException($e) ? $e->getMessage() : 'Server Error', ]; }Copy the code
prepareResponse
Protected function prepareResponse($request, Exception $e) {if (! $this->isHttpException($e) && config('app.debug')) {$this->isHttpException($e) && config('app.debug')) $this->toIlluminateResponse($this->convertExceptionToResponse($e), $e); } if (! $this->isHttpException($e)) { $e = new HttpException(500, $e->getMessage()); } return $this->toIlluminateResponse( $this->renderHttpException($e), $e ); } / / is mainly the debug = true when protected function convertExceptionToResponse (Exception $e) {return SymfonyResponse: : create ( $this->renderExceptionContent($e), $this->isHttpException($e) ? $e->getStatusCode() : 500, $this->isHttpException($e) ? $e->getHeaders() : [] ); } protected function renderExceptionContent(Exception $e) {try {//debug returns config('app.debug') && class_exists(Whoops::class) ? $this->renderExceptionWithWhoops($e) : $this->renderExceptionWithSymfony($e, config('app.debug')); } catch (Exception $e) { return $this->renderExceptionWithSymfony($e, config('app.debug')); Function renderHttpException(HttpException $e) {// Register the error page $this->registerErrorViewPaths(); If (view()->exists($view = "errors::{$e->getStatusCode()}")) {return response()->view($view, $view) [ 'errors' => new ViewErrorBag, 'exception' => $e, ], $e->getStatusCode(), $e->getHeaders()); } return $this->convertExceptionToResponse($e); }Copy the code
2. Flow chart
3. How to ignore exceptions
Added to the dontReport
4. Write the error to the log
It is written to the log during the report
5. Customize the exception response
Implement PHP Exception, can define their own report and render
6. Modify the error page
Refer to point 7 to register the error page to the view
7, you can customize the method inapp/Exceptions/Handler.php
Unauthenticated Handles unauthorized exceptions
Protected function unauthenticated($request, AuthenticationException $exception) {your logic}Copy the code
ConvertValidationExceptionToResponse validation class exception handling
Protected function convertValidationExceptionToResponse (thrown $e, $request) logical} {youCopy the code
RegisterErrorViewPaths Registers error pages to views
Protected function registerErrorViewPaths() {your logic should look at view processing}Copy the code
8. How to debug gracefully online (without tuning error logs and filtering)
Set class member protected $debug=false; public function __construct(Container $container) { $this->container = $container; $this->debug = isset($_GET['debug'])? $_GET['debug'] == 'h5debug':config('app.debug'); } protected function prepareResponse($request, Exception $e) { if (! $this->isHttpException($e) && $this->debug) $this->toIlluminateResponse($this->convertExceptionToResponse($e), $e); } if (! $this->isHttpException($e)) { $e = new HttpException(500, $e->getMessage()); } return $this->toIlluminateResponse( $this->renderHttpException($e), $e ); } protected function renderExceptionContent(Exception $e) {try {//debug returns $this->debug && when true class_exists(Whoops::class) ? $this->renderExceptionWithWhoops($e) : $this->renderExceptionWithSymfony($e, config('app.debug')); } catch (Exception $e) { return $this->renderExceptionWithSymfony($e, config('app.debug')); Protected function convertExceptionToArray(Exception $e) {return $this->debug? [ 'message' => $e->getMessage(), 'exception' => get_class($e), 'file' => $e->getFile(), 'line' => $e->getLine(), 'trace' => collect($e->getTrace())->map(function ($trace) { return Arr::except($trace, ['args']); })->all(), ] : [ 'message' => $this->isHttpException($e) ? $e->getMessage() : 'Server Error', ]; }Copy the code
At the end
With you mutual encouragement, I hope to help you