Software Guide

Die besten Tipps, Anleitungen und Downloads

Ihre Werbung auf Software Guide

Sie möchten in dieser Box oder an anderer Stelle dieser Webseiten eine Werbung schalten? Sehen Sie sich dazu am besten einfach mal die verschiedenen Möglichkeiten an.


Multi-(Sub-)Domain-Blog, CMS oder Wiki

30. Mai 2007 von Michael | Webmaster/CMS/Blog

Wer auf mehreren unterschiedlichen Webseiten das gleiche Blog-System, CMS oder Wiki einsetzt, der kann ein Lied davon singen wie langweilig bzw. nervig es ist, auf den jeweiligen Seiten regelmäßige Updates der Software einzuspielen (neue Version, Sicherheitsupdate, Plug-in-Update u.v.m.).

Daher würde sich anbieten, mit nur einer einzigen Installation beliebig viele (Sub-)Domains zu versorgen:
Domains

Werden alle Webseiten (egal ob Subdomains oder unterschiedliche Domains) beim selben Hoster betrieben, so kann man dies in der Tat relativ einfach umsetzen: im Herbst 2006 hatte Erik Range mit dem Artikel «Multi-(Sub)Domain-WordPress» gezeigt, wie man die Konfigurationsdatei des Blog-Systems WordPress anpasst, um mit nur einer einzigen WordPress-„Installation“ (also die WordPress-Dateien auf dem Webserver) prinzipiell eine beliebige Anzahl an Blogs versorgt – die Datenbank-Daten für die einzelnen Blogs stammen dabei aus einer oder mehreren MySQL-Datenbanken.

Allerdings gibt es da noch mehrere Stolpersteine, die es zu beseitigen gilt. Im Folgenden gehe ich darauf ein, wie man das ganze mit einem beliebigen CMS, Blog oder Wiki einrichtet. Ich erläutere das ganze anhand dem Blog-System WordPress, die Umsetzung mit anderen Systemen ist analog.

Ausgangssituation

Ich gehe im Folgenden davon aus, dass 4 Blogs unter unterschiedlichen Domains beim selben Hoster betrieben werden (sw-guide.de, blogwartung.de, ferienhaus-schleching.de, fitlog.de). Als Blog-System wird WordPress eingesetzt, zudem nutzt jede Webseite noch das Webstatistik-Tool chCounter.

All diese Blogs sollen nun von einem zentralen Verzeichnis versorgt werden, welches die Dateien des Blog-Systems, des Statistik-Tools, die einzelnen Themes (Templates), eingesetzte Plugins, etc. enthält. Bei fälligen Updates etc. soll dann nur dieses eine Verzeichnis aktualisiert werden, womit alle Blogs gleichzeitig das Update erfahren. Auch neu hochgeladene Plugins und Themes sollen in allen 4 Blogs erreichbar sein, dennoch kann man je Blog individuell wählen, welches Theme und welche Plugins man für das jeweilige Blog verwenden möchte.

Umsetzung

Änderung der Verzeichnispfade

Grundsätzlich ist es notwendig, dass sämtliche (Sub-)Domains, die das eine Verzeichnis nutzen sollen, serverseitig auf dieses verweisen. Je nach Webserver/Hoster kann dies entsprechend umgesetzt werden. Bei manchen Hostern kann man dies über die Optionen einstellen (Beispiel Domainfactory, Virtual Server):
Domainfactory

Oder man hat etwa die Rechte, die Datei httpd.conf direkt zu ändern, dann verweist man über DocumentRoot jeweils auf dasselbe Verzeichnis.

Datenbanken

