Worpress ist praktisch, wenn man manuell Seiten (Pages) erstellt und diese im Admin Bereich editieren möchte. Allerdings gibt es keine (mitgelieferte) Möglichkeit “virtuelle Seiten” unterzubringen.
Virtuelle Seiten?!
Nun rede ich hier von virtuellen Seiten, aber was verstehe ich darunter?
Im Prinzip ist die Idee ganz einfach: Der Webseitenbesucher soll keinen Unterschied zwischen einer virtuellen und einer “realen” Seite sehen – allerdings ist die virtuelle Seite nicht in der Wordpress Datenbank abgelegt.
Die Probleme
Aus dieser Aufgabenstellung ergeben sich folgende Probleme:
- Umleitung der Anfrage auf ein eigenes php-Skript
- Einbinden des Wordpress Layouts
- Erweitern der Navigation um die Virtuellen Seiten
Umleitung der Anfrage auf ein eigenes php-Skript
Auszug aus der .htaccess
1
2
3
4
| RewriteEngine On
RewriteBase /pfad/zu/meinem/blog/
RewriteRule ^uebung/([\w,=;\-]+)\.html$ ce_exercise.php?id=$1 [L]
RewriteRule ^uebung/?$ ce_exercise.php [L] |
In diesem Beispiel werden alle Anfragen auf /uebung, /uebung/, /uebung/xyz-abc-etc.html auf ce_exercise.php umgeleitet. ce_exercise.php bindet dann Wordpress ein und lädt die angeforderte Seite aus der (eigenen) Datenbank.
Einbinden des Wordpress Layouts
Mit
1
2
3
4
5
6
| define ( 'WP_USE_THEMES', false );
/** hier fehlt noch was! Siehe unten */
/** Loads the WordPress Environment and Template */
require ('./wp-blog-header.php'); |
wird Wordpress eingebunden (angenommen, dass wp-blog-header.php im selben Verzeichnis liegt).
define ( ‘WP_USE_THEMES’, false ); verhindert, dass Wordpress selbstständig wird und Theme Dateien lädt – Das wollen wir ja selbst machen!
Dies alleine reicht allerdings nicht aus, da Wordpress die url analysiert und trotzdem versucht den Inhalt der Seite zu laden. Da die angeforderte Seite virtuell ist wird Wordpress immer davon ausgehen, dass ein 404 (Seite nicht gefunden) vorliegt.
Dies lässt sich wie folgt lösen:
1
2
3
| /* confuse wordpress: make it think the url is something else */
preg_match ( '#(.*)/uebung/#', $_SERVER ['REQUEST_URI'], $treffer );
$_SERVER ['REQUEST_URI'] = $treffer [1] . "/uebung/"; |
Ich gebe zu, diese Lösung ist weder schön noch Zukunftssicher – aber sie funktioniert.
Wichtige Hinweise zu dieser Lösung:
- Ich verwende “schöne” permalinks mit mod_rewrite
- Es muss eine Seite angelegt werden, die auf die umgeschriebene url passt. Hier: /uebung/
- Der Code muss vor require (’./wp-blog-header.php’); stehen!
Der Anfang des php-Skriptes sieht dann so aus:
1
2
3
4
5
6
7
8
9
10
11
| error_reporting ( E_ALL );
define ( 'WP_USE_THEMES', false );
/* confuse wordpress: make it think the url is something else */
preg_match ( '#(.*)/uebung/#', $_SERVER ['REQUEST_URI'], $treffer );
$_SERVER ['REQUEST_URI'] = $treffer [1] . "/uebung/";
$requested_page = isset ( $_GET ['id'] ) ? $_GET ['id'] : "main";
/** Loads the WordPress Environment and Template */
require ('./wp-blog-header.php'); |
Nun können die Wordpress-Funktionen get_header (); get_sidebar (); und get_footer (); aufgerufen werden.
Damit ist das Problem des Layouts gelöst – bleibt noch:
Erweitern der Navigation um die Virtuellen Seiten
Wordpress stellt viele sogenannter “hooks” zur Verfügung, um die Ausgabe von Wordpress Funktionen zu beeinflussen. Diese Hooks werden auf den Resultaten der Wordpress Funktionen ausgeführt, nachdem die Wordpress Funktion fertig ist.
Vereinfacht kann man sich das so vorstellen:
1
2
| $reslut = wp_some_funtion();
$result = my_hook( $result ); |
Die Kunst besteht darin die richtige Wordpress Funktion auszuwählen. Ich hab hier auch einen unschönen aber schnellen und effektiven Weg gewhält: Ich modifiziere die Navigation, nachdem diese als HTML generiert wurde. Konkret: Ich verwende einen Hook auf wp_list_pages.
In meinem Fall möchte ich nur die Navigation der Sidebar beeinflussen und nicht die des Headers. Deshalb wird der Hook erst nach Ausgabe des Headers aufgerufen.
Jetzt bleibt nur noch das Hinzufügen der zusätzlichen Navigationselemente im Hook. Ich suche dazu nach dem Navigationseintrag, der “uebung” enthält und füge danach die virtuellen Seiten ein.
Der gesamte (auf das Wesentliche reduzierte) Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
error_reporting ( E_ALL );
/* verhindern, dass WP selbständig Themes lädt */
define ( 'WP_USE_THEMES', false );
/* confuse wordpress: make it think the url is something else */
preg_match ( '#(.*)/uebung/#', $_SERVER ['REQUEST_URI'], $treffer );
$_SERVER ['REQUEST_URI'] = $treffer [1] . "/uebung/";
$requested_page = isset ( $_GET ['id'] ) ? $_GET ['id'] : "main";
/** Loads the WordPress Environment and Template */
require ('./wp-blog-header.php');
get_header ();
// hier den eigentlichen Seiteninhalt ausgeben
// hier $added_pages_str mit den virtuellen Seiten füllen
add_filter ( 'wp_list_pages', 'ce_mod_pages_list', 1, 2 );
get_sidebar ();
get_footer ();
function ce_mod_pages_list($pages_str, $opt) {
global $added_pages_str, $requested_page;
$parts = preg_split ( "#</li>#", $pages_str );
foreach ( $parts as $key => $value ) {
if (strpos ( $value, "uebung" ) !== false) {
if ($requested_page != "main") {
$parts [$key] = str_replace ( "current_page_item", "", $parts [$key] );
}
$parts [$key] .= $added_pages_str;
break;
}
}
return implode ( "</li>", $parts );
} |
Schlussbemerkungen
- ce_ steht für CompuLearn Englisch
- Das Deutsch / Englisch Chaos in Code und Kommentaren ist ärgerlich aber nicht zu vermeiden.
- Oje, das ist ja ganz schön viel geworden – Ich hoffe jemand liest das und findet Anwendung dafür.
- Die Resultate können auf compulearnenglisch.de/uebung besichtigt werden.
- Fragen und Kommentare wie immer erwünscht.
- Listen machen alles übersichtlicher
