# Kako PHP stvara web-stranicu: put jednog zahtjeva

> Kako radi PHP? Od klika u pregledniku preko web-poslužitelja, SAPI-ja, kompilatora i Zend VM-a do gotove stranice, objašnjeno u sedam koraka s primjerima.

Izvor: https://phpsos.de/hr/php/wie-php-funktioniert/  
Stanje: 25.10.2026  
Pružatelj: PHP SOS, PHP hitna pomoć i sigurnost poslužitelja. Hitna pomoć putem WhatsAppa: https://wa.me/491736494914?text=Pozdrav%20PHP%20SOS%2C%20trebamo%20pomo%C4%87%20s%20na%C5%A1im%20PHP%20poslu%C5%BEiteljem.%20Tvrtka%3A%20%E2%80%A6%20Web-stranica%3A%20%E2%80%A6

**Ukratko:** Kada preglednik zatraži PHP stranicu, web-poslužitelj prima zahtjev i prosljeđuje ga PHP-u putem sučelja (SAPI). PHP skriptu prevodi u bytecode, izvršava ga u Zend Engineu i rezultat, najčešće HTML, vraća web-poslužitelju. Nakon toga se stanje zahtjeva čisti kako bi sljedeći počeo čist.

## Što se događa kada netko otvori Vašu web-stranicu?

Za posjetitelje je to jedan klik. Na poslužitelju se u milisekundama odvija mnogo koraka. Tko poznaje taj slijed, bolje razumije zašto su ažuriranja, ponovna pokretanja i konfiguracija toliko važni i zašto ranjivost u samom PHP-u teže pogađa nego ranjivost u dodatku.

PHP priručnik navodi tri sastavnice potrebne za PHP web-stranicu: PHP interpreter (kao CGI ili modul poslužitelja), web-poslužitelj i preglednik. Interpreter je program koji čita i izvršava PHP kod. Kako je povezan s web-poslužiteljem, određuje način rada.

## Kako radi PHP? Sedam koraka jednog zahtjeva

