라라벨의 모든 예외(Exception)들은 별도의 catch 블록을 사용하지 않는 경우 App\Exceptions\Handler 클래스에 의해 로그를 남기고 사용자에게 응답을 보여주도록 되어있다.
또한 별도의 Exception Class 를 생성하여 report(), render() 메소드를 통해 핸들링을 할수 있도록 지원하고 있으며 해당 글에서는 별도의 예외클래스를 생성하여 에러를 핸들링하는 예제에 대해 소개하고자 한다.
Exception Class 생성하기
Exception Class 의 생성은 라라벨에서 제공하는 artisan 커맨드를 통해 생성하는 방법과 직접 파일을 추가하는 방법이 있다. artisan 커맨드를 이용할 경우 app\Exception 경로에 클래스가 생성되며, 반드시 해당 네임스페이스가 아니어도 상관없다.
root@fbb55136d2a1:/var/www/tailerbox# artisan make:exception ValidateException
Exception created successfully.
위와 같이 artisan 명령어를 사용하면 app\Exception 네임스페이스에 ValidateException 클래스가 생성이 되는 것을 확인할 수 있다. artisan 명령어를 사용하지 않고 직접 생성하는 경우 해당 네임스페이스를 사용하지 않아도 무방하지만 Exception Class 를 상속받아야 한다.
<?php
namespace App\Exceptions;
use Exception;
class ValidateException extends Exception
{
//
}
상기와 같이 생성된 클래스에 로그 및 응답결과를 반환하기 위한 메소드를 추가 해보자.
<?php
namespace App\Exceptions;
use Exception;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Validator;
use Symfony\Component\HttpFoundation\Response;
class ValidateException extends Exception
{
/**
* @var \Illuminate\Support\MessageBag $messageBag
*/
public $messageBag;
/**
* @param Validator $validator
*/
public function __construct(Validator $validator)
{
$this->messageBag = $validator->getMessageBag();
parent::__construct($this->messageBag->first(), Response::HTTP_UNPROCESSABLE_ENTITY);
}
public function report()
{
Log::error(
sprintf("%s::%s", __CLASS__, $this->messageBag->first()),
$this->messageBag->messages()
);
}
public function render()
{
return \response([
'errors' => $this->messageBag->all()
], Response::HTTP_UNPROCESSABLE_ENTITY);
}
}
예외가 발생하는 경우 해당 클래스에 선언된 report() 메소드가 실행되고, 응답을 반환하기 위한 render() 메소드가 순차적으로 실행된다.
해당 예외의 경우 예외가 발생할 때 Validator 의 인스턴스를 주입받아 유효성 검증에 실패한 인자의 필드 및 메시지를 로그에 남기고 render() 메소드를 통해 Response Body 및 Status 를 반환한다.
※ 주의할 점
아래와 같이 예외발생 구문에 try {...} catch (Throwable $e) {...} 이 존재하고 try block 내에서 예외를 던지는 경우 report/render 메소드가 아닌 catch 블록에 명시된 코드에 의해 예외가 핸들링 된다.
try {
if ($validator->fails()) {
throw new ValidateException($validator);
}
} catch (Throwable $e) {
if ($e instanceof ValidateException) {
/* report/render 메소드가 실행되지 않음. */
}
}
'Framework > Laravel' 카테고리의 다른 글
[Laravel] i18n 국제화 적용하기 (0) | 2021.11.19 |
---|---|
[Laravel] 라우팅 정책 변경하기 (API 를 도메인 기반으로) (0) | 2021.11.18 |
[Laravel] 설치하기 (0) | 2021.11.18 |