Benutzer:TS/AJAX-Beispiele: Nachladen von Daten
Informationen zum Autor
- Name:
- Thomas Schmieder
- E-Mail:
- selfhtml@bitworks.de
- Homepage:
- bitworks.de
Um Datensätze aus einer Datenbank seitenweise nachzuladen, ohne das Stammdokument (Die "Seite") neu laden zu müssen, kann man asynchrone Requests (AJAX) einsetzen. Durch Verwendung der jQuery-Bibliothek wird diese Methode sehr übersichtlich und leicht verständlich. In diesem Artikel soll deshalb das Nachladen von Datensäten mittels XMLHttp-POST-Requests gezeigt werden, und wie einfach diese in das vorhandene Dokument (DOM) eingefügt werden können.
Inhaltsverzeichnis
Aufbau der Struktur
/ | +----Domain-Space | | | +---- htdocs | | | | | +---- index.php | | +---- main.css | | +---- jQuery.js | | +---- loadadd.js | | +---- images | | | | | +---- loader.gif | | +---- background.png | | | +---- includes | | | | | +---- dbuser.inc.php | | +---- functions.inc.php | | | +---- data | +---- DBMS-Data |
Zeitlicher Ablauf
● Client ●
- Startseite anfordern
■ Server ■
- functions.inc.php - Basisfunktionen laden
- Datenbankverbindung herstellen
- Session starten
- Dispatcher wertet den Request aus
- path auswerten und festlegen
- header auswerten und auf XHR untersuchen
- Post & Get-Parameter auf XHR untersuchen
- Zugriffsrechte prüfen
- bei berechtigtem XHR: XHR-Modul zum Path laden, ausführen und index.php beenden
- kein XHR: passende Includes zum path laden
- Response senden
● Client ●
- Response (index-php) zu DOM umformen
- Sekundärrequests anfordern
- CSS-Datei laden
- jQuery laden
- externe JS-Dateien laden
---> DOM-Gerüst aus Primärrequest ist fertig aufgebaut (1)
- weitere Ressourcen (z. B. Images) anfordern
---> läuft parallel ab:
- JS-Funktionen definieren
- Event-Listener anmelden
- Event tritt ein
- Callback Bedingungen auswerten
- Loader-Image ins DOM einblenden
- Nachladefunktion aufrufen per XHR
- Response des XHR in das DOM-Gerüst einhängen
- Loader-Image aus dem DOM entfernen
- Callback Bedingungen auswerten
(1) Die restlichen Elemente aus den Sekundärrequests können in der Reihenfolge ihrer Notation parallel zum XHR weiter geladen und gerendert werden.
Benötigte Bausteine und Dateien
Datenbank
Tabelle
Create-Statement:
User
Queries
.htaccess oder virtHost-Einrichtung
Damit alle Requests, für die es in unserer Document-Root keine realen Dateien oder SymLinks darauf gibt, an die index.php weitergeleitet werden, benutzen wir die Rewrite-Engine des Webservers. Wir können die Angaben in einer .htaccess-Datei in der Document-Root des Projektes unterbringen, oder besser in der virtual-Host-Konfiguration.
RewriteEngine on RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-l RewriteRule (.*) index.php/$1 [QSA]
Startdatei (index.php)
Um einheitlich geklärte Berechtigungsverhältnisse schaffen zu können, werden alle Requests (in diesem Beispiel mit Ausnahme von Bildern, CSS, JS-Skripten), über die index.php abgewickelt.
Die index.php prüft die Request-Hesder und entscheidet, welche Module (Includes) hinzugeladen werden.
jQuery.js
Ladeprogramm (loaddata.php)
main.css
/* /nachladen/main.css */ body { font-size : 11pt; font-family : "Century Gothic", Helvetica, sans-serif; background-image: url("/images/raster-74-74.png"); background-attachment: fixed; margin: 0; padding : 0 0 30px 0; /* T R B L */ } h1 { text-align: center; color: #A03050; font-variant: small-caps; font-size: 25pt; } .block { height: 50px; width: auto; border-bottom: 1px solid silver; padding: 5px; font-weight: normal; font-size: 18pt; display: flex; align-items: center; } .block:lastchild { border-bottom-left-radius: 15px; border-bottom-right-radius: 15px; } #loader { text-align: center; height: 60px; width: auto; padding: 20px; background: white; border-bottom-left-radius: 15px; border-bottom-right-radius: 15px; } #wrapper { margin: 60px auto 100px auto; width: 700px; min-height: 500px; padding: 0px; border: 1px solid blue; box-shadow: 7px 7px 8px #818181; border-radius: 15px; background-color: rgba(248, 248, 230, 0.8); } footer { height: 20px; width: 100%; font-size: 8pt; text-align: center; margin: 0; margin-top: 2px; padding: 0; padding-top: 2px; position: fixed; bottom: 0; background-color: #FFFFAA; border-top: 2px #F0F0A0 groove; z-index: 7; }
Images
Zugriffsschutz
AJAX Request-Header
Wie kann man eigentlich einen XHR (XMLHttpRequest) erkennen? Diese Frage lässt sich nur mit gutem Willen aus den Request-Headers erkennen:
Host: nachladen.lan User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:43.0) Gecko/20100101 Firefox/43.0 Accept: */* Accept-Language: de,en-US;q=0.7,en;q=0.3 Accept-Encoding: gzip, deflate DNT: 1 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 X-Requested-With: XMLHttpRequest Referer: http://nachladen.lan/ Content-Length: 9 Cookie: PHPSESSID=96genejh98uv8kbq7gqee9bpj3 Connection: keep-alive
Nur der Header "X-Requested-With: XMLHttpRequest" weist auf einen asynchronen Request hin. Ob dieser Header enthalten ist, hängt vom Good Will des Clients und/oder seines Proxys ab. Das JavaScript-Framework jQuery fügt diesen Header selbsttätig hinzu. Wenn man sich einen XHR generisch nur mit JavaScript aufbaut, sollte man sich dieser Konvention anschließen, und ihn ebenfalls hinzufügen.
Und auch wenn der Header enthalten ist, ist das keine Garantie dafür, dass das Nachlade-Modul (die angefragte Ressource für XHR) nicht doch von einem Grabber direkt aufgerufen wurde.
Zumindest hilft uns dieser Header bei einer Single-Target-Applikation, in der _eine_ einzige index.php als Ziel für alle Requests dient, in deren Dispatcher (ggf. nach der Berechtigungsprüfung) direkt auf die Methoden/Funktionen zu verzweigen, die für den XHR zuständig sind.
GET vs. POST
Wie wir aus den obigen Request Headers ersehen können, wird der Request hier ohnehin per POST gesendet. "Content-Type: application/x-www-form-urlencoded; charset=UTF-8". Damit können wir auch die Request-Parameter per POST-Body senden.
Im XHR-Code ist das der Unterschied zwischen:
Request-Parameter per GET
// $.post("/loaddata.php?lid="+userID,
Request-Parameter per POST
$.post("/loaddata.php", { lid: userID },
Die Signatur der Request-Methode ".post()" ist variant, oder überladen. Sie kennt vier Parameter (-> $.post()).
Also können wir die relevanten Request-Parameter auch gleich ausschließlich per POST im Request-Body senden. Damit liegen sie dann nicht mehr offen in der URi vor!
Dies ist nach geltender Konvention eine Bedingung dafür, dass die Parameter nicht in Logs und Suchmaschinen offengelegt werden. Es ist aber auch keine Garantie dafür, dass sie nicht trotzdem irgendwo unerlaubt ausgewertet werden (-> Edward Snowden).
Sessions und AJAX
Iterierbarkeit der Abfragen
Wer möchte schon gerne, dass sein Datenbestand stumpf abgefischt wird?
Integration von Aufgaben
Sicherheit
Injection Protection
Beispiel
Ein aktives Beispiel befindet sich unter getscript.de