찾다
PHP 프레임워크LaravelLaravel 핵심 분석 예외 처리(코드)

Laravel 핵심 분석 예외 처리(코드)

Feb 11, 2019 am 10:22 AM
laravelphp

이 글의 내용은 Laravel 핵심 분석의 예외 처리(코드)에 대한 내용입니다. 필요한 친구들이 참고할 수 있기를 바랍니다.

예외 처리는 프로그래밍에서 매우 중요하지만 가장 간과되는 언어 기능입니다. 이는 개발자에게 프로그램 런타임 오류를 처리하는 메커니즘을 제공합니다. 프로그램 설계의 경우 올바른 예외 처리를 통해 프로그램 자체의 세부 정보가 사용자에게 유출되는 것을 방지할 수 있습니다. 완전한 오류 역추적 스택을 제공하는 동시에 프로그램의 견고성을 향상시킵니다.

이 기사에서는 Laravel에서 제공되는 예외 처리 기능을 간략하게 검토한 다음 개발 시 예외 처리를 사용하는 몇 가지 사례, 사용자 정의 예외를 사용하는 방법 및 Laravel의 예외 처리 기능을 확장하는 방법에 대해 설명합니다.

예외 처리기 등록

여기서 커널이 우리가 여러 번 말한 요청을 처리하기 전에 부트스트랩 단계로 돌아가야 합니다. 부트스트랩 단계의 IlluminateFoundationBootstrapHandleExceptions 섹션에서 Laravel은 시스템 예외 처리 동작을 설정하고 등록합니다. 전역 예외 처리기. ExceptionHandler. 예외 기록은 Storage/laravel.log 파일이며, 요청 유형에 따라 예외 응답을 렌더링하여 클라이언트에 출력합니다. 여기서 ExceptionHandler는 프로젝트 시작 시 서비스 컨테이너에 등록된 AppExceptionsHandler 클래스의 인스턴스입니다.

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');
        }
    }
    
    
    public function handleError($level, $message, $file = '', $line = 0, $context = [])
    {
        if (error_reporting() & $level) {
            throw new ErrorException($message, 0, $level, $file, $line);
        }
    }
}

여기서 set_error_handler 함수는 오류 핸들러 함수를 등록하는 데 사용됩니다. 또는 대부분의 클래스 라이브러리는 오류를 발생시키기 위해 PHP의 Trigger_error 함수를 사용합니다. 따라서 예외 핸들러는 예외만 처리할 수 있지만 오류는 처리할 수 없습니다. 따라서 이전 클래스 라이브러리와 호환되기 위해 일반적으로 전역 오류 핸들러 메소드를 등록하는 데 set_error_handler가 사용됩니다. 메서드에 오류가 있으면 오류가 예외로 변환된 다음 다시 발생하므로 프로젝트의 모든 코드가 올바르게 실행되지 않을 때 예외 인스턴스가 발생할 수 있습니다.

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);
    }
}

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

// 渲染CLI请求的异常响应
protected function renderForConsole(Exception $e)
{
    $this->getExceptionHandler()->renderForConsole(new ConsoleOutput, $e);
}

// 渲染HTTP请求的异常响应
protected function renderHttpResponse(Exception $e)
{
    $this->getExceptionHandler()->render($this->app['request'], $e)->send();
}

일반적으로 사용되는 Laravel 예외 예제

Laravel은 공통 프로그램 예외에 해당하는 예외 인스턴스를 발생시킵니다. 이를 통해 개발자는 이러한 런타임 예외를 캡처하고 필요에 따라 후속 처리를 수행할 수 있습니다(예: catch에서 다른 해결 방법 호출, 로그 파일에 예외 기록, 알람 이메일 보내기, 문자 메시지 보내기) 여기에서는 개발 중에 흔히 발생하는 몇 가지 예외를 나열하고 일반적인 코딩 중에 어떤 상황에서 예외가 발생하는지 설명합니다. 프로그램에서 이러한 예외를 포착하는 데 주의해야 합니다. 프로그램을 더욱 강력하게 만들기 위해 이를 잘 처리합니다.

