Trenutno stanje: PHP2Shell. Dvije kritične PHP ranjivosti (CVSS 9.2) omogućuju zlonamjerni kod bez prijave. Zakrpe od 21. 10. 2026.Što sada učiniti →

Pogreške i iznimke (exceptions) u PHP-u

PHP poznaje klasične poruke o pogreškama i iznimke. Ova stranica objašnjava hijerarhiju Throwable, urednu obradu pogrešaka, sigurne postavke za produkciju i mjeru PHP2Shella uz fatal_error_backtraces.

Stanje 5 min čitanjaPHP znanje

Ukratko: PHP prijavljuje probleme na dva načina: kao klasične pogreške poput upozorenja i napomena, kojima se upravlja putem error_reporting, te kao iznimke koje se mogu uhvatiti s try i catch. Od PHP-a 7 i mnoge interne pogreške bacaju objekt klase Error; zajedno s Exception implementira sučelje Throwable. U produkciji vrijedi: pogreške zapisivati, nikad ih ne prikazivati u pregledniku. Na PHP-u 8.5 zbog PHP2Shella među prijelazne mjere spada i fatal_error_backtraces=0.

Dva svijeta: klasične pogreške i iznimke

PHP potječe iz vremena u kojem su se pogreške ponajprije ispisivale kao poruke: napomene (E_NOTICE), upozorenja (E_WARNING), zastarjele funkcije (E_DEPRECATED) i fatalne pogreške (E_ERROR). Mnoge od tih poruka dopuštaju da skripta nastavi raditi, često s pogrešnim ili praznim podacima.

Iznimke rade drukčije. Prekidaju uobičajeni tijek i skaču na sljedeći odgovarajući catch blok. Ako ga nema, skripta završava. Za donositelje odluka razlika je važna: tiho upozorenje može dovesti do toga da se narudžba spremi nepotpuno, a da to nitko ne primijeti. Iznimka problem čini vidljivim i obradivim.

Podcijenjena korist klasičnih poruka su napomene tipa E_DEPRECATED. One najavljuju da će jezično sredstvo otpasti u budućoj verziji PHP-a. Tko ih skuplja u zapisniku i redovito analizira, prije nadogradnje zna koja mjesta treba prilagoditi i kod hitne sigurnosne ranjivosti ne mora dugo testirati.

Hijerarhija Throwable

Sve što se može baciti s throw i uhvatiti s catch implementira Throwable. Ispod njega postoje dvije grane:

Klasa Svrha Primjeri potklasa
Exception pogreške koje se mogu očekivati u aplikaciji i ekstenzijama ErrorException, PDOException, vlastite klase
Error interne pogreške PHP-a TypeError, ValueError, ArgumentCountError, ArithmeticError, DivisionByZeroError, UnhandledMatchError

Vlastite klase pogrešaka nasljeđuju Exception, a ne Error. Od PHP-a 8.0 većina internih funkcija pri nevaljanim parametrima baca TypeError ili ValueError, umjesto da samo ispiše upozorenje. strlen([]) je jedan takav slučaj.

try, catch i finally u praksi

<?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-a 8.0 varijabla u catchu nije obavezna
        $log->error('Zahlungsdienst nicht erreichbar', ['bestellung' => $b->id()]);
        return false;
    } finally {
        $dienst->verbindungSchliessen();
    }
}

Više se klasa može objediniti znakom | u jednom catchu. Blok finally izvršava se uvijek, bez obzira je li došlo do pogreške. Od PHP-a 8.0 throw je uz to izraz i može stajati, primjerice, iza ??: $id = $_GET['id'] ?? throw new InvalidArgumentException('id fehlt');.

Globalni handleri: set_error_handler i set_exception_handler

Dvije funkcije hvataju ono što bi inače promaknulo. set_exception_handler() registrira funkciju za neuhvaćene Throwable objekte. Prema priručniku skripta završava nakon što se ona pozove; pogodna je dakle za zapisivanje i neutralnu stranicu s pogreškom, a ne za nastavak rada.

Dobro se pokazao handler koji potpunu pogrešku s vremenom i slučajnom oznakom upisuje u zapisnik, a posjetitelju prikazuje samo neutralnu stranicu s tom oznakom. Podrška tada slučaj može pronaći u zapisniku, a da interni detalji ne procure prema van.

set_error_handler() hvata klasične pogreške. Priručnik pokazuje kako ih pretvoriti u ErrorException kako bi se upozorenja obrađivala kao iznimke:

<?php
set_error_handler(function (int $nr, string $text, string $datei, int $zeile): bool {
    if (!(error_reporting() & $nr)) {
        return false; // isključeno putem error_reporting
    }
    if ($nr === E_DEPRECATED || $nr === E_USER_DEPRECATED) {
        return false; // napomene o zastarjelom ne eskalirati
    }
    throw new ErrorException($text, 0, $nr, $datei, $zeile);
});

