laravel中有哪些異常

2022-06-28 18:00:26

laravel中的異常有:1、「E_ERROR」致命執行時錯誤,不可恢復,會導致指令碼終止不再繼續執行;2、「E_WARNING」執行時警告「非致命錯誤」;3、「E_PARSE」編譯時語法解析錯誤;4、「E_CORE_ERROR」初始化啟動過程中發生的致命錯誤;5、「E_COMPILE_ERROR」致命編譯時錯誤;6、「E_RECOVERABLE_ERROR」可被捕捉的致命錯誤。

本教學操作環境:windows7系統、Laravel9版,DELL G3電腦。

laravel中的異常級別

常數說明
E_ERROR致命的執行時錯誤。這類錯誤一般是不可恢復的情況,例如記憶體分配導致的問題。後果是導致指令碼終止不再繼續執行。
E_WARNING執行時警告 (非致命錯誤)。僅給出提示資訊,但是指令碼不會終止執行。
E_PARSE編譯時語法解析錯誤。解析錯誤僅僅由分析器產生。
E_NOTICE執行時通知。表示指令碼遇到可能會表現為錯誤的情況,但是在可以正常執行的指令碼裡面也可能會有類似的通知。
E_CORE_ERROR在 PHP 初始化啟動過程中發生的致命錯誤。該錯誤類似 E_ERROR,但是是由 PHP 引擎核心產生的。
E_CORE_WARNINGPHP 初始化啟動過程中發生的警告 (非致命錯誤) 。類似 E_WARNING,但是是由 PHP 引擎核心產生的。
E_COMPILE_ERROR致命編譯時錯誤。類似 E_ERROR, 但是是由 Zend 指令碼引擎產生的。
E_COMPILE_WARNING編譯時警告 (非致命錯誤)。類似 E_WARNING,但是是由 Zend 指令碼引擎產生的。
E_USER_ERROR使用者產生的錯誤資訊。類似 E_ERROR, 但是是由使用者自己在程式碼中使用 PHP 函數 trigger_error () 來產生的。
E_USER_WARNING使用者產生的警告資訊。類似 E_WARNING, 但是是由使用者自己在程式碼中使用 PHP 函數 trigger_error () 來產生的。
E_USER_NOTICE使用者產生的通知資訊。類似 E_NOTICE, 但是是由使用者自己在程式碼中使用 PHP 函數 trigger_error () 來產生的。
E_STRICT啟用 PHP 對程式碼的修改建議,以確保程式碼具有最佳的互操作性和向前相容性。
E_RECOVERABLE_ERROR可被捕捉的致命錯誤。 它表示發生了一個可能非常危險的錯誤,但是還沒有導致 PHP 引擎處於不穩定的狀態。 如果該錯誤沒有被使用者自定義控制程式碼捕獲 (參見 set_error_handler ()),將成為一個 E_ERROR 從而指令碼會終止執行。
E_DEPRECATED執行時通知。啟用後將會對在未來版本中可能無法正常工作的程式碼給出警告。
E_USER_DEPRECATED使用者產少的警告資訊。 類似 E_DEPRECATED, 但是是由使用者自己在程式碼中使用 PHP 函數 trigger_error () 來產生的。
E_ALL使用者產少的警告資訊。 類似 E_DEPRECATED, 但是是由使用者自己在程式碼中使用 PHP 函數 trigger_error () 來產生的。

Laravel 例外處理

laravel 的例外處理由類 \Illuminate\Foundation\Bootstrap\HandleExceptions::class 完成:

class HandleExceptions
{
    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');
        }
    }
}

異常轉化

laravel 的例外處理均由函數 handleException 負責。

PHP7 實現了一個全域性的 throwable 介面,原來的 Exception 和部分 Error 都實現了這個介面, 以介面的方式定義了異常的繼承結構。於是,PHP7 中更多的 Error 變為可捕獲的 Exception 返回給開發者,如果不進行捕獲則為 Error ,如果捕獲就變為一個可在程式內處理的 Exception。這些可被捕獲的 Error 通常都是不會對程式造成致命傷害的 Error,例如函數不存在。

PHP7 中,基於 /Error exception,派生了 5 個新的 engine exception:ArithmeticError / AssertionError / DivisionByZeroError / ParseError / TypeError。在 PHP7 裡,無論是老的 /Exception 還是新的 /Error ,它們都實現了一個共同的 interface: /Throwable。

因此,遇到非 Exception 型別的異常,首先就要將其轉化為 FatalThrowableError 型別:

