Menu
Coddy logo textTech

Hierarquia de Exceções Personalizada

Parte da seção Programação Orientada a Objetos do Journey de PHP da Coddy. Lição 67 de 91.

Embora as classes de exceção integradas do PHP cubram cenários comuns, aplicações reais geralmente precisam de tipos de erro mais específicos. Criar uma hierarquia de exceções personalizadas permite definir exceções que correspondam ao seu domínio e capturá-las em diferentes níveis de especificidade.

Para criar uma exceção personalizada, basta estender a classe Exception ou uma de suas subclasses:

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

Observe como InsufficientFundsException estende PaymentException, e não Exception diretamente. Isso cria uma hierarquia na qual você pode capturar todas as exceções relacionadas a pagamentos com um único bloco catch ou tratar exceções específicas individualmente.

Exceções personalizadas podem incluir propriedades e métodos adicionais relevantes para o erro. Aqui, getShortfall() fornece informações úteis que uma exceção genérica não poderia oferecer:

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

Uma hierarquia de exceções bem projetada torna seu código mais fácil de manter. Ao capturar exceções, você pode ser tão abrangente ou específico quanto necessário, e os próprios objetos de exceção carregam um contexto significativo sobre o que deu errado.

challenge icon

Desafio

Fácil

Vamos criar um sistema de processamento de pedidos com uma hierarquia personalizada de exceções que trata diferentes tipos de falhas de pedidos. Você criará exceções que carregam um contexto significativo sobre o que deu errado, tornando o tratamento de erros mais preciso e informativo.

Você organizará seu código em quatro arquivos:

  • OrderException.php: Crie uma classe base OrderException que estenda Exception. Ela servirá como classe pai para todas as exceções relacionadas a pedidos, permitindo capturar qualquer problema de pedido com um único bloco catch quando necessário.
  • OutOfStockException.php: Crie uma classe OutOfStockException que estenda OrderException. Essa exceção deve aceitar um nome de produto e a quantidade solicitada em seu construtor. Use a promoção de construtor para essas propriedades privadas. Chame o construtor da classe pai com uma mensagem no formato "[productName] is out of stock (requested: [quantity])". Adicione um método getProductName(): string que retorne o nome do produto.
  • InvalidQuantityException.php: Crie uma classe InvalidQuantityException que estenda OrderException. Essa exceção deve aceitar um valor de quantidade em seu construtor, usando a promoção de construtor como uma propriedade privada. Chame o construtor da classe pai com a mensagem "Invalid quantity: [quantity]". Adicione um método getQuantity(): int que retorne o valor da quantidade.
  • main.php: Inclua os três arquivos de exceção. Você receberá duas entradas: um nome de produto e uma quantidade (como uma string que precisa ser convertida em um inteiro).

    Com base no valor da quantidade, lance a exceção apropriada:

    • Se a quantidade for menor que 1, lance uma InvalidQuantityException
    • Se a quantidade for maior que 100, lance uma OutOfStockException (simulando estoque insuficiente)
    • Caso contrário, imprima "Order placed: [quantity]x [productName]"

    Capture as exceções usando a hierarquia. Primeiro, capture InvalidQuantityException e imprima "Quantity error: [message] (value: [quantity])" usando a mensagem da exceção e o método getQuantity(). Em seguida, capture OutOfStockException e imprima "Stock error: [message] (product: [productName])" usando a mensagem da exceção e o método getProductName().

Essa hierarquia permite tratar exceções específicas individualmente e, ao mesmo tempo, manter a opção de capturar todos os problemas relacionados a pedidos por meio da classe base OrderException. Os métodos personalizados de cada exceção fornecem um contexto que uma exceção genérica não poderia oferecer.

Experimente você mesmo

<?php
// Inclua todos os arquivos de exceção
require_once 'OrderException.php';
require_once 'OutOfStockException.php';
require_once 'InvalidQuantityException.php';

// Leia a entrada
$productName = trim(fgets(STDIN));
$quantity = intval(trim(fgets(STDIN)));

// TODO: Use try-catch para lidar com o processamento do pedido
// Dentro do bloco try:
//   - Se quantity < 1, throw InvalidQuantityException
//   - Se quantity > 100, throw OutOfStockException
//   - Caso contrário, print "Order placed: [quantity]x [productName]"
//
// Catch InvalidQuantityException primeiro:
//   - Print "Quantity error: [message] (value: [quantity])" usando getMessage() e getQuantity()
//
// Catch OutOfStockException:
//   - Print "Stock error: [message] (product: [productName])" usando getMessage() e getProductName()

?>
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de PHP online