Menu
Coddy logo textTech

Özel İstisna Hiyerarşisi

Coddy'nin PHP Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 67 / 91.

PHP'nin yerleşik istisna sınıfları yaygın senaryoları kapsasa da, gerçek uygulamalar genellikle daha spesifik hata türlerine ihtiyaç duyar. Bir özel istisna hiyerarşisi oluşturmak, alanınıza (domain) uygun istisnalar tanımlamanıza ve bunları farklı özgünlük seviyelerinde yakalamanıza olanak tanır.

Özel bir istisna oluşturmak için, Exception sınıfını veya onun alt sınıflarından birini genişletmeniz yeterlidir:

<?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 sınıfının doğrudan Exception sınıfını değil, PaymentException sınıfını nasıl genişlettiğine dikkat edin. Bu, tüm ödeme ile ilgili istisnaları tek bir catch bloğu ile yakalayabileceğiniz veya belirli olanları tek tek ele alabileceğiniz bir hiyerarşi oluşturur.

Özel istisnalar (custom exceptions), hatayla ilgili ek özellikler ve yöntemler içerebilir. Burada, getShortfall() genel bir istisnanın sunamayacağı yararlı bilgiler sağlar:

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

İyi tasarlanmış bir istisna hiyerarşisi, kodunuzu daha sürdürülebilir hale getirir. İstisnaları yakalarken, gerektiği kadar genel veya spesifik olabilirsiniz ve istisna nesnelerinin kendileri, neyin yanlış gittiğine dair anlamlı bir bağlam taşır.

challenge icon

Görev

Kolay

Farklı türdeki sipariş hatalarını işleyen özel bir istisna (exception) hiyerarşisine sahip bir sipariş işleme sistemi oluşturalım. Hata ayıklamayı daha kesin ve bilgilendirici hale getiren, neyin yanlış gittiğine dair anlamlı bağlam taşıyan istisnalar oluşturacaksınız.

Kodunuzu dört dosya halinde düzenleyeceksiniz:

  • OrderException.phpException sınıfını genişleten temel bir OrderException sınıfı oluşturun. Bu, siparişle ilgili tüm istisnalar için ebeveyn görevi görür ve gerektiğinde tek bir catch bloğu ile herhangi bir sipariş sorununu yakalamanıza olanak tanır.
  • OutOfStockException.phpOrderException sınıfını genişleten bir OutOfStockException sınıfı oluşturun. Bu istisna, yapıcı metodunda (constructor) bir ürün adı ve talep edilen miktarı kabul etmelidir. Bu özel (private) özellikler için constructor promotion kullanın. Ebeveyn yapıcıyı "[productName] is out of stock (requested: [quantity])" formatında bir mesajla çağırın. Ürün adını döndüren bir getProductName(): string metodu ekleyin.
  • InvalidQuantityException.phpOrderException sınıfını genişleten bir InvalidQuantityException sınıfı oluşturun. Bu istisna, constructor promotion kullanarak özel bir özellik olarak bir miktar değerini yapıcı metodunda kabul etmelidir. Ebeveyn yapıcıyı "Invalid quantity: [quantity]" mesajıyla çağırın. Miktar değerini döndüren bir getQuantity(): int metodu ekleyin.
  • main.php — Her üç istisna dosyasını da dahil edin. İki girdi alacaksınız: bir ürün adı ve bir miktar (tam sayıya dönüştürülmesi gereken bir dize olarak).

    Miktar değerine bağlı olarak uygun istisnayı fırlatın:

    • Eğer miktar 1'den küçükse, bir InvalidQuantityException fırlatın
    • Eğer miktar 100'den büyükse, bir OutOfStockException fırlatın (yetersiz stoğu simüle ederek)
    • Aksi takdirde, "Order placed: [quantity]x [productName]" yazdırın

    İstisnaları hiyerarşiyi kullanarak yakalayın. Önce InvalidQuantityException istisnasını yakalayın ve istisnanın mesajını ve getQuantity() metodunu kullanarak "Quantity error: [message] (value: [quantity])" yazdırın. Ardından OutOfStockException istisnasını yakalayın ve istisnanın mesajını ve getProductName() metodunu kullanarak "Stock error: [message] (product: [productName])" yazdırın.

Bu hiyerarşi, temel OrderException sınıfı aracılığıyla siparişle ilgili tüm sorunları yakalama seçeneğine sahip olmaya devam ederken, belirli istisnaları ayrı ayrı yönetmenize olanak tanır. Her istisna üzerindeki özel metodlar, genel bir istisnanın sunamayacağı bağlamı sağlar.

Kopya kağıdı

Exception sınıfını veya onun alt sınıflarını genişleterek özel istisnalar (custom exceptions) oluşturun:

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

Özel istisnalar, diğer özel istisnaları genişleterek bir hiyerarşi oluşturabilir. Bu, istisnaları farklı özgünlük seviyelerinde yakalamanıza olanak tanır; ödeme ile ilgili tüm istisnaları PaymentException ile yakalayabilir veya InsufficientFundsException gibi belirli olanları ayrı ayrı ele alabilirsiniz.

Özel istisnalar, hata hakkında bağlam sağlamak için ek özellikler ve yöntemler içerebilir:

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

Özellikleri doğrudan yapıcı (constructor) parametrelerinde tanımlamak için "constructor promotion" özelliğini kullanın. İstisna mesajını ayarlamak için parent::__construct() metodunu çağırın.

Kendin dene

<?php
// Tüm istisna dosyalarını dahil et
require_once 'OrderException.php';
require_once 'OutOfStockException.php';
require_once 'InvalidQuantityException.php';

// Girdiyi oku
$productName = trim(fgets(STDIN));
$quantity = intval(trim(fgets(STDIN)));

// TODO: Sipariş işlemini yönetmek için try-catch kullanın
// try bloğu içinde:
//   - Eğer miktar < 1 ise, InvalidQuantityException fırlatın
//   - Eğer miktar > 100 ise, OutOfStockException fırlatın
//   - Aksi takdirde, "Order placed: [quantity]x [productName]" yazdırın
//
// Önce InvalidQuantityException'ı yakalayın:
//   - getMessage() ve getQuantity() kullanarak "Quantity error: [message] (value: [quantity])" yazdırın
//
// OutOfStockException'ı yakalayın:
//   - getMessage() ve getProductName() kullanarak "Stock error: [message] (product: [productName])" yazdırın

?>
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler