throw,try,catchvefinallyile istisna fırlatmak ve yakalamakThrowable,ExceptionveErrorhiyerarşisini açıklamak ve özel bir istisna yazmak- Hata raporlamayı geliştirme ve canlı ortam için doğru yapılandırmak
Ödeme sistemi yanıt vermiyor, kullanıcı bozuk bir JSON göndermiş, veritabanına ulaşılamıyor... Gerçek bir sitede bu tür durumlar her gün yaşanır. İyi bir program “beyaz ekran” göstermez: sorunu yakalar, kullanıcıya anlaşılır bir mesaj verir, ayrıntıları ise günlüğe (log) yazar. PHP'de bunun temel aracı istisnalardır (exceptions).
try, catch ve finally
Kod bir sorun fark ettiğinde throw ile bir istisna fırlatır: fonksiyon hemen durur ve istisna, onu yakalayan bir catch bloğu bulana kadar çağrı zinciri boyunca yukarı çıkar. Riskli kod try bloğuna yazılır, catch belirli türdeki bir istisnayı yakalar, finally ise her durumda, istisna olsa da olmasa da çalışır.
<?php
function divide(int $a, int $b): float
{
if ($b === 0) {
throw new InvalidArgumentException("Cannot divide by zero");
}
return $a / $b;
}
foreach ([4, 0] as $b) {
try {
$result = divide(12, $b);
echo "12 / $b = $result\n";
} catch (InvalidArgumentException $e) {
echo "Error: ", $e->getMessage(), "\n";
} finally {
echo "-- done with $b\n";
}
}12 / 4 = 3 -- done with 4 Error: Cannot divide by zero -- done with 0
$b = 0 olduğunda echo satırı hiç çalışmadı: throw'dan sonra kontrol doğrudan catch'e geçti. finally ise döngünün iki turunda da çalıştı. İstisna nesnesinin kullanışlı metotları: getMessage() mesajı, getCode() kodu, getFile() ve getLine() hatanın yerini, getPrevious() ise önceki istisnayı verir.
Exception ve Error
PHP 7'den beri fırlatılabilen her şeyin ortak atası Throwable arayüzüdür. Ondan iki kol ayrılır: **Exception, programın kendi mantığındaki sorunlar (hatalı argüman, bulunamayan dosya, başarısız veritabanı bağlantısı); Error** ise PHP'nin iç hataları (yanlış tür, sıfıra bölme, var olmayan bir metodun çağrılması).
| Kol | Sık görülen sınıflar | Ne zaman |
|---|---|---|
Exception | InvalidArgumentException, RuntimeException, JsonException, PDOException | beklenen sorunlar: yakalanıp ele alınabilir |
Error | TypeError, ValueError, DivisionByZeroError, ArgumentCountError, UnhandledMatchError | genellikle koddaki bir hata: düzeltilmesi gerekir |
<?php
$tests = [
fn() => intdiv(10, 0),
fn() => json_decode("{bad json", flags: JSON_THROW_ON_ERROR),
fn() => throw new RuntimeException("Disk is full"),
];
foreach ($tests as $test) {
try {
$test();
} catch (Throwable $e) {
echo get_class($e), ": ", $e->getMessage(), "\n";
}
}DivisionByZeroError: Division by zero JsonException: Syntax error RuntimeException: Disk is full
Kendi istisnaların
Kendi istisna sınıfını oluşturmak için mevcut bir sınıftan, genellikle RuntimeException ya da DomainException'dan türet. Adı sorunu açıkça anlatsın; gerekirse ek bilgiyi bir özellikte sakla. Böylece catch bloğu tam olarak bu duruma kesin bir tepki verebilir.
<?php
class InsufficientFundsException extends RuntimeException
{
public function __construct(public readonly float $missing)
{
parent::__construct("Not enough money: missing $missing AZN");
}
}
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;
echo "Paid $amount, left {$this->balance}\n";
}
}
$wallet = new Wallet(30);
try {
$wallet->pay(12);
$wallet->pay(25.5);
$wallet->pay(1);
} catch (InsufficientFundsException $e) {
echo $e->getMessage(), "\n";
echo "Top up at least ", ceil($e->missing), " AZN\n";
}Paid 12, left 18 Not enough money: missing 7.5 AZN Top up at least 8 AZN
$data = json_decode($input);
if ($data === null) {
// broken JSON or the value null?
echo json_last_error_msg();
}try {
$data = json_decode($input, flags: JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
echo "Invalid JSON: ", $e->getMessage();
}null hem bir hata hem de geçerli bir JSON değeri (null) anlamına gelebilir. İstisna ise hatayı kesin biçimde bildirir.Uyarılar ve hata raporlama
Bazı sorunlar istisna fırlatmaz, yalnızca uyarı verir: örneğin var olmayan bir değişken Warning: Undefined variable $x, kullanımdan kalkmış bir fonksiyon ise Deprecated mesajı üretir. Hangi mesajların görüneceğini php.ini ayarları belirler. Altın kural: geliştirme sırasında her şeyi gör; canlı ortamda (production) ise kullanıcıya hiçbir şey gösterme ve her şeyi günlüğe yaz.
Ayar (php.ini) | Geliştirme | Canlı ortam |
|---|---|---|
error_reporting | E_ALL | E_ALL |
display_errors | On | Off |
log_errors | On | On |
error_reporting(E_ALL); ini_set('display_errors', '1');Önemli noktalar
throwbir istisna fırlatır;tryriskli kodu içerir,catchbelirli bir türü yakalar,finallyise her zaman çalışır.Throwable'ın iki kolu vardır:Exception(beklenen sorunlar) veError(PHP'nin iç hataları).- Kendi istisnanı mevcut bir sınıftan türet ve anlamlı bir ad ver; ek bilgiyi bir özellikte sakla.
- PHP 8'de
throwbir ifadedir:$x = $arr[$k] ?? throw new ...; - Geliştirmede
display_errors = On, canlı ortamda iseOffvelog_errors = Onolmalıdır.
Kendini test et
10 soru. Her doğru cevap XP kazandırır.
finally bloğu ne zaman çalışır?