# Как PHP създава уебстраница: пътят на една заявка

> Как работи PHP? От клика в браузъра през уеб сървъра, SAPI, компилатора и Zend VM до готовата страница, обяснено в седем стъпки с примери.

Източник: https://phpsos.de/bg/php/wie-php-funktioniert/  
Актуалност: 25.10.2026  
Доставчик: PHP SOS, Спешна помощ за PHP и сигурност на сървъри. Незабавна помощ по WhatsApp: https://wa.me/491736494914?text=%D0%97%D0%B4%D1%80%D0%B0%D0%B2%D0%B5%D0%B9%D1%82%D0%B5%2C%20PHP%20SOS%2C%20%D0%B8%D0%BC%D0%B0%D0%BC%D0%B5%20%D0%BD%D1%83%D0%B6%D0%B4%D0%B0%20%D0%BE%D1%82%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%20%D1%81%20%D0%BD%D0%B0%D1%88%D0%B8%D1%8F%20PHP%20%D1%81%D1%8A%D1%80%D0%B2%D1%8A%D1%80.%20%D0%A4%D0%B8%D1%80%D0%BC%D0%B0%3A%20%E2%80%A6%20%D0%A3%D0%B5%D0%B1%D1%81%D0%B0%D0%B9%D1%82%3A%20%E2%80%A6

**Накратко:** Когато браузър поиска PHP страница, уеб сървърът приема заявката и я предава на PHP през интерфейс (SAPI). PHP превежда скрипта в байткод, изпълнява го в Zend Engine и връща резултата, най-често HTML, на уеб сървъра. След това състоянието на заявката се почиства, за да започне следващата начисто.

## Какво се случва, когато някой отвори Вашия уебсайт?

За посетителите това е един клик. На сървъра за милисекунди се изпълняват много стъпки. Който познава този процес, разбира по-добре защо актуализациите, рестартиранията и конфигурацията са толкова важни и защо уязвимост в самия PHP тежи повече от уязвимост в добавка.

Ръководството на PHP посочва три компонента, необходими за един PHP уебсайт: интерпретатор на PHP (като CGI или сървърен модул), уеб сървър и браузър. Интерпретаторът е програмата, която чете и изпълнява PHP кода. Начинът, по който е свързан с уеб сървъра, определя режима на работа.

## Как работи PHP? Седем стъпки на една заявка