1. **Zahtjev:** Preglednik poslužitelju šalje HTTP zahtjev, na primjer `GET /kontakt.php`.
2. **Web-poslužitelj:** Apache, Nginx ili LiteSpeed primaju zahtjev. Statične datoteke poput slika isporučuju sami. Za `.php` datoteke pozivaju PHP.
3. **Predaja putem SAPI-ja:** Sučelje poslužitelja (SAPI) predaje PHP-u podatke zahtjeva poput zaglavlja, parametara i podataka obrasca. Kod PHP-FPM-a to ide putem FastCGI protokola, kod mod_php-a izravno u Apacheovu procesu. Pojedinosti u članku [SAPI objašnjen](https://phpsos.de/hr/php/sapi-erklaert/).
4. **Priprema zahtjeva:** PHP podatke zahtjeva sprema u varijable poput `$_GET`, `$_POST`, `$_COOKIE` i `$_FILES` te rezervira memoriju za zahtjev.
5. **Prevođenje:** Skripta se rastavlja na gradivne dijelove (tokene), iz njih nastaje apstraktno sintaktičko stablo (AST), a iz njega opcodeovi, svojevrsni strojni jezik za PHP. Ako je OPcache aktivan, ovaj se korak preskače kada se skripta već nalazi u predmemoriji.
6. **Izvršavanje:** Virtualni stroj [Zend Enginea](https://phpsos.de/hr/php/zend-engine/) obrađuje opcodeove, upućuje upite bazama podataka, čita datoteke i stvara izlaz.
7. **Odgovor i čišćenje:** Izlaz putem SAPI-ja ide natrag web-poslužitelju, a odande pregledniku. Zatim PHP oslobađa memoriju zahtjeva i vraća stanje na početno.

AST postoji od PHP-a 7. Prema pripadajućem RFC-u parser je prije toga opcodeove stvarao izravno tijekom čitanja; podjela na tri faze učinila je kompilator lakšim za održavanje.

## Primjer: što skripta vidi od zahtjeva

Sljedeća bezopasna skripta pokazuje koje podatke PHP dobiva iz zahtjeva i u kojem načinu rada radi:

```php
<?php
header('Content-Type: text/plain; charset=utf-8');

echo 'Betriebsart (SAPI): ' . PHP_SAPI . "\n";
echo 'PHP-Version: ' . PHP_VERSION . "\n";
echo 'Methode: ' . ($_SERVER['REQUEST_METHOD'] ?? '-') . "\n";
echo 'Speicher in dieser Anfrage: ' . memory_get_usage() . " Bytes\n";
```

Na poslužitelju s PHP-FPM-om `PHP_SAPI` ispisuje vrijednost `fpm-fcgi`, a pod Apacheom s mod_php-om `apache2handler`. Takve probne datoteke ostavljajte u javnom direktoriju samo kratko i nikad trajno, jer podaci o verziji pomažu i napadačima pri orijentaciji.

## Gdje u igru ulaze predmemorija bytecodea i JIT

Prevođenje u koraku 5 troši vrijeme. [OPcache](https://phpsos.de/hr/php/opcache/) prema priručniku pohranjuje unaprijed kompilirani bytecode u zajedničku memoriju i tako PHP-u štedi učitavanje i rastavljanje skripti pri svakom zahtjevu. Od PHP-a 8.0 dodatno JIT kompilator iz opcodeova može stvoriti pravi strojni kod. Prema JIT RFC-u gotovo je samostalan dio OPcachea.

| Faza | Rezultat | Sprema li se u predmemoriju? |
|---|---|---|
| Leksička analiza | niz tokena | ne |
| Parsiranje | apstraktno sintaktičko stablo (AST) | ne |
| Kompiliranje | opcodeovi (op-nizovi po datoteci i funkciji) | da, u OPcacheu |
| JIT (neobavezno) | strojni kod | da, u memoriji OPcachea |
| Izvršavanje | izlaz stranice | ne |

Predmemorija se odnosi samo na prevedeni kod. Podaci pojedinog zahtjeva, na primjer unosi u obrascu ili vrijednosti sesije, ne dijele se putem OPcachea.

## Zašto PHP2Shell napada upravo u tom slijedu

Obje PHP2Shell ranjivosti ne pogađaju jednu aplikaciju, nego sam slijed. Kod CVE-2026-109618 stanje nedostatka memorije može prekinuti PHP dok su podaci zahtjeva tek djelomično pripremljeni, dakle u koraku 4. Pri naknadnom čišćenju nevaljani se podaci tada mogu tretirati kao valjani.

Kod CVE-2026-109619 unutarnje stanje zahtjeva može ostati sačuvano nakon oslobađanja memorije. Kasniji zahtjev u istom workeru može ga iskoristiti prije nego što se vrati na početno stanje. To se odnosi na korak 7, čišćenje. Pozadina je na stranici [CVE-2026-109619](https://phpsos.de/hr/php2shell/cve-2026-109619/) i u članku o [životnom ciklusu zahtjeva](https://phpsos.de/hr/php/request-lebenszyklus/).

Iz toga slijedi: zaštitne mjere u kodu aplikacije, na primjer sigurnosni dodaci, djeluju tek u koraku 6. Kod mod_php-a je prema PHP timu čak pokazan exploit prije nego što se uopće izvrši kod aplikacije. Djelotvorno je samo ažuriranje PHP-a na 8.5.12, 8.4.27, 8.3.36 ili 8.2.35 i ponovno pokretanje svih PHP procesa, jer dugovječni workeri inače nastavljaju izvršavati stari kod.

## Kako PHP SOS konkretno pomaže?

- **Učiniti slijed vidljivim:** Utvrđujemo koji su način rada, konfiguracija i predmemorija na Vašem poslužitelju stvarno aktivni.
- **Ispravno ažurirati:** Instaliramo PHP ažuriranje i putem vremena pokretanja provjeravamo da više ne radi nijedan stari proces.
- **Osigurati slojeve:** U okviru [ojačavanja poslužitelja](https://phpsos.de/hr/leistungen/server-haertung/) ograničavamo veličine zahtjeva, memoriju i prava ondje gdje djeluju: ispred koda aplikacije.
- **Provjeriti tragove:** Kod nezaštićeno dostupnih poslužitelja tražimo znakove provale.


## Česta pitanja

**Prevodi li se PHP kod iznova pri svakom pozivu?**  
Bez predmemorije da: PHP rastavlja skriptu, gradi sintaktičko stablo i iz njega stvara opcodeove. S aktivnim OPcacheom opcodeovi se nalaze u zajedničkoj memoriji i ponovno se koriste dok se datoteka ne promijeni.

**Što ostaje u memoriji nakon zahtjeva?**  
U načelu se stanje zahtjeva na kraju čisti kako bi sljedeći zahtjev počeo čist. Dugovječne su samo stvari poput OPcachea ili trajnih veza. Upravo na tom čišćenju napada CVE-2026-109619.

**Zašto se PHP mora ponovno pokrenuti nakon ažuriranja?**  
Kod PHP-FPM-a i mod_php-a procesi rade neprekidno i učitali su stari programski kod. Nove datoteke na disku tu ništa ne mijenjaju. Tek ponovno pokretanje učitava ispravljeni kod.

**Je li web-poslužitelj bez PHP-a sigurniji?**  
Ima manju površinu napada jer nikakva programska logika ne reagira na zahtjeve. Za isključivo statične sadržaje to je prava opcija. Ali za web-trgovine, obrasce i prijave treba jezik na strani poslužitelja, i tada je važno njegovo održavanje.

## Izvori

- [PHP priručnik: Uvod](https://www.php.net/manual/en/introduction.php)
- [PHP RFC: Abstract Syntax Tree](https://wiki.php.net/rfc/abstract_syntax_tree)
- [PHP RFC: JIT](https://wiki.php.net/rfc/jit)
- [PHP priručnik: OPcache](https://www.php.net/manual/en/book.opcache.php)
