# Chyby a výnimky v PHP

> Chyby a výnimky v PHP: Throwable, Error a Exception, try/catch/finally, globálne handlery a bezpečné nastavenia pre výpis chýb a logy.

Zdroj: https://phpsos.de/sk/php/fehler-und-exceptions/  
Stav: 25.10.2026  
Poskytovateľ: PHP SOS, Núdzová pomoc pri PHP a bezpečnosť serverov. Okamžitá pomoc cez WhatsApp: https://wa.me/491736494914?text=Dobr%C3%BD%20de%C5%88%2C%20PHP%20SOS%2C%20potrebujeme%20pomoc%20s%20na%C5%A1%C3%ADm%20serverom%20s%20PHP.%20Spolo%C4%8Dnos%C5%A5%3A%20%E2%80%A6%20Web%3A%20%E2%80%A6

**Stručne:** PHP hlási problémy dvoma spôsobmi: ako klasické chyby, napríklad varovania a upozornenia, ktoré sa riadia cez `error_reporting`, a ako výnimky, ktoré sa dajú zachytiť pomocou `try` a `catch`. Od PHP 7 vyhadzuje objekt triedy `Error` aj mnoho interných chýb; spolu s `Exception` implementuje rozhranie `Throwable`. V produkcii platí: chyby zapisovať do logu, nikdy ich nezobrazovať v prehliadači. Na PHP 8.5 patrí kvôli PHP2Shell k prechodným opatreniam aj `fatal_error_backtraces=0`.

## Dva svety: klasické chyby a výnimky

PHP pochádza z čias, keď sa chyby vypisovali predovšetkým ako hlásenie: upozornenia (`E_NOTICE`), varovania (`E_WARNING`), zastarané funkcie (`E_DEPRECATED`) a fatálne chyby (`E_ERROR`). Mnohé z týchto hlásení nechajú skript bežať ďalej, často s nesprávnymi alebo prázdnymi údajmi.

Výnimky fungujú inak. Prerušia normálny priebeh a preskočia na najbližší vhodný blok `catch`. Ak sa žiadny nenájde, skript skončí. Pre rozhodovateľov je rozdiel dôležitý: tiché varovanie môže viesť k tomu, že sa objednávka uloží neúplne, bez toho, aby si to niekto všimol. Výnimka robí problém viditeľným a ošetriteľným.

Nedocenený prínos klasických hlásení sú upozornenia typu `E_DEPRECATED`. Oznamujú, že jazykový prostriedok v budúcej verzii PHP zanikne. Kto ich zbiera v logu a pravidelne vyhodnocuje, vie pred upgradom, ktoré miesta treba upraviť, a pri naliehavej bezpečnostnej zraniteľnosti nemusí najprv dlho testovať.

## Hierarchia Throwable

Všetko, čo sa dá vyhodiť pomocou `throw` a zachytiť pomocou `catch`, implementuje `Throwable`. Pod ním sú dve vetvy:

| Trieda | Účel | Príklady podtried |
|---|---|---|
| `Exception` | očakávateľné chyby aplikácie a rozšírení | `ErrorException`, `PDOException`, vlastné triedy |
| `Error` | interné chyby PHP | `TypeError`, `ValueError`, `ArgumentCountError`, `ArithmeticError`, `DivisionByZeroError`, `UnhandledMatchError` |

Vlastné triedy chýb sa odvodzujú od `Exception`, nie od `Error`. Od PHP 8.0 vyhadzuje väčšina interných funkcií pri neplatných parametroch `TypeError` alebo `ValueError` namiesto toho, aby vypísala len varovanie. Takým prípadom je `strlen([])`.

## try, catch a finally v praxi

```php
<?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) {
        // od PHP 8.0 je premenná v catch voliteľná
        $log->error('Zahlungsdienst nicht erreichbar', ['bestellung' => $b->id()]);
        return false;
    } finally {
        $dienst->verbindungSchliessen();
    }
}
```

Viaceré triedy možno v jednom `catch` zlúčiť pomocou `|`. Blok `finally` sa vykoná vždy, či už nastala chyba, alebo nie. Od PHP 8.0 je `throw` navyše výraz a môže stáť napríklad za `??`: `$id = $_GET['id'] ?? throw new InvalidArgumentException('id fehlt');`.

## Globálne handlery: set_error_handler a set_exception_handler

Dve funkcie zachytia to, čo by inak prešlo. `set_exception_handler()` zaregistruje funkciu pre nezachytené Throwable. Podľa príručky skript po jej zavolaní skončí; hodí sa teda na zapisovanie do logu a neutrálnu chybovú stránku, nie na pokračovanie v práci.

Osvedčil sa handler, ktorý do logu zapíše celú chybu s časom a náhodným identifikátorom a návštevníkovi ukáže iba neutrálnu stránku s týmto identifikátorom. Podpora potom prípad v logu nájde bez toho, aby unikli interné podrobnosti.

`set_error_handler()` zachytáva klasické chyby. Príručka ukazuje, ako ich premeniť na `ErrorException`, aby sa varovania ošetrovali ako výnimky:

```php
<?php
set_error_handler(function (int $nr, string $text, string $datei, int $zeile): bool {
    if (!(error_reporting() & $nr)) {
        return false; // vylúčené cez error_reporting
    }
    if ($nr === E_DEPRECATED || $nr === E_USER_DEPRECATED) {
        return false; // upozornenia na zastarané veci neeskalovať
    }
    throw new ErrorException($text, 0, $nr, $datei, $zeile);
});
```

