Web Programmierung 2 Ein Skriptum zu den gleichnamigen Lehrveranstaltungen im 2. Semester von MultiMediaTechnolgy Überblick 0. Vorbereitung 6 1. Einstieg in die serverseitige Programmierung 12 2. HTTP 26 3. Webapplikationen mit MySQL 42 4. Login, Sessions und Datenbank verändern 51 5. AJAX und REST 66 6. DB-Transaktionen und Apache Konfiguration 77 7. Ausblick 88 Anhänge 93 Stichwortverzeichnis 95 Version vom 23.Juni 2009
Aufbauend auf Grundkenntnisse über HTTP, HTML, CSS und Javascript wird die serverseitige Programmierung in PHP vorgestellt. Als Datenbankschnittstelle wird mysqli (mit prepared statements) verwendet. Das REST-Prinzip wird erläutert um die schlimmsten Nebenwirkungen von AJAX zu vermeiden.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Web Programmierung 2
Ein Skriptum zu den gleichnamigen Lehrveranstaltungen
im 2. Semester von MultiMediaTechnolgy
Überblick
0. Vorbereitung 6
1. Einstieg in die serverseitige Programmierung 12
2. HTTP 26
3. Webapplikationen mit MySQL 42
4. Login, Sessions und Datenbank verändern 51
5. AJAX und REST 66
6. DB-Transaktionen und Apache Konfiguration 77
7. Ausblick 88
Anhänge 93
Stichwortverzeichnis 95
Version vom 23.Juni 2009
MMT Webprogrammierung 2 2
Ziele
Diese Lehrveranstaltung führt mehrere Themen, die im ersten Semester noch separat behandelt
wurden zusammen: Datenbanken, UNIX, Webprogrammierung mit HTML, CSS, Javascript werden
zusammen mit der Programmiersprachen PHP eingesetzt um Web-Applikationen zu bauen.
Am Ende des zweiten Semesters können Sie sagen:
• Ich kann Webapplikationen erstellen, und habe auch schon eine kleine Applikation inklusive
Datenbank vollständig umgesetzt.
• Ich kenne die Arbeitsteilung in einem Web-Projekt und kann meinen (technischen) Teil mit
Javascript, PHP und MySQL beitragen.
• Ich kann die Qualität einer Webapplikation beurteilen: Ich kenne die REST-Prinzip, ich ken-
ne Sicherheitsprobleme und Lösungsansätze, ich kann AJAX einsetzen.
• In meinem Blog zeige ich mehrere Artikel über Aspekte einer Web-Applikation.
MMT Webprogrammierung 2 3
Inhaltsverzeichnis
0. Vorbereitung 6
0.1 Ziele dieses Kapitels 6
0.2 Was ist PHP? Was passiert am Webserver? 7
0.3 Apache 7
0.3.1 Apachefriends und XAMPP 7
0.3.2 Apache und MySQL starten 8
0.3.3 Apache als Windows-Dienst 8
0.3.4 Webserver stoppen 9
0.4 Das erste PHP-Programm 9
0.4.1 PHP Versionen 10
0.4.2 Dokumentation 11
1. Einstieg in die serverseitige Programmierung 12
1.1 Ziele 12
1.2 Syntax von PHP 12
1.2.1 HTML und PHP 12
1.2.2 Includes 15
1.2.3 Variablen und Typen 16
1.2.4 Funktionen 18
1.3 Dateien und Ordnern in PHP 19
1.3.1 Zugriffsrechte 19
1.3.2 Ordner auflisten 20
1.3.3 Datei lesen 21
1.3.4 Datei (über-)schreiben 21
1.3.5 Gleichzeitiger schreibender Zugriff 22
1.4 PHP erzeugt nicht nur HTML 22
1.4.1 PHP erzeugt CSS 22
1.4.2 PHP erzeugt Bild 23
1.4.3 PHP erzeugt Variablen für Flash 24
1.4.4 PHP erzeugt XML 24
1.4.5 PHP leitet weiter 25
2. HTTP 26
2.1 Ziele 26
2.2 TCP/IP und DNS 26
2.3 HTTP 28
2.3.1 Ablauf im Überblick 28
2.3.2 Aufbau von Request und Response 28
2.3.3 HTTP abhören 30
2.3.4 Seite laden oder Formulardaten senden mit GET 31
2.3.5 Senden von Formulardaten mit Post 32
MMT Webprogrammierung 2 4
2.3.6 Umleitung an neue URL 33
2.3.7 Authentisierung nach RFC 2617 34
2.3.8 HTTPS 35
2.3.9 Proxies 35
2.4 Daten aus Web-Formularen verarbeiten 36
2.4.1 Daten senden mit Methode POST 37
2.4.2 Daten prüfen 37
2.4.3 Datei Upload 39
2.5 PHP und E-Mail 40
3. Webapplikationen mit MySQL 42
3.1 Ziele 42
3.2 PHP und MySQL 42
3.2.1 MySQL Installation, Wiederholung, Dokumentation 42
3.2.2 MySQL von PHP aus 45
3.3 Eine lesende Web-Applikation 46
3.3.1 Viele Datensätze aus der Datenbank lesen 48
3.3.2 Einzelne Daten aus der Datenbank lesen 48
3.3.3 Einen bestimmten Datensatz lesen 48
3.3.4 Datensätze suchen 50
3.3.5 Bilanz 50
4. Login, Sessions und Datenbank verändern 51
4.1 Ziele 51
4.2 Session und Login 52
4.2.1 Cookies 52
4.2.2 Session 53
4.3 Web-Applikation mit Schreibrecht 56
4.3.1 Daten löschen 57
4.3.2 Daten einfügen 58
4.3.3 Einen Datensatz bearbeiten 60
4.3.4 Escapen von HTML 62
4.3.5 Darstellen von HTML 63
5. AJAX und REST 66
5.1 Ziele 66
5.2 Wiederholung: Was ist AJAX 66
5.2.1 Simples AJAX Beispiel mit jQuery 68
5.2.2 Schlechte Verwendung von AJAX 68
5.3 REST – Representational State Transfer 69
5.3.1 Jedes Dokument soll eine eindeutige URL haben 70
5.3.2 Dokumente sollen Links auf andere Dokument enthalten 71
5.3.3 HTTP-Methoden GET, POST, PUT, DELETE 71
5.3.4 Ein Dokument – mehrere Repräsentationen 72
5.3.5 Zustandslosigkeit = Statlessness. 72
MMT Webprogrammierung 2 5
5.4 jQuery – Wiederholung 73
5.5 jQuery und AJAX 74
5.5.1 Clientseitige Datenprüfung mit AJAX-Nachfrage beim Server 74
5.5.2 Autofill 75
5.6 Quellenverzeichnis 76
6. DB-Transaktionen und Apache Konfiguration 77
6.1 Ziele 77
6.2 Foreign Key Constraint 78
6.3 Transaktion 79
6.4 Andere DB-Schnittstellen 81
6.5 Konfiguration von Apache 83
6.5.1 Konfigurations-Änderung wirksam machen 83
6.5.2 Fehlermeldung 84
6.5.3 Zugriffsbeschränkung 84
6.5.4 HTTP Auth mit Apache 85
6.5.5 mod_rewrite 86
7. Ausblick 88
7.1 Templates und MVC 89
7.1.1 Templates am Beispiel von Smarty 89
7.2 Security von Web-Applikationen 91
7.2.1 Keine Ausreden 91
7.2.2 Beispiele für Attacken 91
7.2.3 Tipps für mehr Sicherheit in PHP 92
Anhänge 93
7.3 Literatur- und Web-Tipps 93
Stichwortverzeichnis 95
MMT Webprogrammierung 2 6
0. Vorbereitung
Bevor dar eigentliche Unterricht startet müssen Sie Ihren Computer auf die Arbeit mit PHP und
MySQL vorbereiten.
0.1 Ziele dieses Kapitels
Was Sie wissen sollten
• Dass PHP eine freie Skriptsprache ist, die am Webserver interpretiert wird. Dass nur der Out-
put von PHP an den Browser übertragen wird, also der Source-Code niemals lesbar ist.
• Dass Apache ein freier Webserver ist.
• Dass MySQL eine freie Datenbank ist.
• Wo Sie Apache, PHP und MySQL im Paket für Windows herunterladen können.
Was Sie können sollten
• Ein PHP Programm schreiben und testen – sowohl am eigenen Computer als auch auf einem
UNIX-Webserver wie z.B. www.users.fh-salzburg.ac.at.
• Die PHP-Dokumentation als Nachschlagewerk verwenden.
• PHP-Code lesen, egal auf welche Art er in HTML eingebettet ist.
Weitere Informationsquellen
• Apache, PHP, MySQL als Paket für Apple: MAMP
• PHP Homepage mit Dokumentation in verschiedenen Sprachen: http://php.net
Vertiefungsmöglichkeiten
Helfen Sie einem Kollegen / einer Kollegin beim installieren von XAMPP.
MMT Webprogrammierung 2 7
0.2 Was ist PHP? Was passiert am Webserver?
PHP ist eine Programmiersprache am Webserver. Sie ist im Vergleich zu anderen Programmierspra-
chen wie C++ oder Javascript recht simple in der Schreibweise und etwas altmodisch. Gerade des-
wegen eignet sie sich gut für Programmier-EinsteigerInnen. Viele bekannte open source Web-
Applikationen sind in PHP geschrieben.
Neben PHP werden viele andere Sprachen am Webserver verwendet. Da der Output dabei immer
HTML ist kann der Client nicht erkennen, welche Sprache verwendet wurde. Der Quelltext des Pro-
gramms wird nie im Browser sichtbar.
Das PHP-Programm wird gestartet um die Anfrage des Browsers zu beantworten. Nachdem diese
Aufgabe erfüllt ist, wird das PHP-Programm wieder beendet. Die Laufzeit ist also sehr, sehr kurz!
Ein sehr einfaches Beispielprogramm in PHP gibt „Hallo Welt“ aus und zeigt (mit dem Befehl phpin-
fo) viele Informationen über den Webserver und die PHP Installation an:
In der “Haupt-Datei” warden alle diese Einzelteile zusammengefügt:
<?php include "phpfunctions.php"; // kein Output, nur Definitionen von Funktionen! $pagetitle = "Berechnung der Geschwindigkeit"; $entfernung = 296; $h = 2; $min = 40; $kmh = calc($entfernung, $h, $min); include "header.php"; // erster Output von HTML echo "<p>$entfernung km in $h:$min sind $kmh km/h</p>"; if( $kmh > 130 ) { echo("<p><b>Das ist zu schnell!</b></p>"); } include "footer.php" ?>
Und wieder gilt: die „Zusammensetzung“ erfolgt am Server. Im Client landet nur der fertige HTML-
Code. Die UserIn kann nicht erkennen, dass die Seite ursprünglich aus mehreren Dateien bestand.
1.2.3 Variablen und Typen
Variablennamen in PHP beginnen mit einem Dollar-Zeichen. Warum? Sie haben im Beispielprogramm
schon gesehen, wie Variablen einfach in Strings eingebettet werden können:
MMT Webprogrammierung 2 17
echo "$entfernung km in $h:$min sind $kmh km/h";
Das ist nur möglich weil die Variablennamen mit einem besonderen Zeichen gekennzeichnet sind. Es
gibt in PHP eine zweite Schreibweise für Strings die keine Variablen erlaubt:
echo 'Bei einfachen Anführungszeichen ist ein $ einfach ein $';
Variablen in PHP müssen nicht deklariert oder initialisiert werden. PHP unterscheidet zwischen den
Datentypen boolean, integer, float, string, array, object, resource und NULL. In einer Variable
können nacheinander verschiedene Datentypen gespeichert werden, die Variable selbst hat also
keinen Typ! Je nach verwendeten Operatoren und Funktionen werden die Typen konvertiert:
<?php $foo = "0"; // $foo is a string with one character (ASCII 48) $foo += 2; // $foo is now an integer (2) $foo = $foo + 1.3; // $foo is now a float (3.3) $bar = 5 + "10 Little Piggies"; // $bar is an integer (15) $baz = 5 . "10 Small Pigs"; // $baz is a longer string "510 Small Pigs" ?>
Die Addition mit + interpretiert beide Summanden als Zahl. Falls ein Summand ein String ist, wird am
Beginn des Strings nach einer Zahl gesucht und diese verwendet. Der Punkt-Operator fügt Strings
zusammen und interpretiert seine beiden Operanden als Strings.
Arrays in PHP können auf ähnliche Art verwendet werden wie in C++ (und C, und Java, und Perl,…)
und verhalten sich auf den ersten Blick auch wie erwartet:
Die Schreibweise von Funktionen inklusive Argumentliste und Rückgabewert ist leicht verständlich.
Eine Falle für erfahrene ProgrammiererInnen ist das Scoping von globalen Variablen:
$pi = 3.141; function inhalt($radius) { return $radius * $radius * $pi; } $r = 10; $a = inhalt($r); echo("ein Kreis mit Radius $r hat eine Fläche von $a");
Dieses Programm funktioniert nicht wie erwartet, da innerhalb einer Funktion kein Zugriff auf die
außerhalb definierten Variablen möglich ist! Die Variable $pi ist in der Funktion nicht sichtbar, statt-
dessen wird mit einer neuen Variable $pi mit Default-Wert 0 gerechnet.
Mit dem Keyword global wird die Variable „in die Funktion eingeladen“ und ist dann auch innerhalb
der Funktion sichtbar, lesbar und veränderbar.
MMT Webprogrammierung 2 19
$pi = 3.141; function inhalt($radius) { global $pi; return $radius * $radius * $pi; } $r = 10; $a = inhalt($r); echo("ein Kreis mit Radius $r hat eine Fläche von $a");
Ausgenommen von dieser Regelung sind die sogenannten „superglobals“. Das sind Variablen, die auf
jeden Fall sichtbar sind. Vier davon werden hier vorgestellt, die anderen werden erst später behan-
delt.
$GLOBALS Dieses Array enthält alle globalen Variablen.
$_SERVER Dieses Array enthält Konfigurations-Informationen des (Web-)Servers und all-
gemeine Informationen zur aktuellen Anfrage (z.B. IP-Adresse des Browsers)
$_ENV Dieses Array enthält die Umgebungsvariablen (je nach Betriebssystem verschie-
den).
$_GET Die Parameter die über die URL an das PHP-Programm übergeben wurden.
1.3 Dateien und Ordnern in PHP
In diesem Kapitel wird beschreiben, wie PHP mit Dateien und Ordnern arbeiten kann und welche
Web-spezifischen Probleme dabei auftreten.
1.3.1 Zugriffsrechte
Achtung: Auf einem UNIX-Webserver läuft das PHP-Programm unter dem Account des Webservers,
nicht unter Ihrem Account! Dies wird relevant, sobald ein PHP-Programm eine andere Datei lesen
oder (über-)schreiben soll.
Beim Upload der Dateien auf den Webserver mit einem FTP oder SFTP Programm sollten Sie auch die
Möglichkeit haben, die Zugriffsrechte anzusehen bzw. zu verändern. Abbildung 10 zeigt links die Dar-
stellung der Zugriffsrechte in der Shell, rechts das Verändern der Zugriffsrechte mit Dreamweaver.
MMT Webprogrammierung 2 20
Abbildung 10: UNIX Zugriffsrechte mit Dreamweaver setzen
Eine kurze Wiederholung der UNIX-Zugriffsrechte: Es gibt drei Rechte (Lesen, Schreiben, Ausführen)
und drei Gruppen von Usern die unterschieden werden (Eigentümer, Gruppe, Andere). Im Terminal
werden diese Rechte als Buchstaben angezeigt: r steht für Lesen, w für Schreiben, x für Ausführen.
Das PHP-Programm läuft nicht unter Ihrem Account, sondern unter dem Account des Webservers.
D.h. für das PHP-Programm gelten die Zugriffsrechte „für Alle“.
Mit den PHP-Funktionen is_readable() und is_writable() können Sie testen, ob das Programm
Lese- bzw. Schreibrechte auf eine bestimmte Datei hat.
1.3.2 Ordner auflisten
Um herauszufinden, welche Dateien (und Unter-Ordner) sich in einem Ordner befinden, verwendet
man die Funktion glob. (Achtung: die Funktionen opendir, readdir, closedir gibt es auch, die sind
zu verarbeiten, könnte folgendes Programm verwendet werden:
<?php $anzahl = $_GET['anzahl']; $adresse = $_GET['adresse']; echo("<p>Ihre Bestellung über $anzahl Flugzeuge ist eingelangt</p>"); echo("<p>Die Flugzeuge werden binnen 1 Monat an $adresse geliefert</p>"); ?>
Dabei wird aber die Eingabe nicht geprüft. Eine bessere Version des Programmes prüft vorher jede
Eingabe und gibt entsprechende Fehlermeldungen aus:
<?php $anzahl = $_GET['anzahl']; $adresse = $_GET['adresse']; $ok = true; // zeigt ob alle Eingaben ok sind $fehler = array(); // sammelt alle Fehlermeldungen if( (int) $anzahl != $anzahl or $anzahl < 1) { $ok = false; $fehler[] = "Bitte geben Sie die Anzahl der Flugzeuge ein!"; } if( strlen( $adresse ) < 5 ) { $ok = false; $fehler[] = "Bitte geben Sie die vollständige Lieferadresse an!"; } if ( ! $ok ) { echo("<p>Ihre Bestellung kann derzeit nicht bearbeitet werden:</p>"); echo("<ol>"); foreach( $fehler as $fehler_text ) { echo("<li>$fehler_text</li>"); } echo("</ol>"); echo("<p>Bitte gehen Sie zurück und bessern Sie die Bestellung aus."); } else { echo("<p>Ihre Bestellung über $anzahl Flugzeuge ist eingelangt</p>"); echo("<p>Die Flugzeuge werden binnen 1 Monat an $adresse geliefert</p>"); } ?>
MMT Webprogrammierung 2 39
2.4.3 Datei Upload
Die Verarbeitung von hochgeladenen Dateien ist wesentlich komplizierter: Die Dateien werden vom
PHP-Interpreter temporär gespeichert. Das PHP-Programm kann die Dateien dann an einen perma-
nenten Speicherort kopieren (falls das die Zugriffsrechte erlauben)
Die Details zu den Hochgeladenen Dateien sind im Array $_FILES gespeichert, in folgendem Beispiel
hatte das Eingabefeld den Namen „bild“:
$_FILES['bild']['name'] Der Originalname der Datei am Client.
$_FILES['bild']['type'] Der „Mime Type“ der Datei – falls der Browser diese In-formation liefert. Zum Beispiel „image/gif“. Achtung: nicht
zuverlässig!
$_FILES['bild']['size'] Größe der hochgeladenen Datei in Byte.
$_FILES['bild']['tmp_name'] Der Dateiname der temporären Datei.
$_FILES['bild']['error'] Fehlercode bei Upload, 0 bedeutet dass kein Fehler aufge-
Achtung: Sie müssen den Ordner img erstellen und ihm geeignete Zugriffsrechte zuweisen, damit der
Webserver (= ein anderer Account) hinein-schreiben darf!
MMT Webprogrammierung 2 40
2.5 PHP und E-Mail
Die Funktion zum Senden von E-Mail heißt mail:
mail( "[email protected]", "Just another SPAM", "Das ist der Text in der E-Mail" );
Dazu passend wieder der Trick, wie man viel Text in einen langen String schreiben kann:
$text <<<Ende Lieber Newsletter-Kunde! wir freuen uns, dass Sie unseren Newsletter zum Thema $thema abonniert haben. Ende; mail("[email protected]", "Just another $thema-Newsletter", $text);
Wie die Mail vom PHP-Interpreter versandt wird, ist in der PHP- Konfiguration festgelegt. Die Konfi-
gurations-Datei hat den Namen php.ini. Wenn man PHP auf dem eigenen Computer betreibt, kann
man den SMTP-Server des Providers eintragen um die ausgehende Mail über diesen Server zu
Der Befehl phpinfo() gibt die ganze Konfiguration von PHP aus. Hier kann man auch die Mail-
Konfiguration nachlesen:
Abbildung 17: Konfiguration von PHP für Mail
MMT Webprogrammierung 2 41
MMT Webprogrammierung 2 42
3. Webapplikationen mit MySQL
3.1 Ziele
Was Sie wissen sollten
• Wie Sie von PHP aus auf Ihre MySQL-Datenbank zugreifen können: Aufbau der Verbindung,
query, fetch, Beenden der Verbindung.
• Dass das Filtern der Daten in der Datenbank passieren sollte und möglichst wenige Daten
nach PHP übertragen werden sollten.
• Wie Datensatz in der Datenbank und Array in PHP zusammenhängen.
Was Sie können sollten
• In einer Webapplikation mit Datenbank kleine Veränderungen und Verbesserungen vorneh-
men.
3.2 PHP und MySQL
MySQL ist die relationale Datenbank, die bei gemietetem Webspace am öftesten angeboten wird.
Hier wird nicht die Funktionsweise einer relationalen Datenbank erklärt (siehe Lehrveranstaltung im
1.Semester), sondern nur die Besonderheiten von MySQL und die für Web-Applikationen wichtigen
Aspekte.
3.2.1 MySQL Installation, Wiederholung, Dokumentation
MySQL ist im Paket XAMPP enthalten. (Man könnte die Datenbank auch separat von mysql.com her-
unterladen und installieren.) In der Standardinstallation ist ein Administrator-Account „root“ ohne
Passwort vorhanden. Die MySQL-Shell wird wie folgt gestartet:
> mysql –u username –p datenbankname Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 to server version: 5.0.27-community-nt Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql>
Ein Beispiel zur Orientierung in der Datenbank des mma-Portfolios
> mysql –u mmtuser –p mma
Das Passwort lautet „geheim!“. Die weiteren Code-Beispiele sind alle ein bisschen gekürzt.
MMT Webprogrammierung 2 43
Show Tables zeigt alle Tabellen in der aktuellen Datenbank:
mysql> show tables; +---------------+ | Tables_in_mma | +---------------+ | macht | | media | | media_werk | | person | | staff | | student | | werk | +---------------+ 24 rows in set (0.00 sec)
Describe zeigt den Aufbau einer bestimmten Tabelle:
mysql> select pid,vorname from person limit 1,8; +-----+-------------+ | pid | vorname | +-----+-------------+ | 2 | Paul | | 3 | Edvard Paul | | 4 | Sandra | | 5 | Philipp | | 6 | Antal | | 7 | Sebastian | | 8 | Johannes | | 9 | Ivan | +-----+-------------+ 10 rows in set (0.00 sec)
Die Details zu SQL in MySQL (Abweichungen vom Standard, Erweiterungen) kann man der Dokumen-
tation entnehmen die Online unter http://dev.mysql.com/ erreichbar ist.
MMT Webprogrammierung 2 44
Abbildung 18: Dokumentation von MySQL auf http://dev.mysql.com/
Ein häufig verwendetes Tool ist der phpMyAdmin, der ein Interface am Web zur Verfügung stellt. Am
gemeinsamen MMA/MMT-Server ist er unter der Adresse https://multimediaart.at/phpmyadmin/ zu
finden.
Abbildung 19: phpMyAdmin
Über phpMyAdmin kann man viele SQL-Abfragen durch Point+Klick formulieren. Das lehrreiche daran:
phpMyAdmin zeigt immer das SQL-Statement mit an — auf diese Art kann man einfach SQL lernen.
Besonders praktisch ist das beim Anlegen und Verändern von Tabellen. Erster Schritt: Name der Ta-
belle:
MMT Webprogrammierung 2 45
Zweiter Schritt: Spalten definieren:
Dritter Schritt: Tabelle wird angelegt und dazugehörendes SQL-Statement angezeigt:
3.2.2 MySQL von PHP aus
Um von PHP auf die Datenbank zuzugreifen gibt es verschiedene Schnittstellen. Hier wird die „MySQL
Improved Extension“ (myslqi) vorgestellt.
So funktioniert der Verbindung-Aufbau (und -Abbau) zur mysql-Datenbank:
<? $db = mysqli_connect ("localhost", "username", "passwort", "datenbank") or die ("Kein Zugriff auf die Datenbank mit dem Namen mmt"); echo ("Zugriff zur Datenbank OK"); mysqli_close($db); echo ("Verbindung zur Datenbank wieder beendet"); ?>
Es gibt noch keinen tollen Output - wir haben bisher nur eine Verbindung zur Datenbank, aber haben
noch keine Daten abgefragt.
Eine Abfrage aus der Datenbank liefert eine ganze Tabelle von Daten (mehrere Datensätze). Man
braucht also eine Schleife um alle Datensätze abzuarbeiten. Innerhalb der Schleife erhält man den
einzelnen Datensatz als Array.
Betrachten Sie folgenden Code und finden Sie die Verbindung zur Datenbank: Wo sehen Sie den Na-
men der Tabelle? Die Namen der Spalten?
MMT Webprogrammierung 2 46
$ergebnis = mysqli_query ( $db, "SELECT * FROM person WHERE ifshow=1 LIMIT 1,10" ); while($person = mysqli_fetch_array($ergebnis)) { echo($person["vorname"]); echo("<br />"); }
Was müssten Sie verändern um den Nachnamen ebenfalls anzuzeigen?
Ein ganz wichtiges Grundprinzip beim Programmieren mit Datenbanken: Das Filtern und Berechnen
der Daten möglichst in der Datenbank erledigen und möglichst wenige Daten zu PHP übermitteln.
Folgender Ansatz wäre also ganz schlecht, besonders wenn viele Daten in der Datenbank sind:
Jede einzelne Zeite ist – wie in Kapitel 1.2.2 beschrieben – mit Hilfe von includes aufgebaut. Dabei
werden immer die Dateien functions.php (mit der Datenbank-Verbindung) header.php und foo-
ter.php inkluidert.
<?php $pagetitle = "Titel der Seite"; include "functions.php"; include "header.php"; // hier passiert die eigentliche Arbeit include "footer.php"; ?>
3.3.1 Viele Datensätze aus der Datenbank lesen
In der Datei werke.php finden Sie ein Beispiel für die Auflistung von mehreren Datensätzen:
echo "<p>10 zufällige Werke:</p> <ul>"; $ergebnis = mysqli_query ( $db, "SELECT * FROM werk ORDER BY RAND() LIMIT 1,10" ); while($werk = mysqli_fetch_array($ergebnis)) { echo("<li>$werk[titel] $werk[pub_date]</li>"); } echo("</ul>");
3.3.2 Einzelne Daten aus der Datenbank lesen
In der Datei home.php finden Sie zwei Beispiele für das Lesen einzelner Daten. Mit der SQL-Funktion
COUNT() wir die Anzahl der Werke in der Datenbank bestimmt.
$ergebnis = mysqli_query ( $db, "SELECT COUNT(*) AS anzahl FROM werk" ); $datensatz = mysqli_fetch_array($ergebnis); $anz_werke = $datensatz['anzahl']; echo("<p>Es befinden sich $anz_werke Werke in der Datenbank</p>");
3.3.3 Einen bestimmten Datensatz lesen
Wenn Sie die Datei person.php mit einem Parameter aufrufen person.php?pid=586 soll eine bestimm-
te Person aus der Datenbank angezeigt werden. Dafür wird der Parameter aus dem $_GET – Array
ausgelesen und sicher gestellt, dass es sich wirklich um eine Zahl handelt.
In der Datenbank sind Personen, deren Profil nicht angezeigt werden soll, mit ifshow=0 gekennzeich-
net. Im SQL-Statement wird sicher gestellt, dass nur sichtbare Personen angezeigt werden. Das Er-
gebnis der Abfrage kann also sein, dass keine Person gefunden wurde – entweder weil unter diesem
Schlüssel gar keine gespeichert ist, oder weil ifshow=0 ist. In diesem Fall gibt mysqli_fetch_array kein
Array sondern der Wert FALSE zurück.
MMT Webprogrammierung 2 49
$pid = $_GET['pid']; if( (int) $anzahl != $anzahl ) { echo("Error !"); } else { $ergebnis = mysqli_query ( $db, "SELECT * FROM person WHERE ifshow=1 AND pid=$pid" ); $person = mysqli_fetch_array($ergebnis); if( $person == FALSE ) { echo "<p>Konnte keine passenden Daten aus der Datenbank lesen.</p>"; } else { // Darstellung der Person } }
Die Darstellung der einzelnen Person ist noch nicht fertig programmiert: der Username wird zwar
angezeigt, aber nicht die Anzahl der Werke der Person. Das müssen Sie selbst ausprogrammieren.
Für die Ausgabe des HTML-Codes wird die Heredoc-Schreibweise6 verwendet um die Ausgabe von
Variablen und die Verwendung von Anführungszeichen kombinieren zu können.
if( $person['isfemale'] ) { $anrede = "Frau"; $ersie = "Sie"; } else { $anrede = "Herr"; $ersie = "Er"; } echo <<<EOM <p><img src="http://multimediaart.at/media/profil/$person[bildpfad]" /> $anrede $person[vorname] $person[nachname] hat insgesamt x Werke in dieser Datenbank. $ersie hat den Usernamen $person[uid].</p> EOM;
In der Datei personen.php wird zu jeder Person ein passender Link zu person.php angezeigt:
In PHP finden Sie die bereits gesetzten Cookies, die vom Browser zurückgesendet wurden, im Array
$_COOKIES (und — zusammen mit GET und POST-Parametern — in $_REQUEST). Neue Cookies kön-
nen Sie mit setcookie() setzen.
Cookies in Javascript
Im Client können Cookies mit Javascript gelesen und geschrieben werden: über die Eigenschaft docu-
ment.cookie des Dokument-Objekts.
Achtung: beim lesenden Zugriff auf diese Eigenschaft enthält man einen String mit allen Cookies, die
gerade gültig sind.
Zum Setzen von neuen Cookies wird auf die Eigenschaft zugewiesen. Zum Setzen mehrere Cookies
wird wiederholt zugewiesen — das hat aber (noch) keinen Einfluß auf den Wert den man aus docu-
ment.cookie auslesen kann:
alert(document.cookie); // Zeigt die gültigen Cookies document.cookie = "farbe:grün"; document.cookie = "anzahl: 3"; document.cookie = "passwort: total super geheimes aber recht langes passwort"; alert(document.cookie); // Zeigt immer noch die ALTEN Cookies !!!
Erst wenn ein neuer Request an den Server erfolgt, werden die neu gesetzten Cookies mit gesendet:
erst wenn die Antwort wieder dargestellt wird, sind die neuen Cookies in Javascript über docu-
ment.cookie lesbar!
4.2.2 Session
PHP kann das Setzen des Cookies automatisch erledigen, und geht sogar noch einen Schritt weiter:
Mit dem Befehle session_start() wird
o …beim ersten Aufruf automatisch ein Cookie gesetzt. Wenn danach Daten im Array
$_SESSION Daten gespeichert werden, dann sorgt PHP dafür dass die Daten am Server per-
manent gespeichert werden, also beim nächsten Programmaufruf wieder zur Verfügung ste-
hen.
o …bei jedem weiteren Aufruf die Session an Hand des Cookies wieder identifiziert, und die Da-
ten wieder ins $_SESSION-Array geladen.
MMT Webprogrammierung 2 54
Für unsere Applikation werden wir das verwenden, um den Usernamen des angemeldeten Users zu
speichern. session_start() wird in functions.php ausgeführt, also bei jedem Aufruf einer der Seiten
der Applikation. Die Applikation zeigt direkt in der Navigationsleiste die Login/Logout-Möglichkeit
und den Namen des eingeloggten Users an:
Abbildung 23: Anzeige des Usernamens und Login/Logout-Möglichkeit
Das Login-Formular sieht ganz einfach aus und sendet die Daten mit POST:
Abbildung 24: Login-Formular der Applikation
Username und Passwort werden überprüft, falls Sie passen wird der Username in der Session gespei-
chert:
if ( strlen($username) > 0 and check_login( $username, $passwort ) ) { $_SESSION['USER'] = $username; header("Location: index.php"); exit; }
Nach dem gelungen Login kann man jede beliebige Seite der Applikation aufrufen, immer wird im
Array $_SESSION der Username gespeichert sein. So kann er z.B. in der Navigation angezeigt werden
wie in Abbildung 23 gezeigt.
Das Logout erfolgt ebenfalls mit der Methode POST:
Das Logout ist etwas umständlich zu Programmieren: das Cookie, das von PHP gesetzt wurde, muss
man nun selbst löschen. Dazu wird das „Ablaufdatum“ des Cookies auf ein Datum in der Vergangen-
heit gesetzt, dann wird der Browser es löschen.
MMT Webprogrammierung 2 55
// Löschen aller Session-Variablen. $_SESSION = array(); // Löscht das Session-Cookie. if (isset($_COOKIE[session_name()])) { setcookie( session_name(), // Cookie-Name war gleich Name der Session '', // Cookie-Daten. Achtung! Leerer String hier hilft nicht! time()-42000, // Ablaufdatum in der Vergangenheit. Erst das führt zur Löschung! '/' // Wirkungsbereich des Cookies: der ganze Server ); } session_destroy(); header("Location: index.php")
Achtung: das Setzen und Löschen der Session-Cookies dauert immer einen Request länger als ge-
dacht! Deswegen ist eine Weiterleitung wie hier mit Location: sinnvoll.
Achtung: die Weiterleitung funktioniert nur, wenn noch keine Ausgabe erfolgt ist, also vor dem La-
den der header-include-Datei. Hier am Beispiel von login:
<?php $pagetitle = "Login"; include "functions.php"; $username = $_POST['username']; $passwort = $_POST['passwort']; if ( strlen($username) > 0 and check_login( $username, $passwort ) ) { $_SESSION['USER'] = $username; header("Location: index.php"); exit; } include "header.php";
Eine Weiterleitung nach der Behandlung eines POST-Requests ist allgemein sinnvoll.
MMT Webprogrammierung 2 56
Abbildung 25: Login mit einer Weiterleitung
4.3 Web-Applikation mit Schreibrecht
Um eine Web-Applikation auszuprobieren, die nicht nur Daten lesen, sondern auch Daten löschen
und in die Datenbank schreiben kann, brauchen Sie nun die eigene Datenbank – die Datenbank mma
reicht nicht mehr aus, dort haben Sie keine Schreibrechte.
Um Daten in die eigene Datenbank zu laden finden Sie die Datei mma-portfolio-simple.sql in der
ZIP-Datei. Über die Kommandozeile können Sie diese Daten in Ihre private Datenbank laden:
> mysql –u username –p nameihrerdatenbank < mmy-portfolio-simple.sql
Danach können Sie die vorhandene Mini-Applikation so verändern, dass Sie auf Ihre eigene Daten-
bank zugreift. (Tipp: nur eine Zeile in einer Datei muss verändert werden!)
Titel Dateiname Request/ Parameter
Beschreibung
Login login.php GET Zeigt Login-Formular
Login Login.php POST
username, passwort
Prüft Login + setzt Session. � Leitet weiter
an index.php
Logout logout.php POST Löscht die Session. Leitet weiter an in-
dex.php
MMT Webprogrammierung 2 57
Person
löschen
delete.php POST pid Löscht die Person mit der angegeben pid.
Person
einfügen
person_new.php GET Zeigt Eingabeformular für eine neue Per-
son
Person
einfügen
person_new.php POST uid,vorname,nachname, profil,mail,web, blog,feed,title,
isfemale,ifshow
Legt eine neue Person an.
Person
bearbeiten
person_edit.php GET pid Zeigt Bearbeitungs-Formuar an
Person
bearbeiten
person_edit.php POST pid, vorname, nachname, profil,
Speichert neue Daten zur Person pid
4.3.1 Daten löschen
Das Löschen könnte so einfach sein: Ein Programm mit namen delete.php, das als Parameter die id
der Person erhält, die gelöscht werden soll:
$pid = $_POST['pid']; mysqli_query($db, "DELETE FROM person WHERE pid=$pid" );
Dieses Programm ist anfällig für folgende Attacke: Ein Aufruf mit einem selbst gebastelten Formular
setzt den Parameter pid auf Wert „9 OR 1=1“
<form method="post" action="delete.php" >
<input type="hidden" value="9 OR 1=1" name="pid"/> <input type="submit" value="del all"/>
</form>
Das führt dazu, dass folgendes SQL-Statement ausgeführt wird:
DELETE FROM person WHERE pid=9 OR 1=1
Und dieses Statement löscht nicht einen Datensatz sondern alle Datensätze. Diese Art von Attacke
auf eine Web-Applikation nennt man „SQL Injection“.
SQL Injection verhindern
Dieses Problem kann vermeiden indem man die Eingabe genau überprüft. In diesem Beispiel also:
nur wenn es sich bei pid um eine ganze Zahl handelt, darf sie verwendet werde. Das wird hier mit
einer Regular Expression (die Sie noch nicht verstehen müssen) überprüft:
MMT Webprogrammierung 2 58
if( ! preg_match( '/^\d+$/', $pid ) ) { error_log("hack: $pid statt id in delete.php."); echo("Hack detected. Please stay at you computer until the police arrive."); exit; }
Der zweite Ansatz ist die Verwendung von „Prepared Statements“ in der Datenbank. Dabei wird der
SQL-Interpreter der Datenbank gänzlich umgangen.
Als erster Schritt wird mit prepare ein SQL-Statement mit Fragenzeichen als Platzhalter vorbereitet.
(Dieses SQL-Statement wird am Server schon mal geparsed und compiliert.) In einem zweiten Schritt
werden Daten an das Statement gebunden (bind), dabei muss man angeben ob es sich um einen
Integer-Wert (i), einen double-Wert (d) einen string(s) oder einen blob (b) handelt. Mit execute wird
dann das Statement ausgeführt.
$stmt = mysqli_prepare($db, "DELETE FROM person WHERE pid=?"); $ok = mysqli_bind_param($stmt, 'i', $pid); mysqli_stmt_execute($stmt);
Die Schritte 2 und 3 können auch mehrfach ausgeführt werden, das ist effektiver als ein normales
mysqli_query zu wiederholen.
4.3.2 Daten einfügen
Hier das einfachste Programm, das ein neues Werk speichert:
mysqli_query( $db, "INSERT INTO werk (titel) VALUES ('$_POST[titel]')" );
Das funktioniert für viele Eingabe, aber was passiert wenn ein Werk den Titel „That’s it“ haben soll?
Dann wird folgendes SQL-Statement ausgeführt:
INSERT INTO werk (titel) VALUES ('That's it')
Das kann nicht funktionieren. Für dieses Problem gibt es in PHP eine einfache und falsche Lösung:
Normalerweise verändert PHP automatisch alle Daten die über GET, POST und Cookies hereinkom-
men: vor alle Anführungszeichen wird ein Backslash eingefügt. Aus „That's it“ wird also automa-
tisch „That\'s it“ , das SQL-Statement funktioniert wieder:
INSERT INTO werk (titel) VALUES ('That\'s it')
Diese Automatik ist unter dem Namen „magic_quotes“ bekannt und kann in der Apache- oder PHP-
Konfiguration abgeschalten7 werden. Auf dem MMT-Server ist sie generell ausgeschalten. Sie sollten
(In Wirklichkeit kann man Sie nicht ganz abschlalten8, aber das ignorieren wir besser. Das Problem
betrifft nur Array-Parameter .)
Wenn die magic quotes abgeschalten sind kann man das SQL-Problem besser lösen: mit prepared
Statements. Hier am Beispiel eines neuen Werkes:
$stmt = mysqli_prepare($db, "INSERT INTO person (uid, vorname, nachname, profil, mail, web, blog, feed, title, isfemale, ifshow) VALUES (?,?,?,?,?,?,?,?,?,?,?)"); mysqli_bind_param($stmt, 'sssssssssii', $_POST['uid'], $_POST['vorname'], $_POST['nachname'], $_POST['profil'], $_POST['mail'], $_POST['web'], $_POST['blog'], $_POST['feed'], $_POST['title'], $_POST['isfemale'], $_POST['ifshow'] ); mysqli_stmt_execute($stmt); // noch ohne Fehlerbehandlung
Der letzte Befehl mysqli_stmt_execute($stmt) liefert einen Boolschen Wert zurück um den Erfolg
oder Misserfolg der gesamten SQL-Anfrage anzuzeigen. Falls ein Fehler auftritt kann man mit mysq-
li_error($db) die Fehlermeldung der Datenbank auslesen.
if ( ! mysqli_stmt_execute($stmt) ) { echo("Fehler beim Speichern in der Datenbank: "); echo(mysqli_error($db)); echo(" Bitte gehen Sie zurück zum Formular!"); exit; }
Aber so weit sollten Sie es nicht kommen lasse: Sie sollten die Eingaben aus dem Webformular schon
vor dem INSERT prüfen und dann ausführliche, vollständige, deutsche Fehlermeldungen ausgeben.
8 http://at2.php.net/get_magic_quotes_gpc#49612
MMT Webprogrammierung 2 60
Abbildung 26: Fehlermeldung der Datenbank vs. selbst gestaltete Fehlermeldung
Falls das Einfügen der Daten funktioniert hat und in der Tabelle ein autoincrement-Feld als Primär-
schlüssel vorhanden ist, kann man den Wert des Schlüssels im neuen Datensatz auslesen und weiter
Auch hier ist eine Weiterleitung direkt nach dem POST-Request sinnvoll: nach dem Einfügen des Da-
tensatzes wird direct auf die Anzeige des neuen Datensatzes weitergeleitet. Falls man danach auf
„Reload“ drückt wird der Datensatz neu angezeigt, aber keinesfalls ein zweites Mal eingefügt.
4.3.3 Einen Datensatz bearbeiten
Wir wollen einen Datensatz aus der Datenbank laden, in einem Formular zur Bearbeitung anbieten,
und dann wieder in der Datenbank speichern.
Abbildung 27: Formular zum Bearbeiten einer Person
Das Lesen des Datensatzes aus der Datenbank erfolgt nun auch mit einem prepared Statement:
$stmt = mysqli_prepare($db, "SELECT pid,vorname,nachname,profil FROM person WHERE pid=?"); mysqli_bind_param($stmt, 'i', $_GET['pid']); mysqli_stmt_execute($stmt); mysqli_bind_result($stmt, $pid,$vorname,$nachname,$profil); mysqli_stmt_fetch($stmt) or die("konnte den datensatz nicht laden");
Bei der Darstellung des Bearbeitungs-Formulars werden die Daten nun als Standardwerte dargestellt.
Das passiert bei Textfeldern mit dem Value-Attribute und bei Textareas als Inhalt des Tags:
MMT Webprogrammierung 2 61
<input name="vorname" value="Tobias" /> <textarea name="profil" rows="7">Webdesigner und Programmierer.</textarea>
Achtung: Falls in den Daten Anführungszeichen, kaufmännische Unds oder Kleiner-Zeichen vorkom-
men müssen diese für HTML escaped werden. Hier ein Beispiel in MySQL:
mysql> select vorname,profil from person where pid=538; +---------------------+-----------------------------+ | vorname | profil | +---------------------+-----------------------------+ | Tobias "the coder" | Mein Lieblings-Tag: <style> | +---------------------+-----------------------------+ 1 row in set (0.00 sec)
So würde die Darstellung der Eingabefelder nicht funktionieren:
Die veränderten Daten werden mit POST an person_edit.php geschickt. Aus den Daten wird ein UP-
DATE-Statement erstellt:
MMT Webprogrammierung 2 62
if( $_POST['pid'] ) { $stmt = mysqli_prepare($db, "UPDATE person SET vorname = ?, nachname = ?, profil = ? WHERE pid=?"); mysqli_bind_param($stmt, 'sssi', $_POST['vorname'], $_POST['nachname'], $_POST['profil'], $_POST['pid'] ); if( ! mysqli_stmt_execute($stmt) ) { echo("Fehler beim Speichern in der Datenbank: "); echo(mysqli_error($db)); exit; } header("Location: person.php?pid=$_POST[pid]"); }
4.3.4 Escapen von HTML
Das Escapen der Daten für HTML hätten wir von Anfang an bei jeder Ausgabe von Daten aus der Da-
tenbank zu müssen. Also auch schon in Kapitel 3.3 beim Anzeigen der Daten. Damals haben wir ein-
fach die Daten direkt mit echo ausgegeben:
echo <<<EOM $anrede $person[vorname] $person[nachname] hat insgesamt x Werke in dieser Datenbank. $ersie hat den Usernamen $person[uid]. $person[profil] EOM
Wenn hier im Profil wieder „Mein Lieblings-Tag ist <style>“ steht, und dieser Text einfach ausgege-
ben wird, dann „verschwindet“ der Rest der Webseite, weil er sich nun innerhalb eines Style-Tags
befindet.
$bildpfad = htmlspecialchars( $person['bildpfad'] ); $uid = htmlspecialchars( $person['uid' ] ); $vorname = htmlspecialchars( $person['vorname' ] ); $nachname = htmlspecialchars( $person['nachname'] ); $profil = htmlspecialchars( $person['profil' ] ); echo <<<EOM <p><img src="http://multimediaart.at/media/profil/$bildpfad" style="float:right" /> $anrede $vorname $nachname hat insgesamt x Werke in dieser Datenbank. $ersie hat den Usernamen $uid.</p> <div>$profil</div> EOM;
Damit funktioniert nun die Darstellung des Datensatzes richtig:
MMT Webprogrammierung 2 63
Abbildung 28: Korrekte Darstellung eines Datensatzes mit kleiner-Zeichen
4.3.5 Darstellen von HTML
Im letzten Beispielen wurde der eingegebene HTML-Tag sichtbar auf der Webseite angezeigt. Wie
kann man HTML-Tags eingeben, abspeichern, und als HTML-Tags wieder anzeigen?
Gefahren
Zuerst eine Warnung: Die Anzeige von HTML das von Fremden eingegeben wurde ist gefährlich! Dazu
zwei Beispiele: Sie bauen ein Gästebuch in dem BesucherInnen beliebiges HTML abspeichern können.
So kann Frau Hacker das Cookie einer BesucherIn Ihres Gästebuchs entwenden. Sie kann nun das
Cookie verwenden um als eingeloggter User Ihre Seite zu benützen!
Lassen Sie niemals, niemals, niemals zu, dass Fremde Javascript in Ihre Site einspeisen können!
MMT Webprogrammierung 2 64
Noch hat unsere Applikation dieses Problem nicht: Wenn Frau Hacker Ihren Code z.B. in das Profil
einer Person eingibt wir der Code htmlescaped angezeigt und „wirkt nicht“:
Abbildung 29: Eingegebener HTML+Javascript-Code wird escaped und dargestellt
Sichere Eingabe von HTML
Für die Beispiel-Applikation wollen wir Zulassen, dass im Profil die HTML-Tags <p> und <b> verwen-
det werden können, mehr nicht. Dass es nur diese Tags und keine anderen sind wird bei der Eingabe
und der Bearbeitung sicher gestellt:
$profil = strip_tags( $_POST['profil'], "<p><b>" ); $stmt = mysqli_prepare($db, "UPDATE person SET profil = ? WHERE pid=?"); mysqli_bind_param($stmt, 'si', $profil, $_POST['pid'] );
Nun können Sie auch die Ausgabe des Profils umstellen und auf das escapen verzichten:
$bildpfad = htmlspecialchars( $person['bildpfad'] ); $uid = htmlspecialchars( $person['uid' ] ); $vorname = htmlspecialchars( $person['vorname' ] ); $nachname = htmlspecialchars( $person['nachname'] ); // das Profil darf einige HTML-Tags enthalten, also nicht escapen! $profil = $person['profil' ]; echo <<<EOM <p><img src="http://multimediaart.at/media/profil/$bildpfad" style="float:right" /> $anrede $vorname $nachname hat insgesamt x Werke in dieser Datenbank. $ersie hat den Usernamen $uid.</p> <div>$profil</div> EOM;
MMT Webprogrammierung 2 65
Die Eingabe des HTML-Codes können Sie mit einem Javascript-Editor wie TinyMCE9 erleichtern. Ti-
nyMCE verwandelt eine normale Textarea in einen wysiwyg-Editor:
Abbildung 30: Normale Textarea (oben) kann mit TinyMCE in einen wysiwyg-Editor (unten) verwandelt werden
9 http://tinymce.moxiecode.com/download.php
MMT Webprogrammierung 2 66
5. AJAX und REST
Die Kombination von Javascript und PHP gibt AJAX. Das Prinzip REST hilft uns unnötigen Einsatz von
AJAX zu vermeiden.
5.1 Ziele
Was Sie alle wissen sollten
• Wie AJAX funktioniert.
• Was REST ist.
• Was für und gegen den Einsatz von AJAX in einem bestimmten Fall spricht.
Was Sie können sollten
• Mit der jquery-Library eine Formularprüfung implementieren
• Mit der jquery-Library AJAX implementieren.
5.2 Wiederholung: Was ist AJAX
AJAX ist die englische Abkürzung für „Asynchrones Javascript und XML“. Der Begriff AJAX wurde von
Jesse James Garrett zuerst verwendet10. Es steht für eine besondere Verwendung von Javascript und
einer serverseitigen Programmiersprache.
Ein Beispiel für die Verwendung von AJAX ist das in Abbildung 31 gezeigte Eingabefeld: schon wäh-
rend des Eintippens eines Suchwortes wird eine Anfrage an den Webserver geschickt. Dieser ant-
wortet mit einer Liste von vorgeschlagenen Namen. Diese Liste wird mit Javascript (unter Verwen-
dung der DOM) in einer <div> unterhalb des Eingabefelds angezeigt:
Abbildung 31: Vorschläge für die Eingabe werden über AJAX geladen
Diese Schreibweise kann man (auf einem Apache Webserver) mit Hilfe des Rewrite Moduls konfigu-
rieren. Damit werden die URLs am Server „übersetzt“. Im Konkreten Beispiel müsste man in die Da-
tei .htaccess im Ordner mini schreiben:
RewriteEngine On RewriteRule ^personen$ personen.php [L] RewriteRule ^person/(.*) person.php?pid=$1 [L]
Umsetzung: die Umstellung auf diese URLs hat Auswirkungen falls sie relative Links verwendet haben,
um z.B. auf Stylesheets zu verweisen. Deswegen rate ich von einer nachträglichen Umstellung der
URLs ab – das ist sehr viel mehr Arbeit als man denkt.
5.3.2 Dokumente sollen Links auf andere Dokument enthalten
Dieses Prinzip haben wir in allen bisher gezeigten Beispielen erfüllt.
Umsetzung: dieses Prinzip müssen Ihre Web-Applikationen auf jeden Fall erfüllen.
5.3.3 HTTP-Methoden GET, POST, PUT, DELETE
Wie sollen diese Methoden verwendet werden? Jede Methode hat eine Bedeutung:
GET Eine Repräsentation einer Ressource soll geholt werden. Das verändert nichts an
der Ressource, diese Methode ist als harmlos.
POST Eine Ressource soll verändert werden. Typische Verwendung wäre also ein For-
mular zum Bearbeiten eines Datensatzes.
PUT Diese Methode dient zum Erzeugen einer neuen Ressource. Diese Methode steht bei normalen Web-Formularen aber nicht zur Verfügung. Deswegen wird statt-
dessen meist ein POST auf eine übergeordnete Ressource verwendet. Statt PUT
auf /person/7 also ein POST auf /personen
DELETE Diese Methode dient zum Löschen einer Ressource. Auch diese Methode steht
bei normalen Web-Formularen aber nicht zur Verfügung.
Umsetzung: in diesem Semester ist wichtig, dass Sie GET und POST korrekt einsetzen. Erst im Schwer-
punkt-Unterricht werden wir die anderen Methoden verwenden.
MMT Webprogrammierung 2 72
5.3.4 Ein Dokument – mehrere Repräsentationen
Ein Dokument kann auf verschiedene Arten repräsentiert werden: z.B. kann die Darstellung einer
Person in HTML, XML und JSON erfolgen. Die HTML-Variante kennen Sie schon:
<h1>Details zu einer Person</h1> <p><img src="http://multimediaart.at/media/profil/edvard_1_2.jpg" /> Herr Edvard Paul Beisteiner hat insgesamt 4 Werke in dieser Datenbank. Er hat den Usernamen fhs14287.</p> <ul> <li><a href='werk/24'>The Thin Red Line</a></li> <li><a href='werk/50'>Der böse Wolf</a></li> <li><a href='werk/83'>nimm zwei, schatz</a></li> <li><a href='werk/303'>the neighbour.</a></li> </ul>
Dieselbe Person könnte man auch als XML darstellen:
Hier ein Beispiel für eine Formularprüfung. Das submit-Event des Formular-Tags wird verwendet um
die Daten zu Prüfen und um das Absenden des Formulars gegebenenfalls zu verhindern (durch Rück-
gabe von false).
$("form").submit(function(){ var ok = true; var i; $("span.error").remove(); // Alle Fehlermeldungen entfernen i = $("input[name=uid]"); if(i.val() == '') { i.after('<span class="error">Bitte einen Usernamen eingeben</span>'); ok = false; } i = $("input[name=mail]"); if(i.val() == '') { i.after('<span class="error">Bitte eine E-Mail Adresse eingeben</span>'); ok = false; } return ok; });
Die Fehlermeldungen werden mit der Funktion after() direkt hinter dem betroffenen Eingabefeld
eingefügt.
5.5 jQuery und AJAX
Die Verwendung von jQuery soll nun an zwei weiteren Beispielen gezeigt werden.
5.5.1 Clientseitige Datenprüfung mit AJAX-Nachfrage beim Server
In der Webapplikation soll bei Eingabe eines Usernamens sofort am Server nachgefragt werden ob
dieser Username schon in Verwendung ist. Falls ja soll eine Fehlermeldung angezeigt werden:
Abbildung 34: Clientseitige Datenprüfung mit AJAX-Nachfrage beim Server
Als Auslöser der Prüfung wird das change-Event des Eingabefeldes verwendet:
MMT Webprogrammierung 2 75
$("input[name=uid]").change(function(){ ... });
Das Programm am Server ist sehr simpel: der Aufruf erfolgt über die URL
username_free.php?uid=hansi
Die Antwort ist plaintext: entweder 1 für wahr (Username ist frei) oder 0 für falsch (Username schon
vergeben).
Die Anfrage vom Client an den Server wird über die get-Funktion von jQuery gesendet. Dabei muss
eine Callback-Funktion angegeben werden, die aufgerufen wird sobald die Antwort des Servers vor-
Wird nun die Person gelöscht, so verschwindet automatisch auch der Datensatz in student:
mysql> DELETE FROM person WHERE pid=100; Query OK, 1 row affected (0.13 sec) mysql> SELECT * FROM student WHERE pid=100; Empty set (0.00 sec)
6.3 Transaktion
Achtung: Transaktionen funktionieren in MySQL nur zwischen Tabellen des Typ InnoDB (siehe
Seite 79).
Wenn wir eine neue Person in der Datenbank speichern, müssen wir immer zuerst den Eintrag in
person vornehmen, den (neu entstandenen) Primary Key pid auslesen, und damit dann eventuell
Einträge in student und/oder person vornehmen.
MMT Webprogrammierung 2 80
Bei Web-Applikationen kommt es oft zur unerwarteten Unterbrechung des Programms. So könnte es
z.B. passieren, dass das Programm unterbrochen wird, nachdem die person schon eingetragen ist,
aber bovor die Einträge in die anderen Tabellen gemacht wurden.
Damit trotzdem die Daten in der Datenbank immer konsistent bleiben, verwenden wir Transaktio-
nen: Die Transaktion stellt sicher, dass die gewünschte Veränderung in der Datenbank entweder
vollständig durchgeführt oder gar nicht durchgeführt wird — auf keinen Fall wird „bloß die Hälf-
te“ gemacht.
Ein Beispiel: eine Person wird eingefügt, das PHP-Programm führt dazu folgende SQL-Queries aus:
START TRANSACTION;
INSERT INTO person (uid, vorname, nachname, profil, isfemale, ifshow)
VALUES ('test', 'testvorname', 'testnachname', 'habe wenig profil', 0, 1);
SELECT pid FROM person where UID='test';
-- Ergebnis: 912
INSERT INTO student (pid,jg,graduated) VALUES (912, 'MMA1996', 1);
An dieser Stelle bricht die Verbindung zur Datenbank ab. Der Datenbankserver führt deswegen einen
automatischen ROLLBACK durch. Danach gibt es von der eben angelegten Person keine Spur mehr in
der Datenbank:
SELECT pid,vorname,nachname FROM person WHERE pid=912;
-- Ergebnis: Empty set
So sieht der Vorgang aus wenn alles gut geht: nach drei INSERTs kommt ein COMMIT:
START TRANSACTION;
INSERT INTO person (uid, vorname, nachname, profil, isfemale, ifshow)
VALUES ('test', 'testvorname', 'testnachname', 'habe wenig profil', 0, 2);
SELECT pid FROM person where UID='test';
-- Ergebnis: 913
INSERT INTO student (pid, jg, graduated) VALUES (913, 'MMA1996', 1);
INSERT INTO staff (pid,jobtitle) VALUES (913, 'Testobjekt');
COMMIT;
Mit dem COMMIT wird die Transaktion abgeschlossen, erst dann werden alle Änderungen an der Da-
tenbank wirklich durchgeführt.
Die mysqli – Datenank-Schnittstelle enthält eigene Befehle für start, rollback und commit der Trans-
aktion. Statt START TRANSACTION heisst es hier autocommit false:
mysqli_autocommit($db, FALSE);
Ein Absichtliches Rollback braucht man in der Fehlerbehandlung:
MMT Webprogrammierung 2 81
$stmt = mysqli_prepare($db, "INSERT INTO person ..."); mysqli_bind_param($stmt, ... ); if ( ! mysqli_stmt_execute($stmt) ) { echo("Fehler beim Speichern in der Datenbank: "); echo(mysqli_error($db)); mysqli_rollback($db); exit; }
Nur wenn alle drei INSERTs gut gegangen sind wird die Transaktion abgeschlossen:
mysqli_commit($db);
6.4 Andere DB-Schnittstellen
Wie anfangs erwähnt ist die MySQL-Schnittstelle „mysqli“ nur eine von vielen Datenbank Schnittstel-
len. Die primitivste Schnittstelle wäre „mysql“ (ohne i wie improved). Abschließend noch ein kurzer
Ausblick auf andere Schnittstellen: MDB2, ADODB und Zend Framework.
MDB214 aus dem "PHP Extension and Application Repository" (PEAR) ist datenbank-unabhängig und
unterstützt derzeit 8 verschiedene Datenbanken, darunter MySQL, Postgres und Oracle. MDB2 un-
Das Zend Framework bietet auch eine Komponente17 die ein Mapping von DB-Tabelle auf PHP-Klasse
ermöglicht (Table Data Gateway Design Pattern und Row Data Gateway Design Pattern).
class Person extends Zend_Db_Table_Abstract { protected $_name = 'person'; // Tabelle in der DB protected $_primary = 'pid'; // Primary key protected $_sequence = true; // --||-- ist auto_increment }
Diese Klasse entspricht der Tabelle person in der Datenbank, jedes Objekt der Klasse entspricht ei-
nem Datensatz in der Tabelle.
Wenn man diese Klassen in PHP verwendet werden die entsprechenden Operationen in der Daten-
Die letzte Einheit bietet einen Rückblick und den Ausblick auf weiter Themen der Webprogrammie-
rung. Das Thema Security wird im Rückblick noch einmal behandelt
MMT Webprogrammierung 2 89
7.1 Templates und MVC
Für eine moderne Web-Applikation brauchen wir eine Mischung aus HTML, CSS, Javascript, PHP, SQL.
Im schlechtesten Fall ist all dieser Code in einer Datei gespeichert, und eng ineinander vermischt – so
wie in den bisher gezeigten Beispielen.
Wie kann man diese Code-Mischung verhindern, den Code durchschaubarer machen und die Arbeits-
teilung zwischen Design (HTML+CSS) und Programmierung (Javascript, PHP, SQL) erleichtern?
7.1.1 Templates am Beispiel von Smarty
Das Smarty Template-System speichert die Templates in einem eigenen Ordner, die einzelnen Datei-
en können die Endung html haben. In einem zweiten Ordner templates_c speichert das System die
compilierten Templates.
Abbildung 38: Ordnerstruktur eines Projekts mit Smarty Templates
Der allgemeine Ablauf einer PHP-Datei lautet mit Smarty:
<?php require 'libs/Smarty.class.php'; $template = new Smarty; $template->assign("pagetitle","Person"); // Zeugs berechnen, aus der Datenbank holen ... $template->assign("vorname","Brigitte"); $template->display('person.html'); ?>
In der Template-Datei gibt es includes und Variablen, in der speziellen Smarty-Schreibweise mit ge-
schwungenen Klammern:
MMT Webprogrammierung 2 90
{include file="header.tpl"} <p>Es befinden sich {$anz_personen} Personen und {$anz_werke} Werke in der Datenbank</p> {include file="footer.tpl"}
Die Variablen werden mit $template->assign in das Template gespeichert. Es können auch Arrays
oder komplexere Datenstrukturen an das Template übertragen werden. In folgendem Beispiel wird
ein Array von Arrays übertragen:
$ergebnis = mysqli_query ( $db, "SELECT * FROM person WHERE ifshow=1 ORDER BY nachname" ); while($person = mysqli_fetch_array($ergebnis)) { $personen[] = $person; } $template->assign("personen", $personen);
Im Template wird das äußere Array mit einer foreach-Schleife abgearbeitet: