Xatolar — try/catch/finally, Exception, error_reporting
Muammodan boshlaylik
Saytingiz ishlab turibdi. Kechasi ma'lumotlar bazasi serveri qayta ishga tushdi. Shu daqiqada saytga kirgan foydalanuvchi ekranda buni ko'rdi:
Fatal error: Uncaught PDOException: SQLSTATE[HY000] [2002] Connection refused
in /var/www/dokon/config/db.php:12
Stack trace: #0 /var/www/dokon/config/db.php(12): PDO->__construct('mysql:host=10.0...', 'dokon_admin', 'Qw3rty!2026')
Foydalanuvchi uchun bu tushunarsiz. Hujumchi uchun esa — sovg'a: server papkalari tuzilmasi, baza manzili, login va parol.
Bu darsda ikki narsani o'rganamiz: xatolarni dastur ichida to'g'ri ushlash va foydalanuvchiga xavfsiz ko'rsatish.
PHP dagi ikki xil muammo
1. Ogohlantirishlar (Warning, Notice, Deprecated) — dastur davom etadi:
<?php
echo $yoq; // Warning: Undefined variable $yoq
echo "Bu chiqadi";
2. Xatolar va istisnolar (Error, Exception) — ushlanmasa, dastur to'xtaydi:
<?php
echo intdiv(10, 0); // DivisionByZeroError
echo "Bu chiqmaydi";
PHP 7 dan boshlab deyarli barcha jiddiy xatolar ob'ekt sifatida "tashlanadi" (throw) va ularni ushlash mumkin.
try / catch
<?php
try {
$natija = intdiv(10, 0);
echo "Bu qator bajarilmaydi";
} catch (DivisionByZeroError $e) {
echo "Nolga bo'lib bo'lmaydi";
}
echo "Dastur davom etadi";
try— xato chiqishi mumkin bo'lgan kodcatch (Tur $e)— shu turdagi xato chiqsa, nima qilish$e— xato ob'ekti, ichida ma'lumot bor
<?php
try {
$data = json_decode('{noto\'g\'ri', true, flags: JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
echo $e->getMessage(); // Syntax error
echo $e->getFile(); // qaysi faylda
echo $e->getLine(); // qaysi qatorda
}
Xatolar ierarxiyasi
Throwable
├── Error ← PHP ning o'z xatolari (kod xatosi)
│ ├── TypeError
│ ├── ValueError
│ ├── ArgumentCountError
│ └── DivisionByZeroError
└── Exception ← kutilgan, qayta ishlanadigan holatlar
├── JsonException
├── PDOException
├── RuntimeException
└── InvalidArgumentException
catch (Exception $e) — barcha Exception larni ushlaydi, lekin Error larni ushlamaydi. Ikkalasini ham ushlash kerak bo'lsa — Throwable.
Bir nechta tur:
<?php
try {
// ...
} catch (JsonException | ValueError $e) {
echo "Ma'lumot noto'g'ri";
} catch (PDOException $e) {
echo "Bazada muammo";
}
throw — o'zingiz xato tashlash
Funksiya o'z vazifasini bajara olmasa — false qaytarish o'rniga xato tashlash yaxshiroq:
<?php
function pulYechish(int $balans, int $summa): int
{
if ($summa <= 0) {
throw new InvalidArgumentException("Summa musbat bo'lishi kerak");
}
if ($summa > $balans) {
throw new RuntimeException("Mablag' yetarli emas");
}
return $balans - $summa;
}
try {
$yangi = pulYechish(50000, 80000);
} catch (RuntimeException $e) {
echo $e->getMessage(); // Mablag' yetarli emas
}
Nima uchun false qaytarish yomon? Chaqiruvchi uni tekshirishni unutishi mumkin — va false jimgina 0 ga aylanib, hisob-kitobni buzadi. Exception ni esa e'tiborsiz qoldirib bo'lmaydi.
O'z xato turingiz
<?php
class MablagYetarliEmas extends RuntimeException {}
throw new MablagYetarliEmas("Balansda 50 000 so'm bor");
Endi aynan shu holatni boshqalardan ajratib ushlash mumkin. Classlar haqida 28-darsdan boshlab.
finally — har doim bajariladi
<?php
$f = fopen(__DIR__ . '/data.csv', 'r');
try {
while (($qator = fgetcsv($f)) !== false) {
qatorniQaytaIshla($qator); // xato tashlashi mumkin
}
} finally {
fclose($f); // xato bo'lsa ham, bo'lmasa ham fayl yopiladi
}
finally — "nima bo'lishidan qat'i nazar, oxirida buni bajar". Resurslarni (fayl, qulf, ulanish) yopish uchun.
Xatolarni ko'rsatish sozlamalari
Ishlab chiqishda (localhost)
<?php
ini_set('display_errors', '1');
error_reporting(E_ALL);
Barcha xatolar va ogohlantirishlar ekranda. Har bir Warning ni ko'rib, tuzatasiz.
Serverda (production)
php.ini:
display_errors = Off
log_errors = On
error_log = /var/log/php/xatolar.log
error_reporting = E_ALL
Foydalanuvchi hech qanday texnik ma'lumot ko'rmaydi. Hamma xatolar faylga yoziladi — siz u yerdan o'qiysiz.
[!WARNING] Serverda
display_errors = On— jiddiy xavfsizlik teshigi. Yuqoridagi misolda baza paroli aynan shu sababli oshkor bo'ldi.
Global xato ushlagich
Hamma joyda try/catch yozish shart emas. Ushlanmay qolgan har qanday xato uchun bitta umumiy ushlagich:
<?php
// bootstrap.php — har bir sahifa boshida require qilinadi
set_exception_handler(function (Throwable $e): void {
error_log(sprintf(
"[%s] %s: %s in %s:%d",
date('Y-m-d H:i:s'),
$e::class,
$e->getMessage(),
$e->getFile(),
$e->getLine()
));
http_response_code(500);
echo "Kechirasiz, xatolik yuz berdi. Biz allaqachon tuzatyapmiz.";
});
// Warning va Notice larni ham exception ga aylantirish
set_error_handler(function (int $daraja, string $xabar, string $fayl, int $qator): bool {
throw new ErrorException($xabar, 0, $daraja, $fayl, $qator);
});
Natija:
- Foydalanuvchi — do'stona xabar va to'g'ri
500status - Siz — logda to'liq texnik ma'lumot
- Warning lar endi jimgina o'tib ketmaydi
Laravel va Symfony ichida aynan shunday mexanizm ishlaydi.
Qachon ushlash, qachon ushlamaslik
Ushlang, agar xatoni ma'noli qayta ishlay olsangiz:
- Foydalanuvchiga tushunarli xabar ko'rsatish ("Bu email allaqachon ro'yxatdan o'tgan")
- Muqobil yo'l (keshdan olish, qayta urinish)
- Resursni yopish (
finally)
Ushlamang, agar faqat yashirish uchun bo'lsa:
<?php
// ❌ Eng yomon kod
try {
muhimIsh();
} catch (Throwable $e) {
// hech narsa
}
Xato yo'qolmadi — u shunchaki ko'rinmay qoldi. Endi sayt noto'g'ri ishlaydi va nima uchunligini hech kim bilmaydi. Ushlay olmasangiz — global ushlagichga qoldiring.
Nima uchun shunday?
Nima uchun PHP da bir vaqtning o'zida eski "Warning" tizimi ham, zamonaviy "Exception" lar ham bor?
PHP dastlab xatolarni ekranga matn chiqarish orqali bildirgan — 1990-yillardagi sahifa skriptlari uchun bu yetarli edi. OOP va katta ilovalar paydo bo'lgach, exception lar qo'shildi (PHP 5). PHP 7 da ko'plab "Fatal error" lar ushlanadigan Error ga aylandi. Eski Warning tizimini butunlay olib tashlash millionlab saytlarni buzardi — shuning uchun ikkalasi yonma-yon yashaydi, set_error_handler esa ularni bitta tizimga birlashtiradi.
Xulosa
Eslab qoling:
try { } catch (Tur $e) { } finally { }Exception— kutilgan holatlar,Error— kod xatolari; ikkalasi hamThrowable- Muvaffaqiyatsizlikda
falseemas,throw new ...Exception - Ishlab chiqishda:
display_errors=1,E_ALL; serverda:display_errors=Off,log_errors=On set_exception_handler— foydalanuvchiga do'stona xabar, logga to'liq ma'lumot- Bo'sh
catchyozmang
Keyingi dars
28-dars: Class va ob'ekt — xususiyat, metod, $this, konstruktor