IlluminateDatabaseQueryException 이 예외는 Laravel에서 SQL 문을 실행할 때 오류가 발생할 때 발생합니다. 또한 가장 일반적으로 사용되는 예외이며, 예를 들어 Update 문을 실행할 때 많은 사람들이 사용합니다. SQL 실행 후 수정된 행의 수를 판단하여 UPDATE 성공 여부를 판단하지만, 일부 시나리오에서는 실행된 UPDATE 문이 레코드 값을 수정하지 않는 경우 이를 통해 UPDATE 성공 여부를 판단하는 것이 불가능합니다. 또한, 트랜잭션 실행 중에 QueryException이 발생하면 코드 블록에서 트랜잭션을 롤백하는 데 사용할 수 있습니다.

IlluminateDatabaseEloquentModelNotFoundException 이 예외는 모델의 findOrFail 및 firstOrFail 메소드를 통해 단일 레코드를 찾을 수 없는 경우 발생합니다(find 및 first는 데이터를 찾을 수 없으면 NULL을 반환합니다).

IlluminateValidationValidationException 이 예외는 요청이 Laravel의 FormValidator 유효성 검사를 통과하지 못한 경우 발생합니다.

IlluminateAuthAccessAuthorizationException 사용자 요청이 Laravel의 정책(Policy) 검증을 통과하지 못한 경우 발생하는 예외입니다.

SymfonyComponentRoutingExceptionMethodNotAllowedException 라우팅을 요청할 때 HTTP 메서드가 올바르지 않습니다.

IlluminateHttpExceptionsHttpResponseException Laravel이 HTTP 요청 예외 처리에 실패할 때 발생합니다.

Laravel 확장 예외 handler

위에서 언급했듯이 Laravel은 AppExceptionsHandler를 전역 예외 처리기로 성공적으로 등록했습니다. 코드에서 포착되지 않은 예외는 결국 AppExceptionsHandler에 의해 포착됩니다. 그런 다음 응답이 클라이언트로 전송됩니다. 그러나 내장된 예외 처리 방법은 사용하기 쉽지 않습니다. 이메일이나 오류 로그 시스템에 예외를 보고하려는 경우가 많습니다. Sentry 시스템에 예외를 보고하는 경우는 매우 좋습니다. 사용:

// bootstrap/app.php

/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
*/

$app = new Illuminate\Foundation\Application(
    realpath(__DIR__.'/../')
);

/*
|--------------------------------------------------------------------------
| Bind Important Interfaces
|--------------------------------------------------------------------------
*/
......

$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);
및 기본 렌더링 방법 양식 확인 중에 생성된 응답의 JSON 형식은 렌더링 방법의 동작을 사용자 정의해야 하는 프로젝트의 통합

형식과 다른 경우가 많습니다.

public function render($request, Exception $exception)
{
    //如果客户端预期的是JSON响应,  在API请求未通过Validator验证抛出ValidationException后
    //这里来定制返回给客户端的响应.
    if ($exception instanceof ValidationException && $request->expectsJson()) {
        return $this->error(422, $exception->errors());
    }

    if ($exception instanceof ModelNotFoundException && $request->expectsJson()) {
        //捕获路由模型绑定在数据库中找不到模型后抛出的NotFoundHttpException
        return $this->error(424, 'resource not found.');
    }


    if ($exception instanceof AuthorizationException) {
        //捕获不符合权限时抛出的 AuthorizationException
        return $this->error(403, "Permission does not exist.");
    }

    return parent::render($request, $exception);
}

自定义后,在请求未通过FormValidator验证时会抛出ValidationException, 之后异常处理器捕获到异常后会把错误提示格式化为项目统一的JSON响应格式并输出给客户端。这样在我们的控制器中就完全省略了判断表单验证是否通过如果不通过再输出错误响应给客户端的逻辑了,将这部分逻辑交给了统一的异常处理器来执行能让控制器方法瘦身不少。

使用自定义异常

这部分内容其实不是针对Laravel框架自定义异常,在任何项目中都可以应用我这里说的自定义异常。

