17.1. So funktioniert ein Rewrite

Wird eine individuelle Permalink-Struktur gewählt und abgespeichert, versucht WordPress eine .htaccess-Datei im Stammverzeichnis anzulegen. Sie enthält eine Rewrite-Regel für den Apache-Webserver.

# BEGIN WordPress
<IfModule mod_rewrite.c>
	RewriteEngine On
	RewriteBase /
	RewriteRule ^index\.php$ - [L]
	RewriteCond %{REQUEST_FILENAME} !-f
	RewriteCond %{REQUEST_FILENAME} !-d
	RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Hinweis
Die Rewrite-Regeln funktionieren nur out-of-the-box, wenn Apache als Webserver zum Einsatz kommt und wenn das Modul, welches für die Steuerung der Regeln zuständig ist, geladen wurde. Nutzt man beispielsweise nginx als Webserver, muss man die Konfiguration selbst vornehmen.

Die Regel ist relativ einfach. Sie leitet alles, was hinter der Domain in der URL angegeben wurde, an die index.php-Datei weiter. Es sei denn, es handelt sich um ein Verzeichnis oder um eine Datei, die auf dem Webserver existiert.

Ruft man also beispielsweise die Url https://meine-seite.com/wp-login.php auf, so wird die Regel keinen Rewrite bewirken, weil wp-login.php physisch existiert.

Anders sieht es mit der URL https://ihre-seite.com/2018/04/02/rewrite-api aus. In der WordPress-Grundinstallation existiert weder ein Verzeichnis mit dem Namen 2018 noch einen anderen Bestandteil nach der Domain. Deshalb wird der Webserver den String 2018/04/02/rewrite-api an die index.php leiten. Und WordPress kümmert sich dann um den Rest.

Im Kern ist die Klasse WP_Rewrite für alle weiteren Dinge zuständig. Wenn die Instanz der Klasse erstellt wird, lädt WordPress alle Regeln mittels get_option( 'rewrite_rules' ). Die Regeln werden also nicht mit jedem Abruf live erstellt sondern in der Datenbank zwischengespeichert. Sie werden nur dann neu aufgebaut, wenn die Option leer ist (also keinen Inhalt hat).

Hinweis:
Wenn ein Admin im WordPress-Dashboard unter „Einstellungen“ -> „Permalinks“ Einstellungen verändert und speichert, wird der Inhalt des Datenbank-Eintrags von rewrite_rules gelöscht. WordPress baut den Cache dann kurz darauf erneut auf.

Hinweis 2:
Eigentlich wird der Inhalt des Datenbank-Eintrags schon beim bloßen Besuchen der Permalinks-Einstellungsseite gelöscht (und nicht erst beim Speichern). Mir ist nicht bewusst, warum. Eventuell um mögliche Missverständnisse zu vermeiden. Es kommt nämlich regelmäßig vor, dass gecachte Regeln in der Datenbank bleiben obwohl es neue Regeln gibt. Das passiert beispielsweise regelmäßig nach der Aktivierung von WooCommerce. Neu angelegte Produkte lassen sich im Frontend nicht aufrufen. Zumindest nicht so lange, bis man den Permalink-Cache geleert hat. Und das klappt – wie beschrieben – einfach nur dadurch, dass man die Einstellungsseite einmalig aufruft.

Hinweis 3:

Im Quellcode von WordPress steht, dass die Rewrite-Regeln ein Mix aus „schwarzer Magie“ und regulären Ausdrücken wäre. Auf lustige Art und Weise würde ich dem sogar zustimmen. Das liegt daran, dass der Algorithmus dahinter sehr komplex ist. Beim Hinzufügen neuer Regeln werden beispielsweise so genannte Endpoint-Bitmasken verwendet, die später einen Bitweise-ODER-Vergleiche erlauben. Wenn Sie mehr darüber erfahren wollen, lesen Sie sich in den Code ein. Ich möchte an dieser Stelle auf die Funktionsweise eingehen, wie Rewrite-Regeln letztlich ausgewertet werden, sodass eine spezieller Aufruf entsteht.

Die Auswertung der Regeln übernimmt die Methode parse_request() der Klasse WP. Darin werden alle Rewrite-Regeln geladen und dann mittels einer For-Schleife so lange durchlaufen, bis die richtige Regel gefunden wurde. Im oben genannten Beispiel würde nachfolgende Regel zutreffen:

([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/([^/]+)(?:/([0-9]+))?/?$

Zerlegen wir die Regel, um sie etwas klarer darzustellen:

([0-9]{4}) / ([0-9]{1,2}) / ([0-9]{1,2}) / ([^/]+)(?:/([0-9]+))?/?$
Jahr			Monat		Tag		Post-Name

Aus diesem regulären Ausdruck, leitet WordPress die einzelnen Variablen ab und schreibt sie in ein Array:

array (
  'year' => '2018',
  'monthnum' => '04',
  'day' => '2',
  'name' => 'rewrite-api',
  'page' => '',
)

Diese Variablen werden dann an die Methode query() der Klasse WP_Query weitergeleitet, die daraus am Ende eine SQL-Abfrage macht.