22. Januar 2013 | 3 Comments Hallo zusammen, viele von uns benutzen Heutzutage Ajax – Sei es zum „echtzeit“ speichern von Informationen oder um Daten vom Server nachzuladen. Inzwischen rücken die kompletten Seiten-reloads immer mehr in den Hintergrund und machen Platz für ein dynamischeres Web – Sehr zur Freude der Besucher! Immerhin beinhaltet jeder ausgelagerte Ajax-Request Daten, die nicht beim initialen Seitenaufruf geladen werden mussten… Das bedeutet im Klartext: Schnellere Ladezeiten und weniger Datenvolumen. Standardisierte Ajax Anfragen und Antworten Für das hin- und her schicken von Daten sollte man sich das Framework seiner Wahl zunutze machen und, früher oder später, eine saubere Datenstruktur überlegen, um sich nicht selbst ein Bein zu stellen. Zunächst möchte ich zwei Quelltext-Beispiele präsentieren: Ein Ajax Request mit Hilfe von jQuery und ein weiterer mit Hilfe von Prototype. jQuery jQuery verfügt über eine ausgereifte API um Ajax requests abzuschicken und liefert diverse Optionen um auf Antworten des Servers zu reagieren: $.ajax('url/zum/ajax-handler.php', { /* Daten / Parameter */ data:{}, /* Methode */ type:"POST", // Oder "GET". dataType:"json", // Oder "xml", "html", "script", ... /* Callback Funktionen */ error:function () { // Der Request ist fehlgeschlagen. }, success:function () { // Der Request war erfolgreich. }, /* Callback Funktionen für bestimmte Status-Codes */ statusCode:{ 404:function () { // URL konnte nicht gefunden werden. }, 500:function () { // Interner Server-Fehler. } // ... } }); jQuery wird die Daten innerhalb von data serialisieren (also zu einem „Query String“ zusammenführen) sofern wir nicht die Option processData:false mitgeben. Für uns dürfte hier besonders dataType interessant sein… Denn hier müssen wir differenzieren was wir für Daten erwarten: Erwarten wir fertig gerendertes HTML (z.B. ein nachgeladenes DIV mit Artikeln) oder reine Daten im JSON Format? Diese Frage wird weiter unten noch weiter behandelt… Prototype Natürlich verfügt auch Prototype über eine saubere API, die uns schnell und einfach Daten zum oder vom Server laden lässt. Anbei ein Beispiel: new Ajax.Request('url/zum/ajax-handler.php', { /* Daten / Parameter */ parameters:{}, /* Methode */ method:"post", // Oder "get" /* Callback Funktionen */ onComplete:function (response) { if (response.status == 404) { // URL konnte nicht gefunden werden. } else if (response.status == 500) { // Interner Server-Fehler. } }, onFailure:function (response) { // Der Request ist fehlgeschlagen. } }); Prototype bietet zwar etwas weniger Optionen/Callbacks an, doch in diesem Fall muss ich aus eigener Erfahrung sagen: weniger ist mehr. Der Quelltext wirkt nicht so aufgebläht durch zu viele Optionen oder Callbacks sondern bleibt stehts überschaubar! Doch genug dazu, ich möchte langsam zum eigentlichen Teil des Beitrags kommen… Wie sieht eine saubere Anfrage an den Server aus? Ganz gleich ob wir mit Hilfe von jQuery oder Prototype arbeiten, die Requests sollten immer direkt an den zuständigen Ajax Handler geleitet werden und so schlank wie möglich sein. Arbeiten wir mit einem Framework, wie z.B. Kohana, F3 oder Slim, sollten wir davon gebrauch machen, das wir auf Ajax Requests direkt reagieren können – Sei es via Routing („example.com/ajax/<handler>/<methode>“) oder der Request-Method (in der Regel „POST“). Außerdem sollten wir (wenn nötig) immer diejenigen Parameter übergeben die den geringsten Aufwand machen. Damit meine ich, wenn wir z.B. Informationen zu einem Produkt nachladen möchten sollten wir nicht sowas übergeben: { "produkt":"Doppeltür-Kühlschrank mit Eiswürfelbereiter", "typ":"Kühlschrank", "farbe":"Gebürstetes Aluminium" } Stattdessen sollten wir mit dem arbeiten, was die Datenbank uns bietet: IDs { "produkt_id":987, "produkt_typ":654, "farbe":321 } Zack! Anstatt mit Strings in der Datenbank nach einem Produkt zu suchen, holen wir uns einfach die Informationen mit Hilfe numerischer IDs. Das spart etwas Aufwand beim beschaffen der Daten (Wir können nämlich bedenkenlos nach INT casten um SQL-Injectionn vorzubeugen), der Request bzw. die zu übermittelnden Daten verbrauchen weniger Resourcen und wir greifen direkt auf die Indizes der Datenbanktabellen zu, was schneller ist als Stringvergleiche. Fakt ist, das Strings als Parameter immer etwas mehr Aufwand als Beispielsweise IDs (Ganzzahlen) oder fest definierte Konstanten bereiten. Im Gegensatz zum Frontend muss bei Ajax Requests nicht auf die üblichen SEO Regeln geachtet werden (sprechende URL, verständliche Parameter, …) Und wie sollte eine „saubere“ Antwort vom Server aussehen? Im Grunde gibt es, wie vorhin kurz angedeutet, verschiedene Möglichkeiten: Reine Daten (via JSON, XML, …) nachladen {"data":[1,2,3,4]} ["Daten vom Server.","Weitere Daten"] HTML nachladen <div>HTML mit Inhalten...</div> Für die erste Option kann man sich folgende Datenstruktur anschauen und benutzen: { "success":true, "message":null, "data":{/* ... */} } Oder, im Fehlerfall… { "success":false, "message":"Fehler beim beschaffen der Daten", "data":null } Der dazugehörige PHP Teil könnte so aussehen: // Wichtig für Prototype zum feststellen des Antwort-Typs. header('Content-Type: application/json'); try { $data = array( 'success' => true, 'message' => '', // Ggf. Debug-Informationen 'data' => funktion_zur_datenbeschaffung() ); } catch (Exception $e) { $data = array( 'success' => false, 'message' => $e->getMessage(), 'data' => null // Ggf. Fallback-Daten ); } // Achtung! der zurückgelieferte String muss ggf. UTF8 kodiert werden! echo json_encode($data); die; Dieser Quelltext setzt natürlich voraus, das ihr in eurem Code sauber mit Exceptions arbeitet 😉 Die Array-Keys success, message und data sind dabei natürlich nur Beispiele, bewähren sich aber durchaus in der Praxis! Vor allem die Information ob die Datenbeschaffung erfolgreich war oder nicht ist viel Wert! Diese Struktur macht also sowohl beim laden als auch speichern von Daten Sinn! Für die zweite Option (zurückliefern von fertig gerendertem HTML) gibt es eigentlich kaum Einschränkungen. Hier wird einfach nur das reine HTML als String zurückgeliefert und dann via Javascript in den DOM geworfen. Und mit diesen Worten möchte ich meinen Eintrag für Heute beenden – Ich freue mich wie immer über Kommentare, Lob und Kritik oder Verbesserungsvorschläge! In diesem Sinne wünsche ich euch eine erfolgreiche Woche und Happy Coding!