Als nächstes wird die Datei wp-config.php bearbeitet. Jetzt kommt es darauf an: will man alle 4 Webseiten in einer Datenbank haben, oder in 4 verschiedenen Datenbanken:

  1. Alle 4 Blogs in einer mySQL-Datenbank:
    Hier sollten jetzt die Tabellen als Präfix den Hostnamen ohne TLD-Endung enthalten, also sw-guide, blogwartung, fitlog und ferienhaus-schleching. Achtung: Normaler Bindestrich (Minus) „-“ ist in Tabellennamen nicht zulässig, daher am besten einen Unterstrich „_“ dafür verwenden. Bei einer bestehenden WordPress-Installation (Tabellen-Präfix „wp_“) kann man folgende MySQL-Befehle ausführen (z.B. in phpMyAdmin), um als neues Präfix „sw_guide“ zu erhalten:

    ALTER TABLE wp_categories RENAME AS sw_guide_categories;
    ALTER TABLE wp_comments RENAME AS sw_guide_comments;
    ALTER TABLE wp_link2cat RENAME AS sw_guide_link2cat;
    ALTER TABLE wp_links RENAME AS sw_guide_links;
    ALTER TABLE wp_options RENAME AS sw_guide_options;
    ALTER TABLE wp_post2cat RENAME AS sw_guide_post2cat;
    ALTER TABLE wp_postmeta RENAME AS sw_guide_postmeta;
    ALTER TABLE wp_posts RENAME AS sw_guide_posts;
    ALTER TABLE wp_usermeta RENAME AS sw_guide_usermeta;
    ALTER TABLE wp_users RENAME AS sw_guide_users;
    UPDATE sw_guide_options SET option_name = replace(option_name, 'wp_user_roles', 'sw_guide_user_roles');
    UPDATE sw_guide_usermeta SET meta_key = replace(meta_key, 'wp_user_level', 'sw_guide_user_level');
    UPDATE sw_guide_usermeta SET meta_key = replace(meta_key, 'wp_capabilities', 'sw_guide_capabilities');

    Die letzten 3 Zeilen sind in WordPress übrigens notwendig, weil seltsamerweise davon Benutzerrechte abhängig sind und das Präfix in die Datenbank übernommen wurde. Werden Plugins verwendet, die zusätzliche Tabellen verwenden (z.B. Simple Tagging Plugin verwendet ‚wp_stp_tags‘), so ist der obenstehende Code entsprechend zu erweitern, um auch diese Tabellen zu berücksichten.

    Nun sorgt man dafür, dass alle Tabellen in eine Datenbank übernommen werden, z.B. per Export/Import über das Tool phpMyAdmin.

    Als nächstes macht man nun in der Datei wp-config.php eine Fallunterscheidung: je nach Domain sollen die entsprechenden Tabellen verwendet werden, wird also z.B. blogwartung.de aufgerufen, so sollen die Tabellen mit dem Präfix „blogwartung_“ verwendet werden. Man ersetzt daher in der Datei wp-config.php die Zeile $table_prefix = 'wp_'; durch

    $arrPrefix = explode( '.', $_SERVER['HTTP_HOST'] );  
    $table_prefix = str_replace('-', '_', $arrPrefix[0]) . '_';

    Anhand $_SERVER['HTTP_HOST'] wird dabei geprüft, welche Seite der Besucher aufgerufen hat (also sw-guide.de, blogwartung.de, etc.), und entsprechend wird die zugehörige Tabelle zugeordnet.
    Weitere Beispiele für unterschiedlichste Konstellationen (mehrere Subdomains, Domains, etc.) gibt es im schon erwähnten Artikel «Multi-(Sub)Domain-WordPress».

  2. 4 verschiedene Datenbanken:
    Möchte man die Blogs aus 4 verschiedene Datenbanken versorgen, so kann man dies in der wp-config.php wie folgt umsetzen:

    if ( stripos($_SERVER['HTTP_HOST'], 'sw-guide') ) {
    	define('DB_NAME', 'sw-guide');
    	define('DB_USER', 'user');
    	define('DB_PASSWORD', 'pass');
    	define('DB_HOST', 'localhost');
    } elseif ( stripos($_SERVER['HTTP_HOST'], 'blogwartung') ) {
    	define('DB_NAME', 'blogwartung');

    Dies ist nur ein Code-Auszug und ersetzt die Datenbank-Definitionen in der wp-config.php. Zur Umsetzung sind rudimentäre PHP-Kenntnisse erforderlich, wer hier nicht weiterkommt, schaut sich am besten mal das Kapitel Kontroll-Strukturen im PHP-Handbuch an. Grundsätzlich ist auch hier die Strategie, ‚HTTP_HOST‘ abzufragen und über eine Fallunterscheidung die entsprechenden Datenbank-Daten zu definieren.

Dateien im Root-Verzeichnis umbiegen

Im Idealfall haben wir jetzt schon mal dem Blog-System beigebracht, je nach Domain die entsprechenden Datenbank-Inhalte zu verwenden. Da wir aber jetzt ein Hauptverzeichnis für 4 Domains haben, stehen wir vor einem weiteren Problem:
Die Dateien robots.txt, favicon.ico und sitemap.xml werden im Hauptverzeichnis erwartet, sind aber pro Blog unterschiedlich. Ist aber kein wirkliches Problem, wir können bei einem Apache-Webserver, der mod_rewrite unterstützt, folgenden Code in der .htaccess verwenden:

RewriteRule ^favicon.ico$ /_data/%{HTTP_HOST}_favicon.ico [L]
RewriteRule ^robots.txt$ /_data/%{HTTP_HOST}_robots.txt [L]
RewriteRule ^sitemap.xml$ /_data/%{HTTP_HOST}_sitemap.xml [L]

Zudem speichern wir diese Dateien z.B. im Unterverzeichnis „_data“ ab, und als Dateinamen verwenden wir sw-guide.de_favicon.ico, sw-guide.de_robots.txt, etc. Ein Aufruf von sw-guide.de/favicon.ico verweist dann automatisch auf sw-guide.de/_data/sw-guide.de_favicon.ico, keiner bekommt also dadurch mit, dass sich etwa das Favicon gar nicht im Hauptverzeichnis befindet, sondern in „_data“ und unter einem anderen Namen.

Weitere Verzeichnisse ändern

Je nach Blog-System und CMS haben wir ein paar weitere Verzeichnisse, die man ggf. aufsplitten muss. Etwa bei WordPress werden standardmäßig alle Uploads unter /wp-content/uploads gespeichert. Hier nun von 4 verschiedenen Blogs alle Upload-Dateien abzulegen, ist u.U. nicht sinnvoll. Maßnahmen:

  • In der WP-Administration unter «Einstellungen > Verschiedene» den Pfad unter «Uploads in folgendem Ordner speichern:» anpassen, am besten wieder mit Domain-Bestandteil im Verzeichnis-Namen, also etwa uploads_sw-guide, uploads_blogwartung, etc.
  • Alle Upload-Ordner der Blogs entsprechend umbenennen und per FTP in das wp-content-verzeichnis hochladen.
  • Alle bestehenden Verweise auf die Upload-Verzeichnisse in der MySQL-Datenbank anpassen, im Folgenden ein Beispielcode für sw-guide:
    UPDATE sw_guide_comments SET comment_content = replace(comment_content, 'wp-content/uploads', 'wp-content/uploads_sw-guide');
    UPDATE sw_guide_options SET option_value = replace(option_value, 'wp-content/uploads', 'wp-content/uploads_sw-guide');
    UPDATE sw_guide_postmeta SET meta_value = replace(meta_value, 'wp-content/uploads', 'wp-content/uploads_sw-guide');
    UPDATE sw_guide_posts SET post_excerpt = replace(post_excerpt, 'wp-content/uploads', 'wp-content/uploads_sw-guide');
    UPDATE sw_guide_posts SET post_content = replace(post_content, 'wp-content/uploads', 'wp-content/uploads_sw-guide');
    UPDATE sw_guide_posts SET guid = replace(guid, 'wp-content/uploads', 'wp-content/uploads_sw-guide');

.htaccess-Anpassungen

Durch die Zusammenführung von 4 Webseiten gibt es auch nur noch eine einzige .htaccess-Datei, daher muss man diese nun auch zusammenführen. Hat man darin spezifische Anpassungen für eine bestimmte Webseite vorgenommen, so sollte man dies eingrenzen. Im Folgenden ein Beispiel, bei dem nur für sw-guide die Seite sw-guide.de/impressum/ auf sw-guide/about/ weitergeleitet werden soll, nicht jedoch für die anderen Seiten (blogwartung etc.):

RewriteCond %{HTTP_HOST} ^.*sw-guide.*$ [NC]
RewriteRule ^impressum/?$ /about/ [L,R=301]

Klappt das auch wirklich?

Ich hatte im Eigenversuch sw-guide.de, blogwartung.de, ferienhaus-schleching.de und fitlog.de erfolgreich auf ein zentrales WordPress-Verzeichnis umgestellt und in diesem Zuge auch alle Seiten auf WordPress 2.2 aktualisiert. Die Seiten laufen nun schon mehrere Tage fehlerfrei und reibungs- und konfliktlos.
Daher kann ich dies wirklich jedem empfehlen, der mehrere Webseiten mit dem selben Content-Management-, Blog-System oder Wiki betreibt: man spart u.a. enorm viel Zeit bei Updates ein, zudem verringert sich der Backup-Aufwand. Und es ist einfach nur komfortabel: ich habe nun z.B. alle Plugins zentral in einem Verzeichnis, bei Aktualisierungen lade ich das Plugin nur einmal hoch; ich kann deswegen trotzdem nach wie vor entscheiden, welches Plugin ich in welchem Blog einsetzen möchte.

Analog zur beschriebenen Vorgehensweise habe ich übrigens auch das Webstatistik-Tool chCounter zentral installiert und es wird für alle 4 Blogs getrennt voneinander verwendet, die config.inc.php sieht bei mir in diesem Fall wie folgt aus:

$arrPrefix = explode( '.', $_SERVER['HTTP_HOST'] );  
$table_prefix = str_replace('-', '_', 'chc_' . $arrPrefix[0]) . '_';
$_CHC_DBCONFIG = array(
	'server' => 'server',
	'user' => 'user',
	'password' => 'pass',
	'database' => 'datenbank',
	'tables_prefix' => $table_prefix
);

Das heißt die Counter-Daten der 4 Blogs werden alle in einer Datenbank gespeichert und erhalten wieder je nach Domain unterschiedliche Tabellen-Präfixe.

Funktioniert das auch mit dem CMS xyz?

Ich habe es bisher nur mit WordPress und chCounter getestet, bin mir aber ziemlich sicher, dass dies auch mit vielen anderen CMS, Wikis oder Blog-Systemen klappt, zumindest die auf PHP/MySQL basieren, was die große Mehrheit ist. Zickt ein CMS, weil es etwa im Root domainspezifische Dokumente erwartet, so kann man evtl. mit .htaccess-Rewrites tricksen, so wie das oben bereits für favicon.ico etc. beschrieben ist.

Letztendlich empfehle ich, das ganze lokal zu testen und auch mehrere lokale (Sub-)Domains einzurichten, damit man dies einigermaßen vernünftig testen kann. Vor der Produktivsetzung natürlich ein Backup nicht vergessen.

Informationen zum Artikel:

Weiterblättern im Blog:

Was ist ein Trackback?

13 Trackbacks/Pings:

  • 1

    -=Discobeats=-

    Trackback vom 30. Mai 2007, 6:20


    Fatal error: Uncaught Error: Call to undefined function eregi_replace() in /kunden/151212_80993/webseiten/wp/wp-content/themes/sw-guide2/functions.theme.php:465 Stack trace: #0 /kunden/151212_80993/webseiten/wp/wp-content/themes/sw-guide2/comments.php(84): swg_formatCommentExcerpt('<strong>HowTo: ...', 180) #1 /kunden/151212_80993/webseiten/wp/wp-includes/comment-template.php(1471): require('/kunden/151212_...') #2 /kunden/151212_80993/webseiten/wp/wp-content/themes/sw-guide2/index.php(148): comments_template() #3 /kunden/151212_80993/webseiten/wp/wp-includes/template-loader.php(74): include('/kunden/151212_...') #4 /kunden/151212_80993/webseiten/wp/wp-blog-header.php(19): require_once('/kunden/151212_...') #5 /kunden/151212_80993/webseiten/wp/index.php(17): require('/kunden/151212_...') #6 {main} thrown in /kunden/151212_80993/webseiten/wp/wp-content/themes/sw-guide2/functions.theme.php on line 465