我见过很多人在Repository或者Service类的方法中会根据不同错误返回不同的数组,里面包含着响应的错误码和错误信息,这么做当然是可以满足开发需求的,但是并不能记录发生异常时的应用的运行时上下文,发生错误时没办法记录到上下文信息就非常不利于开发者进行问题定位。

下面的是一个自定义的异常类

namespace App\Exceptions\;

use RuntimeException;
use Throwable;

class UserManageException extends RuntimeException
{
    /**
     * The primitive arguments that triggered this exception
     *
     * @var array
     */
    public $primitives;
    /**
     * QueueManageException constructor.
     * @param array $primitives
     * @param string $message
     * @param int $code
     * @param Throwable|null $previous
     */
    public function __construct(array $primitives, $message = "", $code = 0, Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->primitives = $primitives;
    }

    /**
     * get the primitive arguments that triggered this exception
     */
    public function getPrimitives()
    {
        return $this->primitives;
    }
}

定义完异常类我们就能在代码逻辑中抛出异常实例了

class UserRepository
{
  
    public function updateUserFavorites(User $user, $favoriteData)
    {
        ......
        if (!$executionOne) {
            throw new UserManageException(func_get_args(), 'Update user favorites error', '501');
        }
        
        ......
        if (!$executionTwo) {
            throw new UserManageException(func_get_args(), 'Another Error', '502');
        }
        
        return true;
    }
}

class UserController extends ...
{
    public function updateFavorites(User $user, Request $request)
    {
        .......
        $favoriteData = $request->input('favorites');
        try {
            $this->userRepo->updateUserFavorites($user, $favoritesData);
        } catch (UserManageException $ex) {
            .......
        }
    }
}

除了上面Repository列出的情况更多的时候我们是在捕获到上面列举的通用异常后在catch代码块中抛出与业务相关的更细化的异常实例方便开发者定位问题,我们将上面的updateUserFavorites 按照这种策略修改一下

public function updateUserFavorites(User $user, $favoriteData)
{
    try {
        // database execution
        
        // database execution
    } catch (QueryException $queryException) {
        throw new UserManageException(func_get_args(), 'Error Message', '501' , $queryException);
    }

    return true;
}

在上面定义UserMangeException类的时候第四个参数$previous是一个实现了Throwable接口类实例,在这种情景下我们因为捕获到了QueryException的异常实例而抛出了UserManagerException的实例,然后通过这个参数将QueryException实例传递给PHP异常的堆栈,这提供给我们回溯整个异常的能力来获取更多上下文信息,而不是仅仅只是当前抛出的异常实例的上下文信息, 在错误收集系统可以使用类似下面的代码来获取所有异常的信息。

while($e instanceof \Exception) {
    echo $e->getMessage();
    $e = $e->getPrevious();
}

异常处理是PHP非常重要但又容易让开发者忽略的功能,这篇文章简单解释了Laravel内部异常处理的机制以及扩展Laravel异常处理的方式方法。更多的篇幅着重分享了一些异常处理的编程实践,这些正是我希望每个读者都能看明白并实践下去的一些编程习惯,包括之前分享的Interface的应用也是一样。

위 내용은 Laravel 핵심 분석 예외 처리(코드)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
이 기사는 segmentfault에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제
마지막 Laravel 버전 : 마이그레이션 튜토리얼마지막 Laravel 버전 : 마이그레이션 튜토리얼May 14, 2025 am 12:17 AM

Laravel의 마이그레이션 시스템은 최신 버전에서 제공하는 새로운 기능과 모범 사례는 무엇입니까? 1. 다형성 관계를 위해 nullableMorphs ()를 추가했습니다. 2. 열 순서를 지정하기 위해 후 () 메소드가 도입됩니다. 3. 고아 기록을 피하기 위해 외국 주요 제약 조건 처리를 강조합니다. 4. 인덱스 추가와 같은 성능을 최적화하는 것이 좋습니다. 5. 마이그레이션의 Idempotence와 설명 이름의 사용을 옹호합니다.

