5.2 Serverseitige Verarbeitung mit PHP (Shoutbox)

Serverseitig werden die jeweils 10 jüngsten Einträge der Shoutbox in einer XML-Datei namens shoutbox.xml gespeichert. Diese XML-Datei hat folgendes Aussehen (Beispiel):

<?xml version="1.0" encoding="UTF-8"?>
<shoutbox>
<entry datetime="2007-02-14 14:54">
<name>Simon</name>
<text>Er wird immer in uns leben!</text>
</entry>
<entry datetime="2007-02-14 12:01">
<name>vertigo</name>
<text>Wat denn, wer wird denn gleich heulen? Elvis is halt nich 
mehr unter uns, aber solang wir seine Songs singen, gibts 
keinen Grund zur Trauer</text>
</entry>
<!-- weitere Einträge -->
</shoutbox>

Das Dokumentelement heißt shoutbox. Es enthält für jeden Shoutbox-Eintrag ein Kindelement namens entry. Jedes entry-Element hat ein Attribut namens datetime, in dem der Zeitstempel des Shoutbox-Eintrags festgehalten wird. Der Name des Eintragenden und sein Text werden in den beiden Kindelementen name und text gespeichert.

Das serverseitige PHP-Script namens shoutbox.php, das diese XML-Datei verwaltet, hat folgende Aufgaben:

Wenn es ohne POST-Parameter aufgerufen wurde, also keine neuen Shoutbox-Daten eingegeben wurden, dann liest es die XML-Datei einfach ein und gibt ihren Inhalt aus. Die Ajax-Schnittstelle von JavaScript erhält dann in der Eigenschaft responseXML des XML-HTTP-Objekts automatisch eine DOM-Objektversion des Dateiinhalts.

Findet das PHP-Script dagegen POST-Daten für Felder mit den Namen name und text vor, muss es die XML-Datei zunächst aktualisieren, bevor es sie ausgibt. Für die Aktualisierung wählen wir die DOM-Funktionalität von PHP 5.

<?php
if(isset($_POST['name']) and isset($_POST['text']) 
and $_POST['name'] != "" and $_POST['name'] != "Dein Name?" 
and $_POST['text'] != "" and $_POST['name'] != "Dein Text?") {
   $dom = new DOMDocument("1.0", "UTF-8");
   if(!$dom)
      exit("FEHLER(1)!");
   $dom->preserveWhiteSpace = false;
   if(!$dom->load("shoutbox.xml")) {
      $shoutbox = $dom->createElement("shoutbox");
      $dom->appendChild($shoutbox);
   }
   $new_entry_elem = $dom->createElement("entry");
   $new_entry_elem->setAttribute("datetime", date("Y-m-d H:i"));
   $new_name_elem = $dom->createElement("name", 
                    substr($_POST['name'], 0, 256));
   $new_text_elem = $dom->createElement("text", 
                    substr($_POST['text'], 0, 1024));
   $new_entry_elem->appendChild($new_name_elem);
   $new_entry_elem->appendChild($new_text_elem);
   $shoutbox_elem = get_node($dom, '/shoutbox');
   if($shoutbox_elem->firstChild)
      $shoutbox_elem->insertBefore($new_entry_elem, 
                      $shoutbox_elem->firstChild);
   else
      $shoutbox_elem->appendChild($new_entry_elem);
   $i = 0;   
   $entry_elems = $dom->getElementsByTagName('entry');
   if($entry_elems->length > 10)
       $shoutbox_elem->removeChild($shoutbox_elem->lastChild);
   $dom->save("shoutbox.xml");
}
$content = file_get_contents("shoutbox.xml");
header('Content-Type: text/xml');
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
echo $content;
 
function get_node($dom, $xpath) {
   $path = new DOMXPath($dom);
   $nodes = @$path->query($xpath);
   if(!is_object($nodes))
      return(false);
   else
      return($nodes->item(0));
}
?>

Das Script ermittelt zunächst, ob POST-Daten mit den Feldnamen name und text vorliegen, ob diese nicht leer sind, und ob sie einen anderen Wert haben als in HTML per Default definiert wurde. Ist das der Fall, kann die Datenverarbeitung starten. Dazu wird zunächst eine neue Instanz der DOM-Objektklasse erzeugt und in der Objektvariablen $dom gespeichert.

Mit $dom->load("shoutbox.xml") wird die XML-Datei mit den Shoutbox-Daten direkt in die DOM-Struktur eingelesen. Da aufgrund der POST-Daten ein neuer Shoutbox-Eintrag vorliegt, muss dafür erst einmal ein neues entry-Element mitsamt datetime-Attribut und den Kindelementen name und text erzeugt werden. Das Script verwendet die dazu üblichen DOM-Methoden createElement(), setAttribute() sowie die Methode appendChild() zum Zusammenbauen der XML-Struktur des neuen Shoutbox-Eintrags.

Interessant wird es beim Einbauen des neuen Eintrags in die vorhandene XML-Struktur. Denn der neue Eintrag soll nicht angehängt werden, sondern an oberster Stelle stehen. Mit unserer Hilfsfunktion get_node(), die den XPath-Zugriff auf bestimmte Knoten der XML-Struktur realisiert, speichern wir in $shoutbox_elem den DOM-Knoten des Dokumentelements und ordnen das neu erzeugte entry-Element durch Aufruf von $shoutbox_elem->insertBefore($new_entry_elem, $shoutbox_elem->firstChild); als ersten neuen Kindknoten ein.

Wenn die XML-Datei jedoch bereits 10 Shoutbox-Einträge enthielt, muss der älteste gelöscht werden, damit es auch weiterhin nur 10 Einträge bleiben. Das erreichen wir durch $shoutbox_elem->removeChild ($shoutbox_elem->lastChild). Mit $dom->save("shoutbox.xml") wird die aktualisierte DOM-Struktur in XML-Datei zurückgeschrieben.

Egal ob POST-Daten vorliegen oder nicht: in jedem Fall liest das Script shoutbox.php den aktuellen Stand der shoutbox.xml aus und gibt ihn mit echo aus. Die Ajax-Schnittstelle von JavaScript erhält damit ein wohlgeformtes XML-Dokument, das sie in der responseXML-Eigenschaft als DOM-Struktur zur Verfügung stellt.

Sofern nicht anders angegeben, steht der Inhalt dieser Seite unter Lizenz Creative Commons Attribution-ShareAlike 3.0 License