# OPcache vysvetlená: bytecode cache PHP

> OPcache vysvetlená: ako pracuje bytecode cache PHP, ktoré nastavenia sú dôležité, prečo sa po aktualizáciách musí vyprázdniť a ako ju zabezpečiť.

Zdroj: https://phpsos.de/sk/php/opcache/  
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:** OPcache je vstavaná bytecode cache PHP. Podľa príručky ukladá vopred skompilovaný bytecode do zdieľanej pamäte, takže PHP nemusí skripty pri každej požiadavke znova načítavať a prekladať. Je súčasťou balíka od PHP 5.5.0. OPcache robí PHP rýchlejším, ale nenahrádza aktualizáciu: po záplate PHP sa musia reštartovať všetky procesy PHP, nestačí vyprázdniť cache.

## Čo presne OPcache robí?

Pri každej požiadavke musí PHP skript prečítať, rozložiť a preložiť na opcódy, teda príkazy pre virtuálny stroj [Zend Engine](https://phpsos.de/sk/php/zend-engine/). Pri CMS so stovkami súborov je to veľa práce, ktorá sa neustále opakuje.

OPcache ukladá výsledok tohto prekladu do zdieľanej pamäte (Shared Memory). Pristupujú k nej všetky workery služby PHP-FPM alebo všetky procesy Apache s mod_php. Ak sa súbor nezmení, jeho bytecode sa použije priamo znova.

OPcache sa načítava ako rozšírenie Zend, nie ako bežné rozšírenie:

```ini
; Linux (cesta podľa balíka)
zend_extension=opcache.so
; Windows
; zend_extension=php_opcache.dll
```

Podľa príručky sa má OPcache načítať pred Xdebug, ak sú aktívne obe.

Dôležité je, komu zdieľaná pamäť patrí. Pri PHP-FPM ju vytvára hlavný proces (master) a využívajú ju všetky workery všetkých poolov tejto služby. Pri mod_php patrí hlavnému procesu Apache. Reštart služby preto cache vyprázdni úplne, jeden nový worker však nie. Pre príkazový riadok neexistuje zdieľaná pamäť medzi jednotlivými volaniami, pretože každé volanie je samostatný proces; tam je OPcache štandardne vypnutá.

Pre rozhodovateľov postačí pravidlo palca: OPcache je na produkčných serveroch takmer vždy užitočná, vyžaduje však jasný postup pri nasadzovaní a aktualizáciách.

## Ktoré nastavenia OPcache sú dôležité?

Nasledujúce hodnoty pochádzajú zo stránky konfigurácie v príručke PHP. Stĺpec „Meniteľné“ ukazuje, kde sa nastavenie smie zadať: `INI_SYSTEM` len v php.ini alebo v konfigurácii servera, `INI_ALL` všade.

| Direktíva | Štandard | Meniteľné | Význam |
|---|---|---|---|
| `opcache.enable` | 1 | INI_ALL | cache zapnutá alebo vypnutá, počas behu sa dá len vypnúť |
| `opcache.enable_cli` | 0 | INI_SYSTEM | cache pre príkazový riadok |
| `opcache.memory_consumption` | 128 | INI_SYSTEM | veľkosť zdieľanej pamäte v MB |
| `opcache.interned_strings_buffer` | 8 | INI_SYSTEM | pamäť pre spoločné reťazce znakov v MB |
| `opcache.max_accelerated_files` | 10000 | INI_SYSTEM | maximálny počet skriptov v cache |
| `opcache.validate_timestamps` | 1 | INI_ALL | kontroluje, či sa súbory zmenili |
| `opcache.revalidate_freq` | 2 | INI_ALL | interval kontroly v sekundách, 0 = pri každej požiadavke |
| `opcache.restrict_api` | prázdne | INI_SYSTEM | povoľuje funkcie API iba z jednej cesty |
| `opcache.validate_permission` | 0 | INI_SYSTEM | kontroluje práva súborov voči aktuálnemu používateľovi |
| `opcache.validate_root` | 0 | INI_SYSTEM | zabraňuje kolíziám názvov pri chroot |
| `opcache.file_cache` | prázdne | INI_SYSTEM | druhá úroveň cache na disku |

Typická produkčná konfigurácia by mohla vyzerať takto. Hodnoty si vopred overte so svojou aplikáciou:

```ini
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=60
opcache.restrict_api=/var/www/admin-tools
```

Kto nastaví `opcache.validate_timestamps=0`, získa trochu výkonu. OPcache potom však zmenené súbory vôbec nerozpozná a každé nasadenie vyžaduje reset cache alebo reštart.

## Sledovanie cache a cielené vyprázdnenie

OPcache prináša vlastné funkcie, medzi nimi `opcache_get_status()`, `opcache_get_configuration()`, `opcache_invalidate()` a `opcache_reset()`. Krátky pohľad na zaplnenie, len na čítanie:

```php
<?php
$status = opcache_get_status(false);
if ($status === false) {
    exit("OPcache ist nicht aktiv.\n");
}
printf("Gecachte Skripte: %d\n", $status['opcache_statistics']['num_cached_scripts']);
printf("Freier Speicher: %.1f MB\n", $status['memory_usage']['free_memory'] / 1048576);
```

Na serveroch s viacerými webmi by nemala každá aplikácia vedieť vyprázdniť alebo čítať cache všetkých ostatných. Na to slúži `opcache.restrict_api`: funkcie API smú volať iba skripty pod zadanou cestou.

## JIT: kompilátor strojového kódu v OPcache

Od PHP 8.0 obsahuje OPcache kompilátor JIT, ktorý prekladá opcódy na strojový kód. Podľa RFC k JIT je to takmer samostatná súčasť OPcache a vytvorený kód ukladá do vlastnej oblasti zdieľanej pamäte. Riadi sa pomocou `opcache.jit` a `opcache.jit_buffer_size`. Od PHP 8.4.0 je `opcache.jit` štandardne nastavený na `disable`. Kedy sa JIT oplatí, vysvetľuje príspevok [JIT a výkon v PHP 8](https://phpsos.de/sk/php/jit-und-performance/).

## OPcache a bezpečnosť: čo platí po PHP2Shell

OPcache nie je bezpečnostný nástroj, ale má dôsledky pre bezpečnosť. Po PHP2Shell sú dôležité tri body:

1. **Reset cache nie je aktualizácia.** `opcache_reset()` vyprázdni len skripty v cache. Interpreter so zraniteľnosťami CVE-2026-109618 a CVE-2026-109619 zostáva v pamäti, kým sa nereštartujú všetky procesy. Ako na to, je na stránke [Reštart PHP-FPM a všetkých workerov](https://phpsos.de/sk/php2shell/php-fpm-neustart/).
2. **Votknutý kód môže v cache žiť ďalej.** Ak bol súbor zmanipulovaný a neskôr nahradený, pri vypnutej kontrole časových pečiatok sa môže ďalej vykonávať stará verzia. Po vyčistení preto patrí k veci aj reštart.
3. **Zdieľaná pamäť vyžaduje oddelenie.** Na serveroch s viacerými zákazníkmi pomáhajú samostatné pooly PHP-FPM pre každý web, ako aj `opcache.validate_permission` a `opcache.restrict_api`. Adresár pre `opcache.file_cache` smie byť zapisovateľný iba pre používateľa PHP.

> **Tip:**
> Po každej aktualizácii skontrolujte, či je čas spustenia procesov PHP neskorší než aktualizácia. Plná OPcache s vysokou úspešnosťou nie je dôkazom, že beží nový interpreter.

## Ako konkrétne pomáha PHP SOS?

- **Skontrolovať konfiguráciu:** Zisťujeme aktívnu konfiguráciu OPcache podľa režimu prevádzky a porovnávame ju s vašou aplikáciou.
- **Zabezpečiť nasadzovanie:** Zavedieme pevný postup pre reset cache a reštart, aby nebežala žiadna stará verzia kódu.
- **Oddeliť klientov:** V rámci [zabezpečenia servera (hardening)](https://phpsos.de/sk/leistungen/server-haertung/) nastavujeme oddelené pooly, `restrict_api` a vhodné práva.
- **Kontrolovať po aktualizáciách:** Podľa časov spustenia procesov preukážeme, že aktualizovaný interpreter skutočne beží.


## Časté otázky

**Je OPcache štandardne aktívna?**  
OPcache sa dodáva s PHP od verzie 5.5.0 a podľa príručky beží s opcache.enable=1 ako štandard, len čo je rozšírenie načítané. To, či je načítané, závisí od vášho balíka alebo poskytovateľa hostingu. V príkazovom riadku je OPcache naopak štandardne vypnutá (opcache.enable_cli=0).

**Prečo po nasadení stále vidím starý kód?**  
Pravdepodobne OPcache kontroluje zmeny súborov len v intervaloch alebo vôbec. S opcache.revalidate_freq čaká štandardne dve sekundy, s opcache.validate_timestamps=0 nikdy. Vtedy pomôže iba reset cache alebo reštart PHP-FPM, resp. Apache.

**Stačí opcache_reset() po aktualizácii PHP?**  
Nie. opcache_reset() vyprázdni iba cache s preloženými skriptmi. Aktualizácia PHP nahrádza samotný interpreter a ten je načítaný v každom bežiacom procese. Preto sa musia reštartovať všetky procesy PHP.

**Je JIT v PHP 8.4 zapnutý?**  
Podľa príručky je opcache.jit od PHP 8.4.0 štandardne nastavený na disable, kým opcache.jit_buffer_size má 64M. Predtým to bolo naopak: jit na tracing, vyrovnávacia pamäť na 0. V oboch prípadoch nie je JIT bez vedomej konfigurácie aktívny.

## Zdroje

- [Príručka PHP: OPcache](https://www.php.net/manual/en/book.opcache.php)
- [Príručka PHP: Konfigurácia OPcache](https://www.php.net/manual/en/opcache.configuration.php)
- [Príručka PHP: Inštalácia OPcache](https://www.php.net/manual/en/opcache.installation.php)
- [PHP RFC: JIT](https://wiki.php.net/rfc/jit)
