Menu

PHP İstisnalar: throw ve Özel İstisna Sınıfları

PHP'de bir istisnayı throw new Exception('message'); ile fırlatırsınız ve çağıran onu bir catch bloğunda $e->getMessage() ile okur. Yerleşik istisna sınıflarını, özel istisnalar yazmayı, getCode(), getLine() ve getPrevious() metotlarını, bir ifade olarak throw kullanımını ve PHP'nin kendisinin fırlattığı ValueError ve TypeError gibi hataları öğrenin.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

PHP'de bir istisnayı throw new Exception('message'); ile fırlatırsınız. Çalışma o satırda durur ve istisnanın türünü kabul eden en yakın catch bloğuna atlar; orada $e->getMessage() mesajı döndürür. Çağıranların sorunları ayırt edebilmesi için InvalidArgumentException gibi belirli bir sınıf kullanın.

Bir istisna bir nesnedir. throw onu çağrı yığınında eşleşen bir catch bloğuna sahip ilk çağırana kadar yukarı iletir ve ne yapılacağına o çağıran karar verir; sorunu bulan fonksiyonun bunu bilmesi gerekmez. Yakalamanın işleyişi, finally ve birkaç türü yakalamak try catch sayfasında.

Bir istisna nesnesi neler içerir

Her istisna bir mesaj, bir tam sayı kodu, oluşturulduğu dosya ve satır ve bir yığın izi taşır. Yapıcı, hepsi isteğe bağlı olan ($message, $code, $previous) argümanlarını alır:

getLine() catch satırı değil, throw new satırıdır. İz oraya götüren çağrıları listeler (#0 /home/index.php(8): findOrder()); bu, bir hata bir logda göründüğünde genellikle ilk okunacak şeydir. İstisnayı bir dizgeye çevirmek (echo $e; veya (string) $e) hepsini PHP'nin standart biçiminde yazdırır.

Yerleşik istisna sınıfları

PHP, Standart PHP Kütüphanesinde (SPL) bir istisna sınıfları ailesiyle gelir. Sorunu adlandıran sınıfı fırlatmak kodunuzu daha okunur yapar ve çağıranların dar bir şekilde yakalamasını sağlar. Bunların hepsi Exception sınıfını genişletir:

SınıfNe zaman fırlatılır
InvalidArgumentExceptionbir argümanın biçimi yanlış: boş bir ad, bilinmeyen bir seçenek
DomainExceptionbir değer anlamlı kümenin dışında: negatif bir fiyat
OutOfRangeExceptionkod asla var olamayacak bir indeks istedi (çağıranda bir bug)
OutOfBoundsExceptionyalnızca çalışma zamanında bilinen verilerde bir anahtar veya indeks eksik
RangeExceptionhesaplanan bir sonuç çalışırken geçerli aralığın dışına düşüyor
LengthExceptionbir şey çok uzun veya çok kısa
RuntimeExceptionyalnızca çalışırken tespit edilebilen bir sorun: dolu bir disk, bir zaman aşımı
UnexpectedValueExceptionbir fonksiyon beklemediğiniz türde bir değer döndürdü veya aldı
LogicExceptionkodun kendisi yanlış, hatalı girdi değil bir bug
JsonExceptionJSON_THROW_ON_ERROR ile json_encode()/json_decode() tarafından fırlatılır

InvalidArgumentException, DomainException, LengthException ve OutOfRangeException LogicException sınıfını genişletir; OutOfBoundsException, RangeException ve UnexpectedValueException ise RuntimeException sınıfını genişletir. Herhangi bir sınıfın üst sınıflarını kendiniz kontrol edebilirsiniz:

TypeError sınıfının üst sınıfı Exception değil Error sınıfıdır: aşağıdaki ikinci aileye aittir.

PHP'nin kendisinin fırlattığı hatalar

PHP 7'den beri, PHP 8'den beri ise çok daha fazla, PHP'nin kendi fonksiyonları ve operatörleri eskiden uyarı olan sorunlar için Error alt sınıfları fırlatır. Onları aynı şekilde yakalarsınız, ama catch (Exception $e) onlarla eşleşmez:

DivisionByZeroError, TypeError, ValueError, ArgumentCountError, UnhandledMatchError ve düz Error hepsi Error sınıfını genişletir. Her biri hatalı veriden çok çağıran koddaki bir bug'ı işaret eder; Exception ağacının dışında yaşamalarının nedeni budur. str_repeat(5, 2) ifadesini bir TypeError yapan declare(strict_types=1) satırıdır; o olmadan PHP 5 değerini "5" değerine çevirirdi.

Özel bir istisna sınıfı yazma

Çoğu zaman tek satırlık bir alt sınıf yeterlidir: sınıf adının kendisi anlamı taşır ve çağıranlar tam olarak o türü yakalayabilir. Yakalayanın veriye (hangi sipariş, hangi tutar) ihtiyacı olduğunda özellikler ekleyin ve mesajı parent::__construct() ile yukarı iletin:

Üst sınıfı dikkatle seçin: (düz Exception yerine) RuntimeException sınıfını genişletmek, RuntimeException yakalayan kodun sizinkini de ele alması demektir. Küçük bir hiyerarşi, yani altında belirli alt sınıflar olan kütüphane veya modül başına bir temel istisna, çağıranların "ödemelerden gelen her şeyi yakala" ile "yalnızca bu durumu yakala" arasında seçim yapmasını sağlar.

previous ile istisnaları zincirleme

Düşük seviyeli bir istisnayı yakalayıp daha üst seviyeli bir istisna fırlattığınızda orijinali üçüncü argüman olarak verin. Hiçbir şey kaybolmaz: getPrevious() kök nedene kadar geri gider.

Kullanıcı "customers.csv could not be imported" görür; zinciri izleyen log ise "row 2 has 2 columns" bilgisini de alır. Zincirlenmiş bir istisna hiç yakalanmazsa PHP'nin ölümcül hatası zincirin tamamını yazdırır: önce orijinal neden, sonra her sarmalayıcı bir Next satırının altında.

Bir ifade olarak throw

PHP 8.0'dan beri throw bir ifadedir, bu yüzden bir değer beklenen her yerde durabilir: ?? sonrasında, bir üçlü ifadede, bir ok fonksiyonunda. "Bunu al ya da başarısız ol" işlemini tek satır yapar:

Ne zaman fırlatmamalı

İstisnalar mevcut fonksiyonun ele alamadığı ve normal akışın beklemediği durumlar içindir. Hiçbir şey bulamayan bir arama, boş olan isteğe bağlı bir alan veya giriş yapmamış bir kullanıcı sıradan sonuçlardır: null, false veya boş bir dizi döndürün ve çağıranın kontrol etmesine izin verin; istisnaları devam etmenin yanlış olacağı durumlara saklayın.

İki alışkanlık daha istisna kodunu okunur tutar: bir istisnayı asla yalnızca yok saymak için yakalamayın (boş bir catch (Exception $e) {} bir sonraki gerçek bug'ı gizler) ve çıplak Exception yerine belirli sınıflar fırlatın, böylece bir çağıran tek bir durumu ele almak için asla her şeyi yakalamak zorunda kalmaz.

Sıkça Sorulan Sorular

PHP'de nasıl istisna fırlatırım?

Bir istisna nesnesi oluşturun ve fırlatın: throw new InvalidArgumentException('Quantity must be positive');. Çalışma o satırda durur ve eşleşen en yakın catch bloğuna atlar; yoksa betik bir "Uncaught" ölümcül hatasıyla biter.

PHP'de özel bir istisna nasıl oluştururum?

Exception sınıfını veya alt sınıflarından birini genişletin: class PaymentFailedException extends RuntimeException {}. Onu kendi türüyle fırlatmak ve yakalamak için bu tek satır yeterlidir. Yakalayanın ek veriye ihtiyacı olduğunda özellikler ve bir yapıcı ekleyin ve parent::__construct($message, $code, $previous) çağırın.

getMessage ile getCode arasındaki fark nedir?

getMessage() ilk yapıcı argümanı olarak verilen, insanlar ve loglar için olan metni döndürür. getCode() ikinci argüman olarak verilen tam sayıyı (varsayılan 0) döndürür; hataları HTTP durum kodlarına eşlemek gibi makine kontrolleri için kullanışlıdır.

PHP'de hangi istisnayı fırlatmalıyım?

Soruna uyan yerleşik bir SPL sınıfı kullanın: hatalı bir argüman için InvalidArgumentException, izin verilenin dışındaki bir değer için DomainException, yalnızca çalışma zamanında görülen başarısızlıklar (dolu bir disk, bir zaman aşımı) için RuntimeException, programlama hataları için LogicException. Çağıranlarınızın ayırt etmesi gereken hatalar için kendi alt sınıfınızı oluşturun.

PHP'de istisna zincirleme nedir?

Yeni bir istisna fırlatırken orijinal istisnayı üçüncü yapıcı argümanı olarak vermektir: throw new ImportException('Import failed', 0, $e);. Yeni istisna bağlam verir ve onun üzerindeki $e->getPrevious() orijinal nedeni döndürür, böylece hiçbir ayrıntı kaybolmaz.

Coddy programlama dilleri çizimi

Coddy ile kodlamayı öğren

BAŞLA