Einzelnen Beitrag anzeigen
Alt 15.12.2008, 00:01  
Nikolaus 2.0
Adventskalenderöffner
 
Benutzerbild von Nikolaus 2.0
 
Registriert seit: 27.11.2008
Beiträge: 72
PHP-Kenntnisse:
Fortgeschritten
Nikolaus 2.0 ist einfach richtig nettNikolaus 2.0 ist einfach richtig nettNikolaus 2.0 ist einfach richtig nettNikolaus 2.0 ist einfach richtig nettNikolaus 2.0 ist einfach richtig nett
Standard 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.
Nikolaus 2.0 ist offline  
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten