Praktikum im Grundstudium Teil 6: Dynamische Content-Generierung aus Datenbank-Daten als valid XHTML Aktueller Zustand • Sie sollten schon in der Lage sein… – Formulare in XHTML zu erzeugen (statisch oder dynamisch), – Formulare zu überprüfen (leere Felder, …) – Ausgefüllte Formulardaten entgegenzunehmen und dem Nutzer anzuzeigen – Formularwerte in die Datenbank zu speichern – Formularwerte aus der Datenbank zu lesen – Datenbankeinträge zu ändern • Was fehlt? – Diverse Kleinigkeiten – Alle diese Dinge zusammenbringen Æ Dynamische Generierung der Inhalte 1 Korrekter XHTML-Header • Auslassung aus Foliensatz 1 – Bekannt: Jedes XHML-Dokument sollte mit <html xmlns=… beginnen – Ausgelassen: DOCTYPE (für SGML-Konformität) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns= "http://www.w3.org/1999/xhtml"> </html> – Ohne DOCTYPE Fehler bei W3C-HTML-Validator Der Lebenszyklus eines Formulars/Skripts • Wie kann ein Formular so lange angezeigt werden, bis alle Eingaben korrekt sind? • Ansatz bei interaktiven Programmen á la GdI 1: – Schleife um Lesen der Eingabe – Schleife wird verlassen, wenn die Eingabe korrekt ist $isCorrect = false while (!$isCorrect) { Lesen der Eingabe Prüfen der Eingabe Setzen von $isCorrect = true bei vollständiger Eingabe } – Funktioniert bei Web-Anwendungen leider nicht! – Grund: Mit jedem Browser-Aufruf wird das Skript neu ausgewertet 2 Der Lebenszyklus eines Formulars/Skripts Lösung • Skript hat sich selbst als action=… • Bei Aufruf: Auswerten der Parameter • Ohne Parameter = Aufruf kam zum ersten Mal • Mit Parameter – Überprüfen der Parameter auf Gültigkeit – Markieren der ungültigen Elemente Der Lebenszyklus eines Formulars/Skripts Beispiel <html> <head><title>Test</title></head> <body> <form action="form.php"> <?php if ($_REQUEST["hallo"] == '') echo '<p style="color: red">'; else echo '<p>'; echo 'Hallo: <input type="text" name="hallo" value="'; echo $_REQUEST["hallo"]; echo '" /></p>'; ?> </form> </body> </html> 3 Der Lebenszyklus eines Formulars/Skripts http://.../form.php Browser Sendet Anfrage form.php ohne Parameter Ergebnis von form.php ohne Parameter Webserver Eingabe Browser Sendet Anfrage form.php Parameter: Ausgefüllter Wert Webserver Ergebnis von form.php mit Parameter ergänzt Browser Sendet Anfrage form.php Parameter: … Versteckte Elemente • Wiederholung aus Foliensatz 3: Versteckte Elemente – – – – – Werden nicht angezeigt Können nicht verändert werden Werden aber an Server übertragen Î User-ID in verstecktem Element speichern, bei Übermittlung des Formulars passenden Benutzer suchen Definition <input type="hidden" name="id“ value=“Wert" /> • Sehr praktisch für die Überprüfung – – Wird das Formular zum ersten mal angezeigt? Ù Keine Fehlermarkierung Verstecktes Element nicht vorhanden: erste Anzeige if ($_REQUEST["id"] != "Wert") ... 4 Modularisierung • Durch den include-Befehl können Seiten in Module aufgeteilt werden include($dateiname); – Wertet das als Dateiname gegebene PHP-Skript aus – Zeigt das Ergebnis des Skripts an der Stelle des includeBefehls an • Verwendung: – Einzelne Vorlage-Dateien für verschiedene Bereiche der Seite – Datei mit Hilfsfunktionen, die oft benötigt werden Umleitung auf andere URLs • Umleitung auf neue URL häufig sinnvoll – Umzug in anderes Verzeichnis/auf andere Server – „merkbare“ URL wird in „computerlesbare“ URL umgewandelt – Formular korrekt eingegeben Æ neue Anzeige, obwohl action=… das Formular als URL definiert http://.../form.php Browser http://.../done.php vollständige Eingabe Browser Neue/falsche Eingabe 5 Umleitung auf andere URLs • PHP-Funktion für Umleitung function goto($location) { header('location: http://'.$_SERVER['HTTP_HOST']. dirname($_SERVER['PHP_SELF']).'/'.$location); } – Kandidat für Datei mit Hilfsfunktionen • Umleitung muss vor der Ausgabe von Daten passieren! – noch vor XHTML-Header – Verwendung <?php include("util.php"); if (eingabeKorrekt()) { Speichern der Werte in die Datenbank goto("done.php"); } ?> <html> Ausblick: Template Engines • Validierung von Eingabedaten häufigste Anwendung von Skripts • Durch Web-Lebenszyklus etwas unpraktisch • Vorgestellte Techniken reichen für Praktikum aus • Template Engines – Fertige Lösungen für automatische Erzeugung von dynamischen Seiten – – – – Trennen Skript und Layout – einfacher für Nichtprogrammierer (?) z.B.: Smarty - http://smarty.php.net/ Beispiele auf Webseite Einsatz im Praktikum erlaubt, aber nicht verpflichtend 6 Aus Datenbank erstellter Content • „Never do what SQL can do for you“ • Verwenden von WHERE- und HAVING-Klauseln, anstelle Daten in PHP zu prüfen • Sortierung mittels ORDER gewährleisten • Verwenden von LIMIT bei Anzeige nicht-vollständiger Anzeige Ergebnisse 1 - 10 von ungefähr 241,000,000 Dynamisches Generieren von SQL-Statements • SQL-Statements sind normale Strings Æ können nach Belieben zur Laufzeit erstellt werden – Aus Foliensatz 5: Vorsicht vor „Böswilligen Abfragen“ bei SQL-Abfragefeldern – Entschärfen der Eingabe mit addslashes – sorgt dafür, dass aus WHERE nicht zwei Abfragen werden • Bei Syntaxfehlern in dynamisch generierten Statements Fehlermeldung von PHP – Unterdrückung mittels @ vor mysql_query – Zum Entwickeln Anzeige der Fehlermeldung sinnvoll 7 Dynamisches Generieren von SQL-Statements • Beispiel: Einfache Suche in einem Feld ... <form action="search.php"> Name: <input name="query" type="text" /> </form> <?php if ($_REQUEST['query'] != '') { $result = @mysql_query("SELECT * FROM users WHERE " . name = '" . addslashes($_REQUEST['query'] . "'"); while ($person = @mysql_fetch_array($result)) { // Ausgabe } } ?> ... Verwenden von XHTML-Features für automatische SQL-Erstellung • Gegeben: Datenbank mit vordefinierten Feldern • Gesucht: Deutsches Formular, soll Sortierung nach Belieben erlauben FirstName LastName Company <form action="sort.php"> Sortierung nach: <select name="order" size="1"> <option value="FirstName">Vorname</option> <option value="LastName">Nachname</option> <option value="Company">Firmenname</option> </select> </form> <?php $order = _REQUEST['order']; if ($order == '') $order = 'FirstName'; $result = @mysql_query("SELECT * FROM users ORDER BY $order"); ?> 8 Automatisches Erstellen komplexer SQL-Anfragen • Suche mit mehreren optionalen Elementen • SQL-Anfrage muss zu suchende Felder in WHERE mit AND verbinden – Syntax-Einschränkung: AND nur zwischen Feldern erlaubt, nicht am Anfang oder Ende Automatisches Erstellen komplexer SQL-Anfragen Mehrere Möglichkeiten für korrekte Syntax • Testen, ob noch Nachfolger vorhanden ist Æ wenn ja, dann AND hinzufügen • Einfacher mit Trick: – AND immer hinzufügen – Am Ende immer 1 hinzufügen – Ergebnis: SELECT … WHERE foo = 'x' AND bar = 'y' AND 1 9 Automatisches Erstellen komplexer SQL-Anfragen function makeQuery() { $query = 'SELECT * FROM publications WHERE '; $fields = array('author', 'project', 'year'); foreach ($fields as $element) { if ($_REQUEST[$element] != '') $query .= "$element = '" . addslashes($_REQUEST[$element]) . "' AND "; } if ($_REQUEST['search']) { $query .= "(keyword LIKE '%" . addslashes($_REQUEST['search']) . "%' OR abtract LIKE '%" . addslashes($_REQUEST['search']) . "%') AND "; } $query .= "1"; return $query; } Automatisches Erstellen komplexer SQL-Anfragen • Beispiel Guido Rößling algorithmen • SQL-String 'SELECT * FROM publications WHERE author='Guido Rößling' AND (keyword LIKE '%algorithmen%' OR abstract LIKE '%algorithmen%') AND 1 10 Projekt • Erstellen einer Mediendatenbank • In Ausbaustufen unterteilt – Ausbaustufen bauen aufeinander auf – Sind in sich abgeschlossen – Erzielte Ausbaustufe bestimmt bestenfalls erreichbare Note • Abnahme – Kurze Dokumentation des Projekts – Testat der Lehrveranstaltungsleiter in der letzten Vorlesungswoche 11