Laravel의 최신 LTS 버전은 무엇입니까?Laravel의 최신 LTS 버전은 무엇입니까?May 14, 2025 am 12:14 AM

LARAVEL10, RELEASEFOURED2023, ISTHELATESTLTSVERSION, ISTHELATESTLTSION.ITREQUIRESPHP8.1, EnhancesLaravelPennantForFeatureFlags, 개선 된 서류 핸들링, 정제 문서화 및 특히 인출 된 영역을 최적화합니다.

계속 업데이트 : 최신 Laravel 버전의 최신 기능계속 업데이트 : 최신 Laravel 버전의 최신 기능May 14, 2025 am 12:10 AM

Laravel의 최신 버전은 여러 가지 새로운 기능을 소개합니다. 1. Laravelpennant는 기능 플래그를 관리하는 데 사용되므로 새로운 기능을 단계적으로 릴리스 할 수 있습니다. 2. Laravelreverb는 실시간 주석과 같은 실시간 기능의 구현을 단순화합니다. 3. Larravelvite는 프론트 엔드 구성 과정을 가속화합니다. 4. 새로운 모델 팩토리 시스템은 테스트 데이터 생성을 향상시킵니다. 5. 오류 처리 메커니즘을 향상시키고보다 유연한 오류 페이지 사용자 정의 옵션을 제공합니다.

Laravel에서 Soft Delete 구현 : 단계별 자습서Laravel에서 Soft Delete 구현 : 단계별 자습서May 14, 2025 am 12:02 AM

SoftLeTeInelelaveliSling -Memptry -BraceChortsDevetus -teeedecetovedlyDevelEdTeeCetteEcedElave

현재 Laravel 버전 : 최신 릴리스 및 업데이트를 확인하십시오현재 Laravel 버전 : 최신 릴리스 및 업데이트를 확인하십시오May 14, 2025 am 12:01 AM

laravel10.xisthecurrentversion, newfeatures firempportineloquentmodelsandimprovedroutemodelbindingwithenums.

Laravel 마이그레이션 사용 방법 : 단계별 자습서Laravel 마이그레이션 사용 방법 : 단계별 자습서May 13, 2025 am 12:15 AM

laravelmigrationsStreamlinedatabasemanumangemanagementBeallowingschemachangestobedefinphpcode, thancanbeversion-controlledandshared. here'showtousem : 1) createMigrationClassEStodeFineOperationsLikecreatingmodifyingtables.2) USETE'PHPARTISANGUPS'COMMA

최신 Laravel 버전 찾기 : 빠르고 쉬운 가이드최신 Laravel 버전 찾기 : 빠르고 쉬운 가이드May 13, 2025 am 12:13 AM

Laravel의 최신 버전을 찾으려면 공식 웹 사이트 Laravel.com을 방문하여 오른쪽 상단의 "문서"버튼을 클릭하거나 작곡가 명령 "Composershowlaravel/Framework | grepversions"를 사용할 수 있습니다. 업데이트를 유지하면 프로젝트 보안 및 성능을 향상시키는 데 도움이 될 수 있지만 기존 프로젝트에 미치는 영향을 고려해야합니다.

Laravel으로 업데이트 상태 : 최신 버전 사용의 이점Laravel으로 업데이트 상태 : 최신 버전 사용의 이점May 13, 2025 am 12:08 AM

당신은 당신의 youshouldupdateThelateStlarViversorperferferferferferferferferferferferformanceimprovements, EnhancedSecurity, NewFeatures, BetterCommunitySupport, andlong-Termmainsupport.1) 성능 : laravel9'seloquentormoptimizationsenhanceplicationspeed.2) 보안 : Laravel8introducedBetter

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

VSCode Windows 64비트 다운로드

VSCode Windows 64비트 다운로드

Microsoft에서 출시한 강력한 무료 IDE 편집기

PhpStorm 맥 버전

PhpStorm 맥 버전

최신(2018.2.1) 전문 PHP 통합 개발 도구

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

안전한 시험 브라우저

안전한 시험 브라우저

안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.