Fatálne chyby, ako pretečenie pamäte, sa týmto spôsobom zachytiť nedajú. Čo sa pri pretečení deje vo vnútri, vysvetľuje stránka [memory_limit a Out-of-Memory](https://phpsos.de/sk/php/out-of-memory/).

## Konfigurácia výpisu chýb a zapisovania do logu

Najdôležitejšie nastavenia s ich štandardnými hodnotami podľa príručky:

| Nastavenie | Štandard | Odporúčanie pre produkciu |
|---|---|---|
| `error_reporting` | `E_ALL` od PHP 8.0.0 | `E_ALL` |
| `display_errors` | `1` | `Off` |
| `display_startup_errors` | `1` od PHP 8.0.0 | `Off` |
| `log_errors` | `0` | `On` |
| `error_log` | prázdne (log webového servera, resp. SAPI) | vlastný súbor mimo webrootu |
| `fatal_error_backtraces` | `1`, novinka v PHP 8.5.0 | dočasne `0` (PHP2Shell) |

Od PHP 8.2.0 určuje `error_log_mode` prístupové práva súboru logu, štandardne `0644`. Ak logy obsahujú osobné údaje alebo cesty, je vhodná prísnejšia hodnota, aby ich ostatní používatelia na serveri nemohli čítať. Pomocou `ignore_repeated_errors` sa dajú zlúčiť rovnaké hlásenia z toho istého súboru a riadku, aby slučka chýb nezaplavila log.

Dodávaný `php.ini-production` už nastavuje `display_errors` na `Off`. Podľa príručky `ini_set('display_errors', ...)` za behu nepôsobí na fatálne chyby a syntaktické chyby nastanú skôr, než sa vôbec vykoná nejaké `ini_set()`. Tieto hodnoty preto patria do konfigurácie servera. Súvislosti sú v článku [Vypnutie výpisu chýb v produkcii](https://phpsos.de/sk/blog/display-errors-produktion/); ako viesť logy bez úniku údajov, v článku [Bezpečné zapisovanie do logov](https://phpsos.de/sk/blog/sicher-loggen-php/).

## Ošetrenie chýb a PHP2Shell

Pre PHP 8.5 uvádza php.net ako jedno z prechodných opatrení proti PHP2Shell nastaviť `fatal_error_backtraces=0` a potom PHP reštartovať. Ostatné opatrenia sa týkajú `memory_limit`, `post_max_size` a `session.upload_progress.enabled`. Žiadne z nich nenahrádza aktualizáciu na PHP 8.5.12, 8.4.27, 8.3.36 alebo 8.2.35.

```ini
; iba PHP 8.5, v php.ini alebo v poole FPM, potom reštartovať všetky workery
fatal_error_backtraces = 0
```

Logy chýb sú po PHP2Shell navyše dôležitým dôkazným materiálom. Ak sa od 20. 10. 2026 množia chyby pamäte alebo prerušené workery, môže to naznačovať pokusy o útok, ale môže to mať aj neškodné príčiny. Logy uchovajte a vyhodnoťte spolu s prístupovými logmi, ako opisuje sprievodca [Vyhodnotenie logov webového servera po útoku](https://phpsos.de/sk/ratgeber/logfiles-auswerten/).

## Ako PHP SOS konkrétne pomáha?

- Kontrolujeme účinné nastavenia výpisu chýb a zapisovania do logu pre každý web a nastavujeme ich vhodne pre produkciu.
- Prechodné opatrenia PHP2Shell nastavujeme podľa verzie PHP a reštartujeme všetky workery.
- Zálohujeme logy chýb a prístupov od 20. 10. 2026 a vyhodnocujeme ich na nezrovnalosti.
- V rámci [monitoringu bezpečnosti](https://phpsos.de/sk/leistungen/security-monitoring/) hlásime nezvyčajné nahromadenie chýb, namiesto toho, aby sa stratilo v logu.


## Časté otázky

**Aký je rozdiel medzi Error a Exception?**  
Obe implementujú rozhranie Throwable. Exception je určená pre chyby, ktoré aplikácia očakáva a ošetruje, napríklad neúspešné pripojenie k databáze. Error predstavuje interné chyby PHP, ako TypeError alebo delenie nulou.

**Má byť display_errors v produkcii zapnuté?**  
Nie. Chybové hlásenia v prehliadači prezrádzajú cesty, dotazy a niekedy aj prístupové údaje. V produkcii patrí display_errors na Off a log_errors na On, aby chyby skončili v logu, a nie u návštevníka.

**Dá sa pretečenie pamäte zachytiť pomocou try/catch?**  
Nie. Ak skript prekročí memory_limit, PHP ho ukončí fatálnou chybou, ktorú nemožno zachytiť ako výnimku. Objaví sa iba v logu chýb, pokiaľ je log_errors aktívne.

**Čo je fatal_error_backtraces?**  
Nastavenie, ktoré existuje od PHP 8.5.0 a k fatálnym chybám pridáva backtrace. Je štandardne aktívne. Ako prechodné opatrenie proti PHP2Shell php.net pre PHP 8.5 uvádza nastaviť ho na 0 a potom PHP reštartovať.

## Zdroje

- [Príručka PHP: Konfigurácia ošetrenia chýb](https://www.php.net/manual/de/errorfunc.configuration.php)
- [Príručka PHP: Trieda Error](https://www.php.net/manual/de/class.error.php)
- [Príručka PHP: ErrorException](https://www.php.net/manual/en/class.errorexception.php)
- [Príručka PHP: set_exception_handler](https://www.php.net/manual/en/function.set-exception-handler.php)
- [php.net: Bezpečnostné oznámenia](https://www.php.net/)
