Röviden: A PHP két úton jelzi a problémákat: klasszikus hibaként, például figyelmeztetésként és megjegyzésként, amelyeket az error_reporting vezérel, valamint kivételként, amelyeket try és catch segítségével lehet elkapni. A PHP 7 óta sok belső hiba is Error osztályú objektumot dob; ez az Exception-nel együtt a Throwable interfészt valósítja meg. Éles üzemben az a szabály, hogy a hibákat naplózni kell, és soha nem szabad a böngészőben megjeleníteni. A PHP 8.5-ön a PHP2Shell miatt az átmeneti intézkedésekhez a fatal_error_backtraces=0 is hozzátartozik.
Két világ: klasszikus hibák és kivételek
A PHP olyan korból származik, amikor a hibákat főleg üzenetként írták ki: megjegyzések (E_NOTICE), figyelmeztetések (E_WARNING), elavult függvények (E_DEPRECATED) és végzetes hibák (E_ERROR). Ezen üzenetek közül sok futni hagyja a szkriptet, gyakran hibás vagy üres adatokkal.
A kivételek másként működnek. Megszakítják a normál lefutást, és a következő megfelelő catch blokkra ugranak. Ha egyet sem találnak, a szkript véget ér. A döntéshozók számára a különbség azért fontos, mert egy csendes figyelmeztetés oda vezethet, hogy egy rendelés hiányosan mentődik el anélkül, hogy bárki észrevenné. A kivétel láthatóvá és kezelhetővé teszi a problémát.
A klasszikus üzenetek alulértékelt haszna az E_DEPRECATED típusú megjegyzések. Ezek jelzik, hogy egy nyelvi eszköz egy jövőbeli PHP-verzióban megszűnik. Aki a naplóban gyűjti, és rendszeresen kiértékeli őket, egy frissítés előtt tudja, mely helyeket kell módosítani, és sürgős biztonsági rés esetén nem kell hosszan tesztelnie.
A Throwable-hierarchia
Minden, ami throw-val dobható és catch-csel elkapható, megvalósítja a Throwable-t. Alatta két ág van:
| Osztály | Cél | Példák az alosztályokra |
|---|---|---|
Exception |
az alkalmazás és a bővítmények várható hibái | ErrorException, PDOException, saját osztályok |
Error |
a PHP belső hibái | TypeError, ValueError, ArgumentCountError, ArithmeticError, DivisionByZeroError, UnhandledMatchError |
A saját hibaosztályok az Exception-ből származnak, nem az Error-ból. A PHP 8.0 óta a legtöbb belső függvény érvénytelen paraméter esetén TypeErrort vagy ValueErrort dob, ahelyett hogy csak figyelmeztetést írna ki. A strlen([]) ilyen eset.
try, catch és finally a gyakorlatban
<?php
declare(strict_types=1);
final class ZahlungFehlgeschlagen extends RuntimeException {}
function bezahlen(Bestellung $b, Zahlungsdienst $dienst, LoggerInterface $log): bool
{
try {
$dienst->belasten($b->betrag(), $b->referenz());
return true;
} catch (ZahlungFehlgeschlagen $e) {
$log->warning('Zahlung abgelehnt', ['bestellung' => $b->id(), 'exception' => $e]);
return false;
} catch (TimeoutException | VerbindungsFehler) {
// a PHP 8.0 óta a változó a catch-ben elhagyható
$log->error('Zahlungsdienst nicht erreichbar', ['bestellung' => $b->id()]);
return false;
} finally {
$dienst->verbindungSchliessen();
}
}
Több osztály a | jellel összevonható egyetlen catch-ben. A finally blokk mindig lefut, akár történt hiba, akár nem. A PHP 8.0 óta a throw kifejezés is, így például a ?? mögé kerülhet: $id = $_GET['id'] ?? throw new InvalidArgumentException('id fehlt');.
Globális kezelők: set_error_handler és set_exception_handler
Két függvény fogja el azt, ami egyébként átcsúszna. A set_exception_handler() egy függvényt regisztrál az el nem kapott Throwable-ökhöz. A kézikönyv szerint a szkript a meghívása után véget ér; naplózásra és semleges hibaoldalra alkalmas tehát, nem a továbbfutásra.
Bevált megoldás az a kezelő, amely a teljes hibát időponttal és véletlenszerű azonosítóval a naplóba írja, a látogatónak pedig csak egy semleges oldalt mutat ezzel az azonosítóval. Az ügyfélszolgálat így megtalálja az esetet a naplóban, anélkül hogy belső részletek kiszivárognának.
A set_error_handler() a klasszikus hibákat fogja el. A kézikönyv megmutatja, hogyan lehet őket ErrorException-né alakítani, hogy a figyelmeztetéseket kivételként kezeljék:
<?php
set_error_handler(function (int $nr, string $text, string $datei, int $zeile): bool {
if (!(error_reporting() & $nr)) {
return false; // az error_reporting kizárta
}
if ($nr === E_DEPRECATED || $nr === E_USER_DEPRECATED) {
return false; // az elavultságra utaló megjegyzéseket nem eszkaláljuk
}
throw new ErrorException($text, 0, $nr, $datei, $zeile);
});
A végzetes hibák, például a memóriatúlcsordulás, ezen az úton nem foghatók el. Hogy mi történik túlcsordulás esetén belül, azt a memory_limit és Out-of-Memory oldal magyarázza.
A hibakimenet és a naplózás beállítása
A legfontosabb beállítások a kézikönyv szerinti alapértékekkel:
| Beállítás | Alapérték | Ajánlás éles üzemre |
|---|---|---|
error_reporting |
E_ALL a PHP 8.0.0 óta |
E_ALL |
display_errors |
1 |
Off |
display_startup_errors |
1 a PHP 8.0.0 óta |
Off |
log_errors |
0 |
On |
error_log |
üres (a webszerver, illetve a SAPI naplója) | saját fájl a webgyökéren kívül |
fatal_error_backtraces |
1, újdonság a PHP 8.5.0-ban |
átmenetileg 0 (PHP2Shell) |
A PHP 8.2.0 óta az error_log_mode határozza meg a naplófájl fájljogosultságait, alapértelmezés szerint 0644. Ha a naplók személyes adatokat vagy útvonalakat tartalmaznak, szigorúbb érték az ésszerű, hogy a szerver más felhasználói ne olvashassák őket. Az ignore_repeated_errors segítségével az azonos fájlból és sorból származó azonos üzenetek összevonhatók, hogy egy hibaciklus ne árassza el a naplót.
A mellékelt php.ini-production a display_errors értékét már Off-ra állítja. A kézikönyv szerint az ini_set('display_errors', ...) futásidőben nem hat a végzetes hibákra, a szintaktikai hibák pedig azelőtt lépnek fel, hogy bármely ini_set() egyáltalán lefutna. Ezeknek az értékeknek ezért a szerverkonfigurációba kell kerülniük. A háttérről a Hibakimenet kikapcsolása éles üzemben cikk, a naplóvezetésről adatszivárgás nélkül a Biztonságos naplózás cikk szól.
Hibakezelés és PHP2Shell
A PHP 8.5-höz a php.net a PHP2Shell elleni egyik átmeneti intézkedésként azt nevezi meg, hogy a fatal_error_backtraces=0 értéket kell beállítani, majd újra kell indítani a PHP-t. A többi intézkedés a memory_limit-et, a post_max_size-t és a session.upload_progress.enabled-et érinti. Egyik sem helyettesíti a frissítést a PHP 8.5.12, 8.4.27, 8.3.36 vagy 8.2.35 verzióra.
; csak PHP 8.5, a php.ini-ben vagy az FPM-poolban, utána minden workert újra kell indítani
fatal_error_backtraces = 0
A hibanaplók a PHP2Shell után emellett fontos bizonyítékot jelentenek. Ha 2026. október 20-tól szaporodnak a memóriahibák vagy a megszakadt workerek, az támadási kísérletekre utalhat, de ártalmatlan okai is lehetnek. Őrizze meg a naplókat, és a hozzáférési naplókkal együtt értékelje ki őket, ahogyan a Webszerver-naplók kiértékelése támadás után útmutató leírja.
Hogyan segít konkrétan a PHP SOS?
- Weboldalanként megvizsgáljuk a hibakimenet és a naplózás érvényes beállításait, és éles üzemre alkalmasan állítjuk be őket.
- A PHP2Shell átmeneti intézkedéseit a PHP-verzióhoz illeszkedően alkalmazzuk, és újraindítjuk az összes workert.
- Biztosítjuk a hiba- és hozzáférési naplókat 2026. október 20-tól, és kiértékeljük őket feltűnő jelenségek szempontjából.
- A biztonsági monitoring keretében jelezzük a szokatlan hibahalmozódásokat, ahelyett hogy elmerülnének a naplóban.
Gyakori kérdések
Mi a különbség az Error és az Exception között?
Mindkettő megvalósítja a Throwable interfészt. Az Exception olyan hibákra szolgál, amelyeket egy alkalmazás számít és kezel, például egy sikertelen adatbázis-kapcsolat. Az Error a PHP belső hibáit jelöli, például a TypeErrort vagy a nullával osztást.
Legyen bekapcsolva a display_errors éles üzemben?
Nem. A böngészőben megjelenő hibaüzenetek elárulják az útvonalakat, a lekérdezéseket, olykor a hozzáférési adatokat is. Éles üzemben a display_errors legyen Off, a log_errors pedig On, hogy a hibák a naplóba kerüljenek, ne a látogatóhoz.
Elkapható a memóriatúlcsordulás try/catch-csel?
Nem. Ha egy szkript túllépi a memory_limit-et, a PHP végzetes hibával leállítja, amely nem kapható el kivételként. Csak a hibanaplóban jelenik meg, feltéve, hogy a log_errors aktív.
Mi a fatal_error_backtraces?
Egy beállítás, amely a PHP 8.5.0 óta létezik, és a végzetes hibákhoz backtrace-t fűz. Alapértelmezés szerint aktív. A PHP2Shell elleni átmeneti intézkedésként a php.net a PHP 8.5-nél azt nevezi meg, hogy 0-ra kell állítani, majd újra kell indítani a PHP-t.