Məzmuna keç
Educora
Orta17 dəq8 / 10

İstisnalar və xətaların idarə olunması

try/catch/finally ilə xətaları tut, Exception və Error iyerarxiyasını anla, öz istisna sinfini yarat və xəta hesabatını inkişaf və istehsal mühitləri üçün düzgün qur.

Özünü yoxla
Bu dərsdə öyrənəcəksən
  • throw, try, catch və finally ilə istisnaları atmaq və tutmaq
  • Throwable, Exception və Error iyerarxiyasını izah etmək və öz istisna sinfini yazmaq
  • Xəta hesabatını inkişaf və istehsal mühitləri üçün düzgün qurmaq

Ödəniş sistemi cavab vermir, istifadəçi səhv JSON göndərib, verilənlər bazası əlçatan deyil — real saytda belə hallar hər gün olur. Yaxşı proqram «ağ ekran» göstərmir: problemi tutur, istifadəçiyə aydın mesaj verir, detalları isə jurnala yazır. PHP-də bunun əsas vasitəsi istisnalardır (exceptions).

try, catch və finally

Problem aşkar edəndə kod throw ilə istisna atır: funksiya dərhal dayanır və istisna onu tutan catch blokunu tapana qədər çağırışlar zənciri ilə yuxarı qalxır. try blokuna təhlükəli kod yazılır, catch müəyyən tipli istisnanı tutur, finally isə hər halda — istisna olsa da, olmasa da — icra olunur.

PHP
<?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";
    }
}
Gözlənilən nəticə
12 / 4 = 3
-- done with 4
Error: Cannot divide by zero
-- done with 0

$b = 0 olanda echo sətri heç icra olunmadı: throw-dan sonra idarəetmə birbaşa catch-ə keçdi. finally isə dövrün hər iki addımında işlədi. İstisna obyektinin faydalı metodları: getMessage() — mesaj, getCode() — kod, getFile() və getLine() — xətanın yeri, getPrevious() — əvvəlki istisna.

Exception və Error

PHP 7-dən bəri bütün atılan obyektlərin ortaq valideyni Throwable interfeysidir. Ondan iki qol ayrılır: **Exception — proqramın öz məntiqindəki problemlər (yanlış arqument, fayl tapılmadı, bazaya qoşulmaq alınmadı), Error** — PHP-nin daxili xətaları (yanlış tip, sıfıra bölmə, mövcud olmayan metodun çağırılması).

QolTez-tez rast gəlinən siniflərNə vaxt
ExceptionInvalidArgumentException, RuntimeException, JsonException, PDOExceptiongözlənilən problemlər: tutmaq və emal etmək olar
ErrorTypeError, ValueError, DivisionByZeroError, ArgumentCountError, UnhandledMatchErroradətən koddakı səhv: onu düzəltmək lazımdır
PHP
<?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";
    }
}
Gözlənilən nəticə
DivisionByZeroError: Division by zero
JsonException: Syntax error
RuntimeException: Disk is full

Öz istisnaların

Öz istisna sinfini yaratmaq üçün mövcud sinifdən, adətən RuntimeException və ya DomainException-dan törə. Adı problemi aydın təsvir etsin, lazım olsa, əlavə məlumatı xassədə saxla. Onda catch bloku məhz bu vəziyyətə dəqiq reaksiya verə bilər.

PHP
<?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";
}
Gözlənilən nəticə
Paid 12, left 18
Not enough money: missing 7.5 AZN
Top up at least 8 AZN
Köhnə: qaytarılan qiyməti yoxlamaq
$data = json_decode($input);
if ($data === null) {
    // broken JSON or the value null?
    echo json_last_error_msg();
}
Müasir: istisna
try {
    $data = json_decode($input, flags: JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
    echo "Invalid JSON: ", $e->getMessage();
}
null həm xəta, həm də düzgün JSON-un (null) nəticəsi ola bilər. İstisna isə səhvi birmənalı bildirir.

Xəbərdarlıqlar və xəta hesabatı

Bəzi problemlər istisna atmır, sadəcə xəbərdarlıq verir: məsələn, mövcud olmayan dəyişən Warning: Undefined variable $x, köhnəlmiş funksiya isə Deprecated mesajı yaradır. Hansı mesajların görünəcəyini php.ini parametrləri müəyyən edir. Qızıl qayda: inkişaf zamanı hər şeyi gör, istehsalda isə (production) istifadəçiyə heç nə göstərmə, hər şeyi jurnala yaz.

Parametr (php.ini)İnkişafİstehsal
error_reportingE_ALLE_ALL
display_errorsOnOff
log_errorsOnOn
Kodda da aktivləşdirmək olar: error_reporting(E_ALL); ini_set('display_errors', '1');

Əsas fikirlər

  • throw istisna atır; try təhlükəli kodu, catch konkret tipi tutur, finally isə hər zaman icra olunur.
  • Throwable-ın iki qolu var: Exception (gözlənilən problemlər) və Error (PHP-nin daxili xətaları).
  • Öz istisnanı mövcud sinifdən törət və adını mənalı seç; əlavə məlumatı xassədə saxla.
  • PHP 8-də throw ifadədir: $x = $arr[$k] ?? throw new ...;
  • İnkişafda display_errors = On, istehsalda isə Off və log_errors = On olmalıdır.

Özünü yoxla

10 sual. Hər düzgün cavab XP qazandırır.

1 / 10
finally bloku nə vaxt icra olunur?