Fatalne pogreške poput prekoračenja memorije ovim se putem ne mogu uhvatiti. Što se pri prekoračenju događa iznutra, objašnjava stranica memory_limit i Out-of-Memory.

Konfiguriranje ispisa pogrešaka i zapisivanja

Najvažnije postavke sa zadanim vrijednostima prema priručniku:

Postavka Zadano Preporuka za produkciju
error_reporting E_ALL od PHP-a 8.0.0 E_ALL
display_errors 1 Off
display_startup_errors 1 od PHP-a 8.0.0 Off
log_errors 0 On
error_log prazno (zapisnik web-poslužitelja odnosno SAPI-ja) vlastita datoteka izvan webrootea
fatal_error_backtraces 1, novo u PHP-u 8.5.0 privremeno 0 (PHP2Shell)

Od PHP-a 8.2.0 error_log_mode određuje prava datoteke zapisnika, prema zadanim postavkama 0644. Ako zapisnici sadrže osobne podatke ili putanje, smislena je stroža vrijednost kako ih drugi korisnici na poslužitelju ne bi mogli čitati. S ignore_repeated_errors mogu se sažeti identične poruke iz iste datoteke i retka, kako petlja pogrešaka ne bi preplavila zapisnik.

Isporučeni php.ini-production već postavlja display_errors na Off. Prema priručniku ini_set('display_errors', ...) tijekom izvođenja ne djeluje na fatalne pogreške, a sintaksne pogreške nastaju prije nego što se ini_set() uopće izvrši. Te vrijednosti zato pripadaju u konfiguraciju poslužitelja. Pozadinu donosi članak Isključivanje ispisa pogrešaka u produkciji; kako voditi zapisnike bez curenja podataka, opisuje članak Sigurno zapisivanje.

Obrada pogrešaka i PHP2Shell

Za PHP 8.5 php.net kao jednu od prijelaznih mjera protiv PHP2Shella navodi postavljanje fatal_error_backtraces=0 i potom ponovno pokretanje PHP-a. Ostale mjere tiču se memory_limit, post_max_size i session.upload_progress.enabled. Nijedna od njih ne zamjenjuje ažuriranje na PHP 8.5.12, 8.4.27, 8.3.36 ili 8.2.35.

; samo PHP 8.5, u php.ini ili FPM poolu, zatim ponovno pokrenuti sve workere
fatal_error_backtraces = 0

Zapisnici pogrešaka nakon PHP2Shella uz to su važan dokaz. Ako se od 20. 10. 2026. nagomilaju pogreške memorije ili prekinuti workeri, to može upućivati na pokušaje napada, ali može imati i bezazlene uzroke. Sačuvajte zapisnike i analizirajte ih zajedno sa zapisnicima pristupa, kako je opisano u vodiču Analiza zapisnika web-poslužitelja nakon napada.

Kako PHP SOS konkretno pomaže?

  • Provjeravamo djelotvorne postavke za ispis pogrešaka i zapisivanje po web-stranici i podešavamo ih za produkciju.
  • Postavljamo prijelazne mjere PHP2Shella u skladu s verzijom PHP-a i ponovno pokrećemo sve workere.
  • Osiguravamo zapisnike pogrešaka i pristupa od 20. 10. 2026. i analiziramo ih zbog neobičnosti.
  • U okviru sigurnosnog nadzora prijavljujemo neobična nagomilavanja pogrešaka, umjesto da ih pustimo da se izgube u zapisniku.

Česta pitanja

Koja je razlika između Error i Exception?

Oba implementiraju sučelje Throwable. Exception je namijenjen pogreškama koje aplikacija očekuje i obrađuje, primjerice neuspjelom spajanju na bazu podataka. Error označava interne pogreške PHP-a poput TypeErrora ili dijeljenja s nulom.

Treba li display_errors u produkciji biti uključen?

Ne. Poruke o pogreškama u pregledniku otkrivaju putanje, upite, a ponekad i pristupne podatke. U produkciji display_errors treba biti Off, a log_errors On, kako bi pogreške završavale u zapisniku, a ne kod posjetitelja.

Može li se prekoračenje memorije uhvatiti s try/catch?

Ne. Ako skripta prekorači memory_limit, PHP je prekida fatalnom pogreškom koja se ne može uhvatiti kao iznimka. Pojavljuje se samo u zapisniku pogrešaka, uz uvjet da je log_errors aktivan.

Što je fatal_error_backtraces?

Postavka koja postoji od PHP-a 8.5.0 i fatalnim pogreškama dodaje backtrace. Prema zadanim je postavkama aktivna. Kao prijelaznu mjeru protiv PHP2Shella php.net za PHP 8.5 navodi da je treba postaviti na 0 i zatim ponovno pokrenuti PHP.

Izvori

Hitni kontakt

Svaki sat se računa. Pišite nam odmah.

Ukratko opišite sustav, verziju PHP-a i opažanje. Javit ćemo Vam se, razjasniti situaciju i raditi na daljinu dok incident nije zaključen i dokumentiran.

Hitna pomoć