von Robert Klikics 8 Min Lesezeit veröffentlicht 12. September 2026 zuletzt geändert 1. Oktober 2026
OPcache ist entweder an oder aus — so steht es in den meisten Anleitungen, und so melden es die meisten Werkzeuge. Tatsächlich gibt es mindestens fünf Zustände, die von außen gleich aussehen, und nur zwei davon sind ein Fehler der Installation. Die anderen drei sind Entscheidungen des Hosters oder eine Eigenschaft des Kontexts, in dem gerade gemessen wird.
Wer das verwechselt, schreibt Support-Tickets über Zustände, die in Ordnung sind. Oder er hält eine Installation für beschleunigt, die es nicht ist. Dieser Artikel stellt jeden Zustand nach und dokumentiert die Ausgabe, statt sie zu beschreiben.
Kurz gefasst
- OPcache hat fünf Zustände, die von außen gleich aussehen. Nur zwei davon — nicht installiert und abgeschaltet — sind ein Fehler der Installation.
- Steht
opcache_get_statusindisable_functions, meldet jedes Werkzeug „aus“, obwohl OPcache arbeitet.opcache_is_script_cached()beweist das Gegenteil. opcache.restrict_apisperrt die gesamte API: Auchopcache_get_configuration()undopcache_is_script_cached()liefern dann nur eine Warnung undfalse. Der ehrliche Befund lautet dann „unbekannt“, nicht „aus“.- Auf der Kommandozeile ist OPcache standardmäßig aus. Jede Messung über WP-CLI sagt deshalb nichts über die Website.
- Jeder Zustand am 22. August 2026 unter PHP 8.5 nachgestellt, mit der jeweiligen Ausgabe im Artikel.
Die Sonde
Alles, was ein Werkzeug über OPcache wissen kann, kommt aus vier Quellen: ob die Erweiterung geladen ist, was in den ini-Einstellungen steht, ob die API-Funktionen existieren, und was sie zurückgeben. Die folgende Sonde fragt genau das ab.
<?php
echo "extension_loaded : ", var_export( extension_loaded( 'Zend OPcache' ), true ), "\n";
echo "ini enable : ", var_export( ini_get( 'opcache.enable' ), true ), "\n";
echo "ini enable_cli : ", var_export( ini_get( 'opcache.enable_cli' ), true ), "\n";
echo "ini restrict_api : ", var_export( ini_get( 'opcache.restrict_api' ), true ), "\n";
echo "hat get_status : ", var_export( function_exists( 'opcache_get_status' ), true ), "\n";
if ( function_exists( 'opcache_get_status' ) ) {
$status = @opcache_get_status( false );
echo "get_status() : ", ( is_array( $status ) ? 'Array' : var_export( $status, true ) ), "\n";
}
$konf = function_exists( 'opcache_get_configuration' ) ? @opcache_get_configuration() : null;
echo "get_configuration: ", ( is_array( $konf ) ? 'Array' : var_export( $konf, true ) ), "\n";
echo "is_script_cached : ", var_export( @opcache_is_script_cached( __FILE__ ), true ), "\n";
echo "sapi : ", php_sapi_name(), "\n";Die Fehlerunterdrückung mit @ ist kein Schlamperei-Zeichen, sondern notwendig: Einer der fünf Zustände beantwortet den Aufruf mit einer Warnung, und ohne Unterdrückung landet die im Seitenquelltext.
Der Maßstab: OPcache arbeitet
extension_loaded : true
ini enable : '1'
ini enable_cli : '1'
ini restrict_api : ''
hat get_status : true
get_status() : Array, opcache_enabled=true
get_configuration: Array, enable=true
is_script_cached : true
sapi : cliSo sieht der Normalfall aus. Alle drei Auskunftsquellen sind sich einig. Gegen dieses Bild werden die anderen vier gelesen.
Zustand 1: nicht installiert
Fehlt die Erweiterung, ist extension_loaded('Zend OPcache') gleich false, und keine der opcache_*-Funktionen existiert. Jeder Aufruf ohne vorheriges function_exists() beendet die Anfrage mit einem fatalen Fehler.
Diesen Zustand konnte ich auf dem Testserver nicht nachstellen, und das ist selbst ein Befund. Alle fünf dort vorhandenen PHP-Bauten — 8.2 bis 8.5 — haben OPcache fest einkompiliert. Auch php -n -m, also ein Start ohne jede Konfigurationsdatei, listet Zend OPcache weiterhin auf. Wo PHP aus einem gepflegten Paket kommt, ist „nicht installiert“ deutlich seltener als die Ratgeber nahelegen; wahrscheinlicher ist einer der folgenden Zustände.
Zustand 2: geladen, aber abgeschaltet
php -d opcache.enable=0 -d opcache.enable_cli=1 sonde.php
extension_loaded : true
ini enable : '0'
ini enable_cli : '1'
hat get_status : true
get_status() : false
get_configuration: Array, enable=false
is_script_cached : falseDie Erweiterung ist da, die Funktionen sind da, und opcache_get_status() gibt false zurück. Das entscheidende Merkmal steht eine Zeile tiefer: opcache_get_configuration() antwortet, und in der Antwort steht enable=false. Die Konfiguration sagt selbst, dass sie aus ist.
Das ist neben Zustand 1 der einzige Fall, in dem tatsächlich nichts zwischengespeichert wird und in dem sich etwas ändern lässt. Hier lohnt das Ticket beim Hoster.
Zustand 3: aktiv, aber die Zähler sind gesperrt
Viele Hoster tragen opcache_get_status in disable_functions ein. Der Grund ist nachvollziehbar: Die Funktion verrät unter anderem die Liste aller zwischengespeicherten Dateipfade, und auf einem geteilten Server geht das niemanden etwas an.
php -d opcache.enable_cli=1 -d disable_functions=opcache_get_status sonde.php
extension_loaded : true
ini enable : '1'
hat get_status : false
get_status() : Funktion nicht vorhanden
get_configuration: Array, enable=true
is_script_cached : trueHier trennt sich die Spreu. Ein Werkzeug, das nur opcache_get_status() kennt, findet die Funktion nicht und meldet OPcache als nicht verfügbar. Zwei Zeilen weiter unten steht aber, dass die Konfiguration ihn als eingeschaltet führt — und die letzte Zeile beweist, dass er tatsächlich arbeitet: Die gerade ausgeführte Datei liegt im Cache.
Dieser Zustand ist keine Theorie. Der Server, auf dem turbopress.de läuft, ist selbst dieser Fall. Gemessen im Web-Kontext, also unter dem SAPI, unter dem auch die Besucher bedient werden:
sapi litespeed
extension_loaded true
ini_enable 1
ini_restrict_api
has_get_status false
has_get_config true
config_enable true
wp_settings_cached trueopcache_get_status() existiert nicht, und trotzdem liegt wp-settings.php nachweislich im Cache. Jedes Werkzeug, das hier „OPcache ist aus“ meldet, sagt etwas Falsches über eine Installation, an der nichts zu reparieren ist.
Zustand 4: aktiv, aber die API ist auf einen Pfad beschränkt
opcache.restrict_api erlaubt die API nur Skripten unterhalb eines bestimmten Verzeichnisses. Liegt dein Code woanders — und das tut er, wenn der Hoster den Pfad auf sein eigenes Kontrollpanel gesetzt hat —, sieht das so aus:
php -d opcache.enable_cli=1 -d opcache.restrict_api=/ein/anderer/pfad sonde.php
extension_loaded : true
ini enable : '1'
ini restrict_api : '/ein/anderer/pfad'
hat get_status : true
get_status() : Warnung — Zend OPcache API is restricted
by "restrict_api" configuration directive
get_configuration: false
is_script_cached : falseDas ist der unangenehmste Zustand, und er unterscheidet sich in einem wichtigen Punkt von Zustand 3: Die Sperre trifft die gesamte API. Ohne Fehlerunterdrückung geben sowohl opcache_get_configuration() als auch opcache_is_script_cached() dieselbe Warnung aus und liefern false.
Die verbreitete Empfehlung, im Zweifel eben opcache_get_configuration() zu nehmen, weil die Funktion die Sperren überlebe, stimmt also nur zur Hälfte. Sie überlebt disable_functions auf eine andere Funktion. Sie überlebt restrict_api nicht.
Das Erkennungsmerkmal ist deshalb die Kombination: Die Funktionen existieren alle, ini_get('opcache.restrict_api') ist nicht leer, und trotzdem antwortet keine von ihnen. In diesem Fall ist von innen nicht feststellbar, ob OPcache arbeitet. Die ehrliche Anzeige lautet dann „unbekannt“, nicht „aus“.
Zustand 5: die Kommandozeile
php sonde.php
extension_loaded : true
ini enable : '1'
ini enable_cli : '0'
hat get_status : true
get_status() : false
get_configuration: Array, enable=true
is_script_cached : false
sapi : cliStandardmäßig ist opcache.enable_cli auf 0. Für die Kommandozeile ist das richtig: Jeder Aufruf ist ein eigener Prozess, ein geteilter Speicher zwischen ihnen existiert nicht, ein Cache brächte nichts.
Praktisch heißt das: Jede Messung über WP-CLI ergibt „OPcache aus“, unabhängig davon, was der Webserver tut. Wer den Zustand einer Website erheben will, muss im Web-Kontext messen. Das Unterscheidungsmerkmal ist php_sapi_name(); steht dort cli, ist das Ergebnis für die Website ohne Aussage.
Die Zustände nebeneinander
| Zustand | Funktion vorhanden | get_configuration | is_script_cached | Website betroffen |
|---|---|---|---|---|
| aktiv | ja | Array, enable=true | true | nein |
| nicht installiert | nein | nicht vorhanden | nicht vorhanden | ja |
| abgeschaltet | ja | Array, enable=false | false | ja |
| Funktion gesperrt | nein | Array, enable=true | true | nein |
| API beschränkt | ja | false | false | unbekannt |
| Kommandozeile | ja | Array, enable=true | false | nur die Messung |
Die Spalte ganz rechts ist die, auf die es ankommt. Zwei Zeilen bedeuten, dass die Website tatsächlich langsamer läuft als nötig. Zwei bedeuten, dass alles in Ordnung ist und nur die Auskunft fehlt. Eine bedeutet, dass die Messung am falschen Ort stattfand.
Wo die Einschränkung konfiguriert ist
Wenn du in Zustand 3 oder 4 landest, lohnt der Blick, wo das eingetragen wurde — schon deshalb, weil ein Ticket mit der genauen Datei schneller beantwortet wird als eines mit „OPcache geht nicht“.
php -i | grep -E "^Loaded Configuration File|^Scan this dir"PHP liest zuerst eine Hauptdatei und danach jede .ini aus einem Verzeichnis, das oft php.d heißt. Panel-Systeme legen darüber hinaus je Domain eine eigene Datei an, und genau dort stand auf dem hier gemessenen Server die Zeile, die Zustand 3 auslöst:
disable_functions = "opcache_get_status"Eine einzige Zeile, gesetzt für diese eine Domain, und jedes Werkzeug, das die Zähler ausliest, meldet ab da einen Fehler, den es nicht gibt.
Ein Hinweis zum Argument dahinter: opcache_get_status() nimmt einen Parameter, der bestimmt, ob die Liste aller zwischengespeicherten Skripte mitkommt. Mit false liefert die Funktion nur Zähler — Trefferquote, belegter Speicher, Anzahl der Neustarts — und keine Pfade. Wer beim Hoster nachfragt, hat mit diesem Detail bessere Aussichten als mit der pauschalen Bitte, die Sperre aufzuheben.
Selbst nachsehen
Die Sonde von oben gehört in den Web-Kontext, nicht auf die Kommandozeile. Der kürzeste Weg dorthin ist eine Datei unter wp-content/mu-plugins/, die nur auf einen Parameter reagiert und danach wieder gelöscht wird:
<?php
add_action( 'shutdown', function () {
if ( ! isset( $_GET['opc'] ) || ! current_user_can( 'manage_options' ) ) {
return;
}
printf(
"<!-- sapi=%s geladen=%s status=%s konfig=%s gecacht=%s -->",
php_sapi_name(),
var_export( extension_loaded( 'Zend OPcache' ), true ),
var_export( function_exists( 'opcache_get_status' ), true ),
var_export( is_array( @opcache_get_configuration() ), true ),
var_export( @opcache_is_script_cached( ABSPATH . 'wp-settings.php' ), true )
);
}, 99999 );Der Aufruf erfolgt als angemeldeter Administrator mit angehängtem ?opc=1, und weil ein Seiten-Cache die Anfrage sonst beantwortet, gehört ein zufälliger zweiter Parameter dazu. Das Ergebnis steht als Kommentar im Quelltext.
Gelesen wird es in dieser Reihenfolge: Steht bei sapi etwas anderes als cli, ist die Messung überhaupt gültig. Ist geladen falsch, fehlt die Erweiterung. Ist gecacht wahr, arbeitet OPcache — egal, was die beiden Zeilen davor sagen. Ist gecacht falsch und konfig ebenfalls, dann sieh in ini_get('opcache.restrict_api') nach, bevor du irgendetwas meldest.
Turbopress Database Diagnostics unterscheidet diese fünf Zustände und nimmt die drei, die vom Hosting kommen, aus der Bewertung heraus, statt sie als Mangel der Installation zu zählen.
Wo OPcache in der Rangfolge der Dinge steht, die eine Antwortzeit bestimmen, steht hier: TTFB verbessern. Weitere Messungen aus derselben Reihe sammeln sich unter Wissen.
Welcher PHP-Handler OPcache bereitstellt und wie er konfiguriert ist, legt das Hosting fest. Bei turbopress läuft PHP über LSPHP; was sonst zum Stack gehört, steht im turbopress Tech-Stack.