public function handleException($e)
{
    if (! $e instanceof Exception) {
        $e = new FatalThrowableError($e);
    }

    $this->getExceptionHandler()->report($e);

    if ($this->app->runningInConsole()) {
        $this->renderForConsole($e);
    } else {
        $this->renderHttpResponse($e);
    }
}

FatalThrowableError 是 Symfony 繼承 \ErrorException 的錯誤異常類:

class FatalThrowableError extends FatalErrorException
{
    public function __construct(\Throwable $e)
    {
        if ($e instanceof \ParseError) {
            $message = 'Parse error: '.$e->getMessage();
            $severity = E_PARSE;
        } elseif ($e instanceof \TypeError) {
            $message = 'Type error: '.$e->getMessage();
            $severity = E_RECOVERABLE_ERROR;
        } else {
            $message = $e->getMessage();
            $severity = E_ERROR;
        }

        \ErrorException::__construct(
            $message,
            $e->getCode(),
            $severity,
            $e->getFile(),
            $e->getLine()
        );

        $this->setTrace($e->getTrace());
    }
}

異常 Log

當遇到異常情況的時候,laravel 首要做的事情就是記錄 log,這個就是 report 函數的作用。

protected function getExceptionHandler()
{
    return $this->app->make(ExceptionHandler::class);
}

laravel 在 Ioc 容器中預設的例外處理類是 Illuminate\Foundation\Exceptions\Handler:

class Handler implements ExceptionHandlerContract
{
    public function report(Exception $e)
    {
        if ($this->shouldntReport($e)) {
            return;
        }
        try {
            $logger = $this->container->make(LoggerInterface::class);
        } catch (Exception $ex) {
            throw $e; // throw the original exception
        }
        $logger->error($e);
    }
    protected function shouldntReport(Exception $e)
    {
        $dontReport = array_merge($this->dontReport, [HttpResponseException::class]);
        return ! is_null(collect($dontReport)->first(function ($type) use ($e) {
            return $e instanceof $type;
        }));
    }
}

異常頁面展示

記錄 log 後,就要將異常轉化為頁面向開發者展示異常的資訊,以便檢視問題的來源:

protected function renderHttpResponse(Exception $e)
{
    $this->getExceptionHandler()->render($this->app['request'], $e)->send();
}
class Handler implements ExceptionHandlerContract
{
    public function render($request, Exception $e)
    {
        $e = $this->prepareException($e);
        if ($e instanceof HttpResponseException) {
            return $e->getResponse();
        } elseif ($e instanceof AuthenticationException) {
            return $this->unauthenticated($request, $e);
        } elseif ($e instanceof ValidationException) {
            return $this->convertValidationExceptionToResponse($e, $request);
        }
        return $this->prepareResponse($request, $e);
    }
}

對於不同的異常,laravel 有不同的處理,大致有 HttpException、HttpResponseException、AuthorizationException、ModelNotFoundException、AuthenticationException、ValidationException。由於特定的不同異常帶有自身的不同需求,本文不會特別介紹。本文繼續介紹最普通的異常 HttpException 的處理:

protected function prepareResponse($request, Exception $e)
{
    if ($this->isHttpException($e)) {
        return $this->toIlluminateResponse($this->renderHttpException($e), $e);
    } else {
        return $this->toIlluminateResponse($this->convertExceptionToResponse($e), $e);
    }
}
protected function renderHttpException(HttpException $e)
{
    $status = $e->getStatusCode();
    view()->replaceNamespace('errors', [
        resource_path('views/errors'),
        __DIR__.'/views',
    ]);
    if (view()->exists("errors::{$status}")) {
        return response()->view("errors::{$status}", ['exception' => $e], $status, $e->getHeaders());
    } else {
        return $this->convertExceptionToResponse($e);
    }
}

對於 HttpException 來說,會根據其錯誤的狀態碼,選取不同的錯誤頁面模板,若不存在相關的模板,則會通過 SymfonyResponse 來構造異常展示頁面:

protected function convertExceptionToResponse(Exception $e)
{
    $e = FlattenException::create($e);
    $handler = new SymfonyExceptionHandler(config('app.debug'));
    return SymfonyResponse::create($handler->getHtml($e), $e->getStatusCode(), $e->getHeaders());
}
protected function toIlluminateResponse($response, Exception $e)
{
    if ($response instanceof SymfonyRedirectResponse) {
        $response = new RedirectResponse($response->getTargetUrl(), $response->getStatusCode(), $response->headers->all());
    } else {
        $response = new Response($response->getContent(), $response->getStatusCode(), $response->headers->all());
    }
    return $response->withException($e);
}

【相關推薦:】

以上就是laravel中有哪些異常的詳細內容,更多請關注TW511.COM其它相關文章!