15.12.2008, 00:01
|
|
| Adventskalenderöffner
Registriert seit: 27.11.2008
Beiträge: 72
PHP-Kenntnisse: Fortgeschritten
| 1111: AJAX meets PHP (indirectly) 1111:AJAX ist mittlerweile aus dem Web nicht mehr wegzudenken. Nahezu jede Webzwonullige Seite benutzt AJAX. Hier soll es jedoch nicht um Fluch und Segen dieser Technologie gehen, sondern schlicht und einfach um die Verarbeitung eines AJAX-Requests.
Wie erkennt man einen AJAX-Request? Die häufigste Variante ist die, eine spezielle PHP-Datei für die Verarbeitung eines AJAX-Requests zu erstellen, die dann vom Browser (via AJAX) aufgerufen wird. Dies führt jedoch oft zu redundantem Code und das wollen wir nicht.
Es muss also eine Lösung her, AJAX-Requests zu erkennen und die Ausgabe entsprechend anzupassen, ohne den eigentlichen Inhalt der PHP-Datei kopieren und ändern zu müssen. 1. Die Klassen
Um dies zu realisieren, benötigt man Klassen für die Annahme eines Requests und für die Ausgabe. Da mehrere dieser Klassen existieren können, werden sie gegen ein Interface implementiert.
Die Standardklassen sind auf einen ganz normalen HTTP-Request ausgelegt: PHP-Code: interface Request
{
public function getParam($name);
}
interface Response
{
public function write($output);
public function flush();
}
class HTTPRequest implements Request
{
public function getParam($name)
{
return isset($_REQUEST[$name]) ? $_REQUEST[$name] : null;
}
}
class HTTPResponse implements Response
{
private $output = '';
public function write($output)
{
$this->output .= $output;
}
public function flush()
{
print $this->output;
}
}
Den konkreten Inhalt dieser Klassen spare ich mir und schreibe nur die wichtigsten Methoden auf.
Wenn das Skript nun ausgeführt wird, werden jeweils Instanzen der Klassen angelegt: PHP-Code: $request = new HttpRequest();
$response = new HttpResponse();
// eigentliches Skript
$param = $request->getParam('foobar');
$response->write('You entered: ' . htmlspecialchars($param));
$response->flush();
Als nächstes sollen die Klassen für den AJAX-Request angelegt werden: PHP-Code: class AjaxRequest implements Request
{
public function getParam($name)
{
return isset($_REQUEST[$name]) ? $_REQUEST[$name] : null;
}
}
class AjaxResponse implements Response
{
private $output = array();
public function write($output)
{
$this->output[] = $output;
}
public function flush()
{
$procOutput = '{';
$first = true;
foreach ($this->output as $key => $value) {
if (true !== $first) {
$procOutput .= ', ';
}
$first = false;
$procOutput .= "'" . $key . "' : '" . addslashes($value) . "'";
}
$procOutput .= '}';
print $procOutput;
}
}
Diese tut genau das Gleiche, nur wird die Antwort diesmal in einen JSON-String verpackt.
Um jetzt statt der normalen HTTP-Verarbeitung die AJAX-Verarbeitung einzuschalten, müssen nur die beiden Instanziierungen geändert werden, der Rest des Skripts bleibt unverändert: PHP-Code: $request = new AjaxRequest();
$response = new AjaxResponse();
Doch wie erkennt man nun, dass man die AJAX-Klassen benutzen muss? 2. Erkennung eines AJAX-Requests
Ein AJAX-Request ist in erster Linie ein HTTP-Request und sieht deshalb im Regelfall genauso aus und ist nicht von einem „normalen“ Request zu unterscheiden. Die Anforderung einer AJAX-Verarbeitung muss also schon auf Benutzerseite erfolgen. Das ist aber auch gar nicht schlimm, da die Benutzerseite ja eh entscheidet, ob sie die Daten jetzt per AJAX holen will oder nicht. Um PHP mittzuteilen, dass es sich um einen AJAX-Request handelt, kann man mehrere Dinge tun: - Senden eines GET-Parameters:
Es ist möglich, einen GET-Parameter an den URL anzuhängen, anhand dessen ein AJAX-Request dann identifiziert werden kann: Code: http://www.example.com/index.php?ajax=true
- - Ändern des User-Agents:
Beim AJAX-Request kann der User-Agent erweitert werden: Code: ajaxObject.setRequestHeader('User-Agent', navigator.userAgent + ' Ajax');
Das Problem hierbei ist, dass User, die Ajax im normalen User-Agent haben, immer nur AJAX-Antworten bekommen. Das Risiko ist zwar mehr als gering, aber es besteht. Außerdem wollen viele nicht, dass ihr User-Agent geändert wird und die Log-Files freuen sich auch über Einträge „neuer“ Browser. - - Senden eines zusätzlichen Headers:
Dies halte ich für die beste Variante neben dem Senden eines GET-Parameters. Dabei wird ein zusätzlicher (nicht-standardisierter) HTTP-Header an den Server gesendet: Code: ajaxObject.setRequestHeader('X-Ajax-Request', 1);
Das X am Anfang sollte man auf jeden Fall benutzen, da hierdurch proprietäre Header gekennzeichnet werden.
In PHP lässt sich dieser Header dann über das $_SERVER-Array abfragen: PHP-Code: $isAjax = (bool)$_SERVER['HTTP_X_AJAX_REQUEST'];
Wenn PHP als Apache-Modul läuft, kann auch die Funktion apache_request_headers() genutzt werden.
|
| |