Liveticker mit Ajax & PHPLiveticker für die Website
Flash-Ersatz
Liveticker mit Ajax & PHP
Eine typische Web-Anwendung, bei der die Ajax-Programmiertechnik sinnvolle Zusatzfunktionalität bietet, ist ein Liveticker. Solche oft im Sportbereich eingesetzten Anwendungen werden bisher entweder auf Knopfdruck aktualisiert oder sind Flash-Anwendungen. Sollte Javascript zum Einsatz kommen, handelt es sich bisher meist um IFrames oder Frames, die neu geladen werden. In diesem Workshop entwickeln Sie einen einfachen Liveticker auf Ajax-Basis.
Architektur des Tickers
Liveticker mit Ajax & PHP
Der Liveticker besteht wie jedes Ajax-Beispiel aus zwei Teilen: dem Skript auf Seiten des Clients, das die stetigen Aktualisierungen realisiert, und dem serverseitigen Skript, das die Daten liefert. Als serverseitige Technik kommt PHP 5 zum Einsatz. Um recht einfach die serverseitige Logik oder Technik zu wechseln, verzichtet das vorliegende Beispiel auf eine Ajax-Bibliothek.
Für die Datenspeicherung setzt dieser Liveticker auf XML. XML könnte auch zum Datenaustausch per Ajax verwendet werden. Da im Fall eines Livetickers aber nur wenige und einfach strukturierte Daten auszutauschen sind, greift das Beispiel hier auf durch Strichpunkte separierte Strings zurück. Die XML-Datei selbst ist einfach strukturiert: Sie besteht aus einzelnen Sportereignissen (sportereignis-Tag), die jeweils einzelne Nachrichten (news) besitzen. Da ein Ticker immer nur die aktuellsten Nachrichten schicken sollte, wird bei jeder Nachricht im Attribut zeit der Erstellungszeitpunkt als Zeitstempel gespeichert. Die Nachricht selbst hat dann einen Titel und einen Text:
Willkommen beim Live-Bericht!
Das Spiel geht gleich los!
Damit in PHP 5 auch die DOM-Methode getElementById() verwendet werden kann, muss die XML-Datei zusätzlich noch eine DTD besitzen, in der das ID-Attribut gekennzeichnet ist. Im vorliegenden Beispiel soll jedes Sportereignis eine eigene ID erhalten:
<!DOCTYPE liveticker [
]>
Die Logik macht’s
Liveticker mit Ajax & PHP
Der serverseitige Part des Livetickers erfordert nicht allzu viel Aufwand. Sie benötigen zwei Dateien: liveticker_admin.php für die einfache Administrationsoberfläche und liveticker.php liefert die Daten für die Ajax-Anwendung aus. Die eigentliche Funktionalität steckt in der Datei liveticker.inc.php. Sie erhält zwei Klassen: LiveTicker besteht aus Methoden zum Liefern der Daten für die Ajax-Anwendung und für die Darstellung. LiveTickerAdmin erbt von LiveTicker und erweitert diese Klasse um zwei Methoden für die Administrationsoberfläche.
Die Administrationsoberfläche wird im Workshop sehr einfach gehalten. Der Redakteur, der dort den Ticker füttert, kann zwischen den Sportereignissen wählen und für jedes jeweils über ein Formular neue Nachrichten eingeben. Sie werden dann mit der Methode setNews() in der XML-Datei gespeichert. Zuerst prüfen Sie mit der Methode, ob eine ID für ein Sportereignis mitgeliefert wird. Wenn nicht oder wenn es leer ist, sieht das Skript noch in der Eigenschaft nach, die im Konstruktor der Klasse definiert wurde, und liest den zugehörigen GET-Parameter aus:
public function setNews($titel, $text, $sportereignis_id = ' ') {
if ($sportereignis_id == ' ') {
$sportereignis_id = $this->sportereignis_aktuell_id;
}
Den Zeitstempel zum Sportereignis erzeugen Sie mit der PHP-Funktion microtime(). Mit dem Parameterwert true erhalten Sie die Zeit ohne Fließkommawert:
$this->zeit_aktuell = microtime(true);
Anschließend prüfen Sie, ob überhaupt ein Sportereignis mit der angegebenen ID vorhanden ist. Ist das der Fall, greift das Skript mit der ID darauf zu:
if ($this->sportereignisPruefen()) {
$sportereignis = $this->liveticker_dom->getElementById($sportereignis_id);
Alles braucht seine Richtigkeit
Liveticker mit Ajax & PHP
Beachten Sie, dass getElementById() nur wie erwähnt funktioniert, wenn das XML-Dokument eine DTD hat und die Validierung aktiv ist. Letzteres geschieht im vorliegenden Beispiel im Konstruktor. Dort wird das DOM-Objekt erzeugt, die Validierung aktiviert und dafür gesorgt, dass der DOM-Parser Whitespace (Leerzeichen, Tabs) im Code ignoriert:
$this->liveticker_dom = new DOMDocument();
$this->liveticker_dom->validateOnParse = true;
$this->liveticker_dom->preserveWhiteSpace = false;
$this->liveticker_dom->load($this->xml_url);
Zurück zum Speichern einer Nachricht. Nun folgt ein wenig Klettern im DOM-Baum. Zuerst erstellen Sie ein neues DOM-Objekt für die Nachricht, dann folgt das Attribut für die Erstellungszeit, die einzelnen Unterelemente für Titel und Text und zum Schluss ihre Werte. Die Werte stammen dabei aus dem Formular in liveticker_admin.php:
$neue_nachricht = $this->liveticker_dom->createElement('news');
$neue_nachricht->setAttribute('zeit', $this->zeit_aktuell);
$titel_knoten = $this->liveticker_dom->createElement('titel');
$text_knoten = $this->liveticker_dom->createElement('text');
$titel_knoten->nodeValue = htmlspecialchars($titel);
$text_knoten->nodeValue = htmlspecialchars($text);
Alle einzelnen Elemente fügen Sie dann zusammen und speichern sie ab:
$neue_nachricht->appendChild($titel_knoten);
$neue_nachricht->appendChild($text_knoten);
$sportereignis->appendChild($neue_nachricht);
$this->liveticker_dom->save($this->xml_url);
}
Am Schluss gibt die Methode true zurück, wenn das Speichern geklappt hat.
return true;
}
Nachrichten-Zulieferer
Liveticker mit Ajax & PHP
Für das Ausliefern von Daten an die Ajax-Anwendung sind zwei Methoden verantwortlich. getAlle() liefert alle bisherigen Nachrichten. Diese Methode benötigen Sie beim Neuladen der Ajax-Seite. Dabei greift das Skript auf das aktuelle Sportereignis im DOM-Baum zu und prüft, ob Nachrichten vorhanden sind. Letzteres muss der Fall sein, da sonst die Validierung scheitern würde.
$sportereignis = $this->liveticker_dom->getElementById($sportereignis_id);
if ($sportereignis->hasChildNodes()) {
$nachrichten = $sportereignis->childNodes;
Nun lesen Sie die Nachrichten aus und liefern sie durch Strichpunkte separiert zurück:
foreach ($nachrichten as $nachricht) {
$alle .= $nachricht->firstChild->nodeValue . ';';
$alle .= $nachricht->lastChild->nodeValue . ';';
}
Die zweite Methode, getAktuelle(), funktioniert sehr ähnlich, nur dass sie immer nur die gerade geänderten Nachrichten liefert. Um die Aktualität zu prüfen, wird die aktuelle Zeit von der im XML gespeicherten abgezogen. Ist die Differenz der Zeiten kleiner als das Intervall, in dem die Funktion aufgerufen wird, werden die Nachrichteninhalte gespeichert und später ausgegeben:
code>
foreach ($nachrichten as $nachricht) {
$differenz = $this->zeit_aktuell – $nachricht->getAttribute(‘zeit’);
if ($nachricht->nodeType == 1 && $differenz < ($intervall / 1000)) {
$aktuelle .= $nachricht->firstChild->nodeValue . ‘;’;
$aktuelle .= $nachricht->lastChild->nodeValue . ‘;’;
}
}
Das Intervall muss vor dem Vergleich noch durch 1000 geteilt werden, da die PHP-Funktion microtime() die Mikrosekunden als Fließkommazahl liefert.
Ajax-Verbindung
Liveticker mit Ajax & PHP
Die letzte wichtige Komponente ist die Seite, die den Liveticker ausgibt. Sie soll aus mehreren Teilen bestehen. Das Herzstück wird die Javascript-Funktion liveticker_init(). Diese wird aufgerufen, wenn die Seite geladen wird. Sie startet mit der Funktion liveticker_abfrage() einen Ajax-Request, der alle Nachrichten holen soll. Anschließend wird mit setInterval() eine regelmäßige Abfrage nach den aktuellen Nachrichten gestartet:
function liveticker_init() {
liveticker_abfrage('alle');
intervall_id = window.setInterval("liveticker_abfrage('aktuelle')", intervall);
Zwei Links auf der Liveticker-Seite sollen die Möglichkeit bieten, den Ticker anzuhalten oder zu starten. Zu Anfang wird der Ticker gestartet. Deswegen blenden Sie mit dieser Funktion noch den Link zum Anhalten ein:
if (document.getElementById) {
document.getElementById('anhalten').style.display = 'inline';
document.getElementById('starten').style.display = 'none';
}
}
Die Funktion zum Anhalten erledigt hauptsächlich eine Aufgabe: Sie löscht den mit setInterval() definierten regelmäßigen Funktionsaufruf mittels clearInterval(). Außerdem wird der Starten-Link eingeblendet:
function liveticker_anhalten() {
clearInterval(intervall_id);
if (document.getElementById) {
document.getElementById('anhalten').style.display = 'none';
document.getElementById('starten').style.display = 'inline';
}
}
Die eigentliche Ajax-Abfrage erledigen Sie in der Funktion liveticker_abfrage(). Das meiste ist hier aus anderen Ajax-Anwendungen bekannt. Mit der Funktion liveticker_objekt() prüfen Sie zuerst, ob es ein XMLHTTPRequest-Objekt gibt. Wenn nicht, wird ein solches erstellt:
function liveticker_abfrage(anfrage) {
liveticker_objekt();
Finale: Event-Handler
Liveticker mit Ajax & PHP
Anschließend checken Sie noch einmal, ob das Objekt auch klappt. Wenn ja, erzeugen Sie noch ein Datumsobjekt. Es wird beim Aufruf mit open() verwendet, um den aktuellen Zeitstempel an den URL anzuhängen. Damit verhindern Sie beim Internet Explorer, dass er die Ajax-Rückgabe in den Cache legt:
if (xmlHttp) {
var datum = new Date();
xmlHttp.open('GET', 'liveticker.php?id=' + ticker + '&anfrage=' + anfrage + '&intervall=' + intervall + '&tv=' + datum.getTime(), true);
Nach dem Zusammenstellen der Anfrage wenden Sie sich nun den Event-Handler-Funktionen zu. Dafür soll es hier zwei geben: eine, die reagiert, wenn alle Liveticker-Daten geliefert werden, und eine, die nur die aktuellen Daten verarbeitet:
if (anfrage == 'alle') {
xmlHttp.onreadystatechange = liveticker_ergebnis_alle;
} else {
xmlHttp.onreadystatechange = liveticker_ergebnis_aktuelle;
}
xmlHttp.send(null);
}
}
Der Unterschied zwischen den zwei Event-Handler-Funktionen ist schnell erklärt: Die für alle Daten löscht die bisherige Ausgabe, diejenige für aktuelle Nachrichten hängt sie nur an die bestehende Ausgabe an.
Fazit
Liveticker mit Ajax & PHP
Der hier vorgestellte Liveticker ist natürlich nur eine Ausgangsbasis für optisch und funktional umfangreichere Projekte. Bei der Administration gibt es am meisten Potenzial für Erweiterungen: Sportereignisse könnten auch über eine Administrationsoberfläche erstellt werden, der Ticker ließe sich aber auch direkt mit einem Content-Management-System (CMS) verbinden. Dazu könnte man auch schon abgeschickte Nachrichten aktualisier- und löschbar machen. Auch der Einsatz eines Template-Systems bietet sich an. Im Frontend ist es vor allem die Darstellung, die an die eigenen Bedürfnisse angepasst werden muss. Aber auch zusätzliche Steuerelemente oder eine Fortschrittsanzeige wären als funktionale und bedienerfreundliche Erweiterungen denkbar.
Alle Dateien und Listings zum Workshop finden Sie auf der Heft-CD und unter listings.internet-pro.de.