1. **Заявка:** Браузърът изпраща HTTP заявка, например `GET /kontakt.php`, до сървъра.
2. **Уеб сървър:** Apache, Nginx или LiteSpeed приемат заявката. Статичните файлове като изображения те предоставят сами. За `.php` файловете извикват PHP.
3. **Предаване през SAPI:** Сървърният интерфейс (SAPI) предава на PHP данните от заявката, като заглавни редове, параметри и данни от формуляри. При PHP-FPM това става чрез протокола FastCGI, при mod_php директно в процеса на Apache. Подробности в [SAPI, обяснен](https://phpsos.de/bg/php/sapi-erklaert/).
4. **Подготовка на заявката:** PHP поставя данните от заявката в променливи като `$_GET`, `$_POST`, `$_COOKIE` и `$_FILES` и резервира памет за заявката.
5. **Превеждане:** Скриптът се разчленява на градивни елементи (токени), от тях се получава абстрактно синтактично дърво (AST) и от него опкодове, един вид машинен език за PHP. Ако OPcache е активен, тази стъпка се прескача, когато скриптът вече е в кеша.
6. **Изпълнение:** Виртуалната машина на [Zend Engine](https://phpsos.de/bg/php/zend-engine/) обработва опкодовете, отправя заявки към бази данни, чете файлове и създава изхода.
7. **Отговор и почистване:** Изходът се връща през SAPI към уеб сървъра и оттам към браузъра. След това PHP освобождава паметта на заявката и нулира състоянието.

AST съществува от PHP 7. Според свързания RFC преди това парсерът създавал опкодовете директно по време на четенето; разделянето на три фази направило компилатора по-лесен за поддръжка.

## Пример: какво вижда скриптът от заявката

Следният безобиден скрипт показва каква информация PHP получава от заявката и в какъв режим на работа се изпълнява:

```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";
```

На сървър с PHP-FPM `PHP_SAPI` извежда стойността `fpm-fcgi`, при Apache с mod_php `apache2handler`. Поставяйте такива проверочни файлове в публичната директория само за кратко и никога за постоянно, защото данните за версията помагат и на атакуващите да се ориентират.

## Къде се включват кешът за байткод и JIT

Превеждането в стъпка 5 отнема време. [OPcache](https://phpsos.de/bg/php/opcache/) според ръководството съхранява предварително компилиран байткод в споделената памет и така спестява на PHP зареждането и разчленяването на скриптовете при всяка заявка. От PHP 8.0 допълнително JIT компилатор може да създава от опкодовете истински машинен код. Според JIT-RFC той е почти самостоятелна част от OPcache.

| Фаза | Резултат | Кешира ли се? |
|---|---|---|
| Лексикален анализ | поток от токени | не |
| Синтактичен анализ | абстрактно синтактично дърво (AST) | не |
| Компилиране | опкодове (op-масиви за всеки файл и функция) | да, в OPcache |
| JIT (по избор) | машинен код | да, в паметта на OPcache |
| Изпълнение | изход на страницата | не |

Кешът засяга само преведения код. Данните на отделната заявка, например въведените във формуляри стойности или стойностите на сесията, не се споделят през OPcache.

## Защо PHP2Shell засяга точно този процес

Двете уязвимости на PHP2Shell не засягат отделно приложение, а самия процес. При CVE-2026-109618 състояние на изчерпана памет (out-of-memory) може да прекъсне PHP, докато данните от заявката са подготвени само частично, т.е. в стъпка 4. При последвалото почистване невалидни данни могат да бъдат третирани като валидни.

При CVE-2026-109619 вътрешно състояние на заявка може да остане след освобождаването на паметта. По-късна заявка в същия работен процес може да го използва, преди то да бъде нулирано. Това засяга стъпка 7, почистването. Предистория има на страницата [CVE-2026-109619](https://phpsos.de/bg/php2shell/cve-2026-109619/) и в статията за [жизнения цикъл на заявката](https://phpsos.de/bg/php/request-lebenszyklus/).

От това следва: защитните мерки в кода на приложението, например защитни добавки, действат едва в стъпка 6. При mod_php според екипа на PHP е показан експлойт още преди изобщо да се изпълни код на приложението. Действа само актуализацията на PHP до 8.5.12, 8.4.27, 8.3.36 или 8.2.35 и рестартиране на всички PHP процеси, защото дълготрайните работни процеси иначе продължават да изпълняват стария код.

## Как помага PHP SOS конкретно?

- **Показване на процеса:** Установяваме кой режим на работа, коя конфигурация и кой кеш са действително активни на Вашия сървър.
- **Правилна актуализация:** Внасяме актуализацията на PHP и чрез времето на стартиране проверяваме, че вече не работи стар процес.
- **Защита на слоевете:** В рамките на [заздравяването на сървъра](https://phpsos.de/bg/leistungen/server-haertung/) ограничаваме размерите на заявките, паметта и правата там, където действат: пред кода на приложението.
- **Проверка за следи:** При сървъри, достъпни без защита, търсим признаци за пробив.


## Често задавани въпроси

**Превежда ли се PHP кодът наново при всяко извикване?**  
Без кеш да: PHP разчленява скрипта, изгражда синтактично дърво и от него създава опкодове. При активен OPcache опкодовете лежат в споделената памет и се използват повторно, докато файлът не се промени.

**Какво остава в паметта след една заявка?**  
По принцип състоянието на заявката се почиства накрая, за да започне следващата заявка начисто. Дълготрайни са само неща като OPcache или постоянните връзки. Именно в това почистване се намесва CVE-2026-109619.

**Защо PHP трябва да се рестартира след актуализация?**  
При PHP-FPM и mod_php процесите работят постоянно и са заредили стария програмен код. Новите файлове на диска не променят това. Едва рестартирането зарежда поправения код.

**По-сигурен ли е уеб сървър без PHP?**  
Той има по-малка повърхност за атака, защото никаква програмна логика не реагира на заявките. За чисто статично съдържание това е реална възможност. За магазини, формуляри и влизане в система обаче е нужен език от страна на сървъра и тогава значение има неговата поддръжка.

## Източници

- [Ръководство на PHP: Въведение](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: OPcache](https://www.php.net/manual/en/book.opcache.php)
