사용자 지정 예외 계층 구조
Coddy PHP 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 91개 중 67번째.
PHP의 내장 exception 클래스가 일반적인 상황을 다루기는 하지만, 실제 애플리케이션에는 더 구체적인 error 유형이 필요한 경우가 많습니다. custom exception 계층 구조를 만들면 도메인에 맞는 exception을 정의하고 서로 다른 수준의 구체성으로 이를 catch할 수 있습니다.
사용자 지정 예외를 만들려면 Exception 클래스 또는 그 하위 클래스 중 하나를 간단히 확장하면 됩니다:
<?php
class PaymentException extends Exception {}
class InsufficientFundsException extends PaymentException {
public function __construct(
private float $required,
private float $available
) {
parent::__construct("Need $required but only $available available");
}
public function getShortfall(): float {
return $this->required - $this->available;
}
}
InsufficientFundsException이 Exception을 직접 확장하는 것이 아니라 PaymentException을 확장한다는 점에 주목하세요. 이렇게 하면 하나의 catch 블록으로 결제와 관련된 모든 예외를 포착하거나, 특정 예외를 개별적으로 처리할 수 있는 계층 구조가 만들어집니다.
사용자 지정 예외에는 오류와 관련된 추가 속성과 메서드를 포함할 수 있습니다. 여기서 getShortfall()은 일반 예외로는 제공할 수 없는 유용한 정보를 제공합니다.
<?php
class Wallet {
public function __construct(private float $balance) {}
public function pay(float $amount): void {
if ($amount > $this->balance) {
throw new InsufficientFundsException($amount, $this->balance);
}
$this->balance -= $amount;
}
}
잘 설계된 예외 계층 구조는 코드를 더욱 유지 관리하기 쉽게 만듭니다. 예외를 포착할 때 필요에 따라 포괄적으로 처리하거나 구체적으로 처리할 수 있으며, 예외 객체 자체에 무엇이 잘못되었는지에 대한 의미 있는 맥락이 담겨 있습니다.
챌린지
쉬움다양한 유형의 주문 실패를 처리하는 사용자 지정 예외 계층 구조를 사용하여 주문 처리 시스템을 만들어 보겠습니다. 무엇이 잘못되었는지에 대한 의미 있는 컨텍스트를 전달하는 예외를 만들어 오류 처리를 더 정확하고 유용하게 만들 수 있습니다.
코드는 네 개의 파일로 구성합니다.
OrderException.php:Exception을 확장하는 기본OrderExceptionclass를 Create합니다. 이 class는 모든 주문 관련 예외의 parent 역할을 하므로, 필요할 때 하나의 catch block으로 모든 주문 문제를 처리할 수 있습니다.OutOfStockException.php:OrderException을 확장하는OutOfStockExceptionclass를 Create합니다. 이 exception은 constructor에서 product name과 요청된 quantity를 받아야 합니다. 이러한 private 속성에는 constructor promotion을 사용합니다. parent constructor를"[productName] is out of stock (requested: [quantity])"형식의 message와 함께 호출합니다. product name을 반환하는getProductName(): stringmethod를 Add합니다.InvalidQuantityException.php:OrderException을 확장하는InvalidQuantityExceptionclass를 Create합니다. 이 exception은 constructor promotion을 private 속성으로 사용하여 constructor에서 quantity 값을 받아야 합니다. parent constructor를"Invalid quantity: [quantity]"message와 함께 호출합니다. quantity 값을 반환하는getQuantity(): intmethod를 Add합니다.main.php: 세 exception 파일을 모두 Include합니다. 두 개의 입력, 즉 product name과 quantity(정수로 변환해야 하는 string)를 받습니다.quantity 값에 따라 적절한 exception을 throw합니다.
- quantity가 1보다 작으면
InvalidQuantityException을 throw합니다. - quantity가 100보다 크면
OutOfStockException을 throw합니다(재고 부족을 시뮬레이션). - Otherwise,
"Order placed: [quantity]x [productName]"를 출력합니다.
계층 구조를 사용하여 exception을 catch합니다. 먼저
InvalidQuantityException을 catch하고, exception의 message와getQuantity()method를 사용하여"Quantity error: [message] (value: [quantity])"를 출력합니다. 그런 다음OutOfStockException을 catch하고, exception의 message와getProductName()method를 사용하여"Stock error: [message] (product: [productName])"를 출력합니다.- quantity가 1보다 작으면
이 계층 구조를 사용하면 특정 exception을 개별적으로 처리하면서도 기본 OrderException class를 통해 모든 주문 관련 문제를 catch할 수 있습니다. 각 exception의 사용자 지정 method는 일반 exception으로는 제공할 수 없는 컨텍스트를 제공합니다.
직접 해보기
<?php
// 모든 예외 파일 포함
require_once 'OrderException.php';
require_once 'OutOfStockException.php';
require_once 'InvalidQuantityException.php';
// 입력 읽기
$productName = trim(fgets(STDIN));
$quantity = intval(trim(fgets(STDIN)));
// TODO: try-catch를 사용하여 주문 처리하기
// try 블록 내부:
// - quantity < 1이면 InvalidQuantityException을 throw
// - quantity > 100이면 OutOfStockException을 throw
// - 그렇지 않으면 "Order placed: [quantity]x [productName]" 출력
//
// 먼저 InvalidQuantityException을 catch:
// - getMessage()와 getQuantity()를 사용하여 "Quantity error: [message] (value: [quantity])" 출력
//
// OutOfStockException을 catch:
// - getMessage()와 getProductName()을 사용하여 "Stock error: [message] (product: [productName])" 출력
?>이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 PHP 컴파일러