throw,try,catchvəfinallyilə istisnaları atmaq və tutmaqThrowable,ExceptionvəErroriyerarxiyası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
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 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ı).
| Qol | Tez-tez rast gəlinən siniflər | Nə vaxt |
|---|---|---|
Exception | InvalidArgumentException, RuntimeException, JsonException, PDOException | gözlənilən problemlər: tutmaq və emal etmək olar |
Error | TypeError, ValueError, DivisionByZeroError, ArgumentCountError, UnhandledMatchError | adətən koddakı səhv: onu düzəltmək lazımdır |
<?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
Ö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
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 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_reporting | E_ALL | E_ALL |
display_errors | On | Off |
log_errors | On | On |
error_reporting(E_ALL); ini_set('display_errors', '1');Əsas fikirlər
throwistisna atır;trytəhlükəli kodu,catchkonkret tipi tutur,finallyisə 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ə
throwifadədir:$x = $arr[$k] ?? throw new ...; - İnkişafda
display_errors = On, istehsalda isəOffvəlog_errors = Onolmalıdır.
Özünü yoxla
10 sual. Hər düzgün cavab XP qazandırır.
finally bloku nə vaxt icra olunur?