Christoph Reeg Co-Autor: Jens Hatlak 19.

Juni 2005

Diese Anleitung, die sich gleichermaßen an Anf¨nger wie allgemein Interessierte in Saa chen Datenbanken, SQL und PHP richtet, versucht schrittweise und spielerisch in die Geheimnisse der dynamischen Informationsverarbeitung im WWW einzuf¨hren. Von der u Datenbank-Theorie und -Praxis (am Beispiel MySQL) uber die webfreundliche Script¨ sprache PHP (inklusive Themen wie Datenbank-Anbindung und Objektorientierung) bis hin zu XML wird auf leicht verst¨ndliche Art beschrieben, welche M¨glichkeiten moderne a o Technologien bieten, Webseiten dynamisch zu gestalten. Nicht fehlen d¨rfen dabei nat¨ru u lich die zahlreichen Beispiele und und Hinweise; so gibt es u. a. auch ein Kapitel, das sich mit der Behandlung und Vermeidung von Fehlern besch¨ftigt. a Die aktuelle Version sowie verschiedene Formate zum Herunterladen befinden sich unter http://reeg.net/ .

DSP - Datenbank SQL PHP Copyright (c) 2000 by Christoph Reeg (dsp@reeg.net). Dieses Material darf nur gem¨ß den Regeln und Bedingungen, wie sie von der Open Pua blication Licence, Version v1.0, festgelegt werden, verteilt werden (die letzte Version ist o gegenw¨rtig verf¨gbar unter http://www.opencontent.org/openpub/). Diese Ver¨ffentlia u chung macht von keiner der im Abschnitt LIZENZ-OPTIONEN genannten Optionen Gebrauch. Die genaue Lizenz findet sich im Anhang C.

Inhaltsverzeichnis

1 Vorwort 1.1 Aktuelle Version/Download . . . . . . 1.2 Was ist das hier oder was ist es nicht? 1.3 Weitere Informationsquellen oder Hilfe 1.4 Unterteilung . . . . . . . . . . . . . . . 1.5 Typographische Konventionen . . . . . 1.6 Autoren . . . . . . . . . . . . . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

1 1 1 2 2 4 5

I

Theoretische Grundlagen
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7
8 8 8 9 9 10 10 11 11 11 12 12 13 13 14 14 14 14 15 15 15 15 16 16 18

2 Ben¨tigte Software o 2.1 Apache: Der Webserver . 2.2 PHP - ist das gef¨hrlich? a 2.3 MySQL . . . . . . . . . . 2.4 LAMP / WAMP . . . . .

3 Datenbanksystem 3.1 Komponenten eines Datenbanksystems 3.2 Ebenen eines Datenbanksystems . . . 3.2.1 Betriebssystem/Hardware . . . 3.2.2 Interne Ebene . . . . . . . . . . 3.2.3 Konzeptionelle Ebene . . . . . 3.2.3.1 Tabellenstruktur . . . 3.2.3.2 Schl¨ssel . . . . . . . u 3.2.4 Externe Ebene . . . . . . . . . 4 Datenbanken entwickeln 4.1 Vorgehensweise . . . . . . 4.2 Grunds¨tze . . . . . . . . a 4.2.1 Keine Redundanz . 4.2.2 Eindeutigkeit . . . 4.2.3 Keine Prozeßdaten 4.3 Datenmodelle entwickeln . 4.3.1 Tabellen erstellen . 4.4 Die f¨nf Normalformen . . u 4.4.1 Die 1. Normalform 4.4.2 Die 2. Normalform

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

Christoph Reeg

Seite i

Inhaltsverzeichnis

Inhaltsverzeichnis

4.5 4.6 4.7 4.8

4.4.3 Die 3. Normalform . . . . . . . 4.4.4 Die 4. Normalform . . . . . . . 4.4.5 Die 5. Normalform . . . . . . . 4.4.6 Denormalisierung der Tabellen Streifendiagramm . . . . . . . . . . . . Das ER-Modell . . . . . . . . . . . . . Relationen erstellen . . . . . . . . . . . Datentypen . . . . . . . . . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

18 20 21 21 21 21 24 25

II

Praktischer Teil SQL

26

5 SQL benutzen 27 5.1 MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 5.1.1 Dateien abarbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 5.1.2 Kommentare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 6 SQL-Befehle 6.1 CREATE DATABASE . . . . . . . 6.2 CREATE TABLE . . . . . . . . . 6.3 SHOW . . . . . . . . . . . . . . . . 6.4 DROP TABLE . . . . . . . . . . . 6.5 INSERT INTO . . . . . . . . . . . 6.6 SELECT . . . . . . . . . . . . . . 6.6.1 ORDER BY . . . . . . . . 6.6.2 GROUP BY . . . . . . . . 6.6.3 LIMIT . . . . . . . . . . . . 6.6.4 select expression . . . . . . 6.6.5 Alias . . . . . . . . . . . . . 6.6.5.1 Tabellen-Alias . . 6.6.5.2 Spalten-Alias . . . 6.6.6 where definition . . . . . . 6.6.6.1 LIKE . . . . . . . 6.6.6.2 BETWEEN . . . 6.6.6.3 IN . . . . . . . . . 6.7 Funktionen . . . . . . . . . . . . . 6.7.1 Mathematische Funktionen 6.7.2 Logische Operatoren . . . . 6.7.3 Sonstige Funktionen . . . . 6.7.4 Datums-Funktionen . . . . 6.7.5 Gruppenfunktionen . . . . . 6.8 Joins . . . . . . . . . . . . . . . . . 6.8.1 Equi-Join . . . . . . . . . . 6.8.2 Self-Join . . . . . . . . . . . 6.8.3 Outer-Join . . . . . . . . . 6.9 DELETE FROM . . . . . . . . . . 30 30 31 33 34 34 35 37 39 39 40 41 41 41 42 47 47 48 50 50 50 51 51 52 54 54 55 56 58

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

Christoph Reeg

Seite ii

Inhaltsverzeichnis

Inhaltsverzeichnis

6.10 UPDATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 6.11 ALTER TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 7 Tips 7.1 7.2 7.3 7.4 & Tricks zuf¨llige Daten ausw¨hlen . . . . . . . . . . a a Nutzer in MySQL . . . . . . . . . . . . . . PHPMyAdmin . . . . . . . . . . . . . . . . B¨ume in SQL . . . . . . . . . . . . . . . . a 7.4.1 Was ist ein Baum? . . . . . . . . . . 7.4.2 Beispieldaten . . . . . . . . . . . . . 7.4.3 Baumdarstellung mit Vater-Zeiger . 7.4.4 Nested Set Modell . . . . . . . . . . 7.4.4.1 L¨schen . . . . . . . . . . . o 7.4.4.2 Einf¨gen . . . . . . . . . . u 7.4.5 Performance vom Nested Set Modell ¨ 7.4.6 Ubungen . . . . . . . . . . . . . . . 7.4.6.1 Vater-Zeiger . . . . . . . . 7.4.6.2 Nested Set . . . . . . . . . IF-Ausdr¨cke in SQL . . . . . . . . . . . . . u 7.5.1 Beispiele . . . . . . . . . . . . . . . . 7.5.1.1 Firma Ausbeuter & Co KG 65 65 66 66 67 67 68 69 69 74 76 76 76 76 77 77 79 79

7.5

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

III Einf¨hrung PHP u
8 PHP Grundlagen 8.1 Einleitung . . . . . . . . . . . . . . . . . . . 8.2 Grundbefehle . . . . . . . . . . . . . . . . . 8.2.1 Der echo-Befehl . . . . . . . . . . . . 8.2.2 Der print-Befehl . . . . . . . . . . . 8.2.3 Zuweisungen . . . . . . . . . . . . . 8.2.4 Operatoren . . . . . . . . . . . . . . 8.2.4.1 Arithmetische Operatoren . 8.2.4.2 String-Operatoren . . . . . 8.2.4.3 Bit-Operatoren . . . . . . . 8.2.4.4 Logische Operatoren . . . . 8.2.4.5 Kurzschlußlogik . . . . . . 8.2.5 Kommentare . . . . . . . . . . . . . 8.2.6 Variablen . . . . . . . . . . . . . . . 8.2.6.1 Integer . . . . . . . . . . . 8.2.6.2 Double/Float . . . . . . . . 8.2.6.3 Boolean . . . . . . . . . . . 8.2.6.4 String . . . . . . . . . . . . 8.2.6.5 Beispiel . . . . . . . . . . . 8.2.6.6 Array . . . . . . . . . . . . 8.2.7 Konstanten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

81
82 82 83 83 84 84 85 85 85 85 86 86 87 87 87 88 88 88 89 89 91

Christoph Reeg

Seite iii

. . . . . . . . . . . . . . . . 8. 8. . Vergleichsoperatoren . . . . . 132 . . . . 10 PHP & MySQL 10. . . . . . . . . . . 8. . . . . . . . . . . . . . . . . 9. . . . . . . . . . . . . 8. . . .19 foreach .12 ELSEIF . . . . . . . . . . . . . . . . .2 mysql connect 10. . . . . . . . . . . . . . . . . . . . . . . . . . . 92 93 93 93 94 94 95 95 95 96 96 98 100 101 102 102 103 105 105 106 106 106 109 110 110 111 112 114 114 117 118 118 119 . . . . . . 8. . . .1 Formulare . . . . . . . . . . . . . 8. 8. . . . . . . . . .13 Alternative Syntax f¨r IF: IF(): . .3 number format . . . . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . 8. . . . . . . . . . . . . . . . . . . . . . . . . . 8.9. . . . . . . . . . . . . . . . . . .10 IF .8 8. . . . . . . . .1 allgemein . u 8. . 133 . . . . . . .1 Die T¨rme von Hanoi . . . . . . . . . . . .1. . . . . . . . . . WHILE . . . . . . . . . . . . . . . . . . . . . . . . . . .8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8. . . . . . . . .10 Rekursion . . . . . . . . . . . . .4 Normalform von Formularen . . . 130 132 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8. . . .1. . . . . . . . . . . . .18 SWITCH . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . . 9. . . . . . . . .2 sprintf . . . . . u 8. . . . . . . . . . . .2. . . 8. . . . . . . . . . 10. . . . .2. . . . . . . . .8. . . . . . . . . . . . 8. . . . 9 PHP & HTML 9. . . . . . . . . . . . . . . . . . . . . . . . .11 ELSE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.8. . . . . . . . .4 require . . . . . . . . .16 DO . . . . . . . . . . .2.9 Guter Stil . . . . . . . . . . . . . . . . . . . . . . . 124 . . . . . . . . . 8.1 Syntax . . . . . . . . .1. . . . . . . . . . . . . .1 Wieso ist das Null?! . . . . . . . . .3 Vorteile der Rekursion . . . .3 mysql close . . . . . . . . . . . . . . . . . . . . . . . 8. . . . . . . . . . . . . . . . . . .7. . . . . . . . . . . . . 8. . . . . . . . . . . . . . . . . . . . . . .2. .14 Alternative Syntax f¨r IF: (?:) . . . . . .5 Beispiele zu include und require . . . .4 Rekursion und Iteration im Vergleich . . . .2. . . 123 . . . . . . . . . . . . . . . .2. . . . .9. . . require once . . . . . . . . . . .Inhaltsverzeichnis Inhaltsverzeichnis Variable Variablen . . . . . 8. . . . . . . . .2. . . . . . . u 8. . . . . . . . . . . . . . . . . 129 . 125 . . . . . . . . . . . . . . . . . . . . . . .9 . . . . . . .20 continue . . 8. . . . .2. . 8. . . . . . . . . . . . .4. . . . 8. . . . . . . . . . . .1 printf . . . . . . . . . . . . . . . . . . . . . . . .10. .10. . . . . . . . .2 Werte ubergeben . .3 include . . . . . . . . . . . . . 132 . . . . . . . . . . . . . . . . 8.6 include once. . .2. . . . . . 123 . .2. . . . . . . . . . . . .5 Ein Beispiel aus der Praxis: MIME parsen . . . . . . . . . . . 10. . .1 Typensichere Vergleiche . . . . ¨ 9. . . . .1 Variablenparameter . . . . . . . . . 8. . . . . . . . . . . . . . 8. . . . . . . . . . 132 . . . 9. . . . . . . . . . .1 Warn-/Fehlermeldungen anzeigen . . . . . .8. . .15 WHILE . . . . . . 8. . .17 FOR . . . . . .1. . . .10. . . . . . . . . . . . . . . . . . . . . . . .1 Argumente vertauschen/numerieren 8. . . . . . . . . . . . . . . . . . . .2. . . . . . Christoph Reeg Seite iv . . . . . . . . . . . . . . . . . 8. . . . . . . . . . . . . .3 Dynamische Formulare . . . . . . . . . . . . . . 8. . . . . . . . . . . . . . . . . . . . . . . . ENDIF. . . . . . . . .2 Speicherverbrauch und Stack . . . . . . . . . . . 8. . . . . . . . . . . . . .8 Formatierte Textausgabe . . . . . . . . .2. . . . . . . .10. . . . . .10. . . . . . . .7 Funktionen . . . .

. . . . . . . . . . . . . . .2 Ergebnis-Tabelle ausgeben II . . 11. . . 154 . . . . . . . . . . . . . 12. . . . . . . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . . . . . . . . . . 141 . . . . . . . . . . . .5.5. . .1 einfache Suchmuster . . . . . . . . . . . . . .1. . . .3 Abfrage mit sprintf() . . . . 142 . . 12. . . . . . . . . . 155 . . . . . . . . . 10. . .9 mysql errno . . 10. . . . 12. . . . . . . . . . . . .3 Ubung . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 . . . . . . . . .3. .1 Abfragen mit IN . .1 Ergebnis-Tabelle ausgeben I . 10. .5.2 Anderes Beispiel: Akronyme 12 Regul¨re Ausdr¨cke a u 12. . . . . . . . . . . . . . . . . . . . . . . . . 141 . . . . . . .6 Cache . . . . 153 . . . . . . . 12. . . . . . . . . . . . . . . . .2 Quantifizierer . . . . . . . . . . . . . . . . 153 . . . . . . . . . . . . . . . . . . . . .1 Header . . . . . . . . . . 155 . .1 Beispiel: PHP-Manual . . . . . . . . . . . . . 10. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Tips und Tricks . . . . . . . . 10. . . . . 12. . 11. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 Ubungen . . . . .1. . . . . . . . . . . . . . 150 151 . . . . . . . . . . . . .1 einfache Suchmuster 12. . .11 mysql num rows . . . . . . . . . . 10. . . . . . 12. . . . . . . . . .5 mysql query . . . . .1. . . . . . . . . . 12. . . . . 11.2. . .5. .3 . . . . . . . . .2 . . . . . . . . . . .2. . . . . . . . . . . . . . . 11. . . . . . . . . . . . . . .1.1. 155 . . 155 . . . . . . . . 11. .2. . . . . . . . . . . . . . . . . . . ¨ 10. 12. . .3. . . . . . . . . . . . . . 155 . . . . . . . . . . . . 12. .5. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2 Quantifizierer . . 149 . 155 . . . . . . . . . . . . 146 . . . . . . . . . . . . . 11. . 155 . . . . . . . . . . . . . 12. . . . . . . . .4 Einf¨gen mit automatischer ID u 11 PHP & HTTP 11. . . 10. . . . . . . . . . . . 10. . . . . . .2 Nicht gefunden . 11. . .4 mysql select db . . . . . . . . .2 . . . . . . . . . . . . . . . . . . 141 .5 . . . . . . . . . . . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . .1 . .1. . . . . . . . . . . . . . . . . . . . . 147 . . . . . . . . . . . . . . . . . .1.5. . . . . . . 155 . . . . . . .5. . . . . . . . . . . . . .5. . . . . . . . . . . .1. . . . . . . 10. . . . . . . . . . .3. . . . . . . . . . ¨ 12.3. . . . . . 154 . 12.8 mysql error . . . . . . . . . . .5 . . . . . . . . . . . . .7 mysql fetch row . .3 Gruppierungen . . . . . . . . . . . . . . . . . . . . . 151 . . . . . . . . . . . . . . . . . . . . . . 154 . .10 mysql insert id . 154 . . . . . . . .2. . . . . . 11. . .1. . . . . .4 Download . . . . . . . . . . . . . . . .5. .1 . . . . . . . .4 . . . . .1.1. . . . . . . . . . . . . . . . . . . . . .2. . . . . . 12.2 URLs parsen . . . . . . . . . . . . . . . . . 155 . . . . . . . . . . .3 Authentifizierung . . . .1. . . . . . .1. . . . . . . . . . . . . . . . .Inhaltsverzeichnis Inhaltsverzeichnis 10. . . . . . . . . . . . .1. . . . . . . . . .4 .1. . . . . 149 . .1 Weiterleiten . . .5. . . . . . . 10. . . . . . . . . . . . . . . . . . .1. . . .2. . . . . . . . . . . . 12. . . . . . . . . .5. . . . . . . . . . . . . . . . . . . . . . . . . . . .6 mysql fetch array . . . . . . . 133 133 134 134 135 135 135 135 135 136 136 136 139 139 140 . . . . . . . . . 154 . . . . . . . . . . Christoph Reeg Seite v . . . . . . . . . . . . . . . . . . . . . . . . . . .5. . . . . . . .1. . . . . . . . . . . . . . 142 .2. . . . . . . . .1. . . . . . . . . . . . . . . . . . . . . . 12. . . . . . . . . . . 11. . . . . .4 Optionen . 10. . . 10. . .5 Content-Type .3 . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .1. 191 192 192 193 194 194 195 195 195 196 196 18 Bedeutung von Objektorientierung 18. . . 13. . . . . . . . . . . . . . . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 Schlußbemerkung . . . . . . . . . . . .3 Gruppierungen . . 18. . . . . .1 Ein komisches IF . . . . private oder doch protected? Christoph Reeg Seite vi . . . . . . . . . . . . . . . . . . . . . . . . . . . u 16. . . . . . . . . . . u 16. . . . . . . . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18. . . . . . . . . . . . . . . . . . . . . . 18. 13. . . . . . . . . . . . . .7 Ubung . . 13. . . . . . . . . . . . . . . . . . . . . . . . . . .3 Alle Spr¨che ausgeben . 18. . . 187 V Objektorientierung theorethisch . . . . . . . . . .1 phpDocumentor . . . . . . . . . . . . . . . . . .2 Jedem sein Auto . . .5. . . . . . . . . . . . . . . . . . . . . . . . . . . .5 Konstruktor . . . . . . 18. . . . . . .1 Ein kleines Beispiel: Funkwecker . . . . . . . 18. . . . . . .‘ wo eins ist? 157 159 159 160 160 . . . . . . . . . . . . . . . . . . . .2 Fehler in einer leeren Zeile? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 Destruktor . . . . . . . . . . . . . . . . .4 Spruch l¨schen . . 18. . . . . . . . . . . .3 Wieso fehlt ein ‘. . . . . . . . . . . . .8 Zugriffsrechte: public. . . . . . . . . . . . . . . . . . .4. . . . . . . . . . . . . . . . . . . .5 Spruch andern . . . . . . . . .1 Ubungen . .7 Klasse oder Objekt . . . . . . .1 . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 13 Fehlersuche ¨ 13. . . . . . . . 164 165 170 171 173 176 177 178 182 183 . . . . . . . . . . . . . . . . . . . . . . . . . o 16. . . . . . . . . . 162 IV Beispiele 15 Einfaches G¨stebuch a 16 Spruch des Abrufs 16. . . . . . .1 Image-Beispiel . . . . . .1 Neuen Spruch einf¨gen . . . . . . 184 17. . . . . . . . . . . . . . 14 PHPDOC 161 14. . . . . ¨ 16. . . . . . .5. . .1 Erste Realisierung . . . . . . . . . . . . .2 Zuf¨lligen Spruch ausgeben a 16. . . . . . . . . . . . .4 Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 12. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Inhaltsverzeichnis Inhaltsverzeichnis 12. . . . . . . . . . . . . .2 Zweite Realisierung . . . . . . . . . . . . . . . . . . . . . . . . . . .1. . . . . . . . . . . . . . . . .2. . . .6 . . . . . . . . . . ¨ 16. 17 Kleines Bannerscript 184 17. . .5. . . . . . . . 155 12. .3 Von Autos zu Objekten . . 18. . . . . . . . . . . . . . . . . . . . . . .

. . 216 217 217 218 218 218 220 220 220 Christoph Reeg Seite vii . . . . . . 19. . .3 Beispiel Warenkorb . . . . . . . . . . . . . . . . . . . . .1 Instanz . . . 19. . . . . . . . . . . . . . . . . . . . . . .1 OOP . . . . . .2. . . .3. . . . . 20. . . . . . . . . . . 21. .7 Ubung . . . .6 Konstruktor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Attribute in PHP . . . . . . . .1. . . . . . . . . . . . . . . .2. .5 Klassen dokumentieren . . . . . . . . . . . . . .2 Vererbung in PHP . . . . .3 Methoden-Aufrufe . . .3 foreach mit Objektreferenzen . . .2 Datei 2 . . . . . . . . .1. . . . . . . . . . . . . . .6 Konzeptionelle Beispiele . . . . . . . . . . . . . . . . . . . . . . . . . . .4 Das fertige Beispiel . . . . . . . . . . . . . . . . . . . . . . 19.2. . . . . . . . . .4 Methode . . . . . . . . . .1. 20. . .7. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .index2. . . . . . . . . . . . . . . . .3. . . . . . . . . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .index. . . . . . . . . . 20. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .php . . . . . . . . 20. . . . . . . . . .2 parent . . . . . . . . . . . . . . . . . . . . . . . . 20. . . 20. . . . . . .2 Praxis .1 static . . . . . . . . . . . 199 200 200 200 201 201 202 202 203 204 204 204 205 206 206 206 207 209 211 211 211 214 VII PHP Erweitert 21 Sessions 21. . . . . . . . . . 20. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7. . . . . . . . . . . . . . . . . . . . .1 Referenzierung . . . . . . . . 21. . . . . . . .1 Kopier. . . . . . . .2 Objekt . . . . . . . . . 20. . . . . . . .1. . . . . . . . . . . . .2. . . . . . . . .1 Datei 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Waren . . . . . . . . .php 21. . . . . . . . . . . .1 Konstruktoren . . . . . . 20. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Objekte und Referenzierung in PHP . . . . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20. . . . . 20. . . . . .3 Logout . . . . . . . . . . 20. . . . . . .1. . . . . . . .vs. . . . . . . . . . . .2. ¨ 20. . . . . . . . . . 20. . . . . . . . . . . . . . . . . . . . . . .4 Methoden in PHP . 197 197 197 197 197 197 197 198 198 VI Objektorientierung praktisch 20 Objektorientierung in PHP 20. . . 21. . . . . . . . Referenzsemantik . . . . . . . . . . 20. . . . . . . . . . . .2. . . . . . . . . . .2 Ausweg aus dem Referenzdilemma 20. . . . . . . . . . . . . . . . . . . . .7 Destruktor . 21.5 Attribut . . . . . . . . . . . 19. . . . . . . . . . . . . .Inhaltsverzeichnis Inhaltsverzeichnis 19 Bezeichnungen 19. . . 19.php 21. . . . . .logout. . . . . 20. . . . . .2. . . . . . . . . . . . .1 Was sind Sessions? . 19. . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Klassen in PHP . . . . . . . . .1 Basisklasse 19. . .3. . . . . . . . . . . .2 Referenzsemantik . . . . . . . . . . 20. . . . . . . . . . . . .5 Ausblick: PHP5 . . 20. .1. . . . . . . . . .3 Klasse . .

. . . .6. . . . . . . . . . B. . . . . . . . . . .1 Block-API 23. . . . . . . . . . . . . . . . . . . . . . . . . . . .6. . . . . . . . . . . . . B. . . . .1. . . . . . . . . . . . .2 Parsen von XML-Daten . .6.Inhaltsverzeichnis Inhaltsverzeichnis 21. .1. . . . . . . . . . . .1. . . . . 234 . . . . . .5 L¨sung f¨r Einf¨gen mit automatischer ID o u u B. . . . . . . . . . . . . . . . . . . 240 u B L¨sungen o B. . . B. . . . . . . . . .2 L¨sung f¨r Ergebnis-Tabelle ausgeben I“ o u ” B. . . . . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o u ” B. . . . .2 21. . . . o B. . .1 Vater-Zeiger . . . . . .4 . . . . . . . . . . . . . . . . . 23. . . . . . . . . . . .6.4 Nachteile . . . . . . . . . .2 L¨sung zu Quantifizierer“ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 A. . . . . . . . . . . . . . . .1 L¨sung zu Baumdarstellungen . . . . . . . .1 Was ist XML? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 21.6. . . . . . . . . . . . . . . . . . . . . . . . . . . . B. . . . . . . . . . . . .6. . . .1. . . . B. . . . . . . . Christoph Reeg Seite viii . . . . . . B. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 ¨ Ubersicht . . . . . .3. . . 22. . . . . . . . . . . . . . .1 Die XML-Datei (tutorial.xml) 22. . . . . . 234 . . . . . . . . . . . . . . . . . . . . . B. . . . . . . . . . . . 222 Entfernen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.6. . . . . . . . . . . . . . . . . . . . . B. . . . . . . .1 . . . . . 23. . . . . .3 . . . . 242 242 242 244 246 248 249 249 250 250 250 250 250 251 251 251 251 251 251 251 . . . . . . . . . . . .2 . . . . . . . . . . . . . . . . . . . . . . . . .1 . . . . . .2 . . . . . . . . .2. . . . . . . .2 Nested Set . . . . . . . . 223 224 224 224 225 225 225 228 229 22 XML-Dokumente parsen 22. . . 234 . . . . . . . .1 Zu erstellende Tabellen . . . . . .3. . .2. . . . . . . . . . . . .6. . . .4 . . . . . . . . . . . .3 L¨sung f¨r Ergebnis-Tabelle ausgeben II“ o u ” B.2. . . . .3 Beispiel 1 . . . . . .2 Daten einf¨gen . . . . . . . . . . o ” B. . . . . . B. . . . . . . . . . .2 Das PHP-Skript . . . . . . . . . . . . . . . . .6. . .5 . . . . . .5 Beispiel 2 . . . 23 Templates 23. . . . . . . . . .3. .1 Beispiel . . . . . . . . . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 L¨sungen zu Regul¨ren Ausdr¨cken . . . . . . . . . . . . . . o ” B. . . . . . . . . . 22. . . . . . . . . . . . . . . . . .2. . . . . . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 VIII Anhang 238 A Unser Beispiel in SQL 239 A. . . . . 22. . . . . . . . . 221 Bestellen . . . . . . . .1 L¨sung zu einfache Suchmuster“ . . . . . . . .1. . .3 . . . . . . . . . . . . . . . . .3 Smarty .2 PEAR::IT[X] . . .6. . . . . . . . . . . . . .4 L¨sung f¨r Abfrage mit sprintf()“ . . . . . . . . . 235 . . . . . o a u B. . . . . . 22. . . . . . . . . . .6. . . . . . . . . . . . . . . . . . . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . 22. . . . . . . .1. . . . . . . . . .

. . . . . . .8 B. . . . .2 13. . . . . . . .2. . . . . . . . . .2 Deutsche Version .3 22. . o u ” B. . . . . . . . . . . . . . . . . . . o L¨sung zum Image-Beispiel .7 B. . . . . . . . . . . . . . .11. . . . . . . . . . . . .2005 E. . . . . . . . .04. . . .5 05. .07. .05. . . . . .2 L¨sung f¨r Fehler in einer leeren Zeile?“ o u ” B. . . . . . . . . . . . . . . . . . . . . . . . .2001 E. . . . .10 B. . . . . 263 Literaturverzeichnis 266 C. . . .1 . . . . . . . . . . . . . . .10. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .06. . . . . . . . . .6 . . . . . . . . . .9 27. . . . . . . . . . . . . . . . . . . . . . . . . .09. . . . . . . L¨sungen zur Fehlersuche . . . . . . . . . . . . . . . . . . . . . . .2000 Index 267 268 270 271 271 272 272 272 273 273 273 273 273 274 . 261 C. . . . . . . . .7. . . . .3 zitierte Literatur . . . . . . . . .4 Weitere Informationsquellen . . . . . . . . . . . . . . . . .2002 E. . . . . . .8 30. .7 19. .1 Englische Version . . . . . . . . . . . Christoph Reeg Seite ix . . . . . . . . . .9 B. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o L¨sung zur Referenzsemantik .7. . . . . . . 266 Abbildungsverzeichnis Tabellenverzeichnis D Danksagungen E Versionen E. . . .2001 E. .6. . . . . . . . . . . . . . . . . .4 27. . . . . . . . . . . . . . . . . . o B. . .1 19. . .2000 E. . . . . . .06. . . . . . . . . . . . . . . .6. . . .6. . . . . . . . . . . . . . . .2000 E. . . . . . . . . . . .2000 E. . . . . . . . . . . . . . . . . . . . . . . . . . . .‘ wo eins ist?“ o ” L¨sung zu Spruch des Abrufs . . . . . . . . . . . . . . . . . . . . . . . .2000 E. . . . . . . . . . . . . . . . . . . . . . . . . . . o . . . . . . . . . . B. . . . .1 L¨sung f¨r ein komisches IF“ . . . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Inhaltsverzeichnis Inhaltsverzeichnis B. .5 . . . . . . . . . . . . . . . . .6 27. . . . . . 266 C. . . . . . . . . B. . B. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3. . . . . . . .6. . . . . .12. . .3 Gruppierungen .3 L¨sung zu Wieso fehlt ein ‘. . . . . . . . . . . . . . . . . . . .7. . . . . . . . . . . . . . . . . . 251 251 252 252 252 252 253 254 254 255 259 C Open Publication License 261 C. . . . . .

wenn du auch eine E-Mail bekommen u willst. Anhand von einigen Beispielen wird dabei versucht. sollte dies nur als Einf¨hrung sehen und u sich Hilfe in Form eines Profis besorgen. die Theorie etwas aufzulockern. Wer meint. Wenn du Anregungen hast.net/ immer die ¨ aktuelle Version. w¨rden wir uns uber eine u ¨ E-Mail an dsp-autor@ml.junetz. 1 http://ml.1 Aktuelle Version/Download Diese Anleitung wird st¨ndig aktualisiert und verbessert (wenn ich es schaffe. was noch verbessert werden kann. kannst du dich auf der Mailingliste1 eintragen. Das Wissen sollte f¨r normale und auch etwas aufwendigere Webseiten ausreichen. Daf¨r wird entlang eines Beispiels ein Datenu modell entwickelt und seine Umsetzung beschrieben. Weiterhin befindet sich unter http://reeg. noch Nachholbedarf zu haben. 1. Etwaige Server-spezifische Besonderheiten m¨ssen dabei nat¨rlich u u außer acht gelassen werden.junetz.2 Was ist das hier oder was ist es nicht? Dieses Tutorial will die Grundlagen in Datenbankdesign. 1. den inneren a Schweinehund zu uberwinden). die dieselben Grundkomponenten nutzen.1 Vorwort The difference between theory and practice is that in theory there is no difference between theory and practice but in practice there is. die auf dem Server der Sites u u http://ffm. kann sich unter [7] noch ein Nachschlagewerk besorgen. Dieses Tutorial wurde urspr¨nglich f¨r Skripte geschrieben. Es gibt neben der Online-HTML Variante auch noch PostScript und PDF in verschiedenen Versionen zum herunterladen und ausdrucken.2 beschrieben.de sehr freuen.junetz. SQL und PHP vermitteln.junetz. wie in Abschnitt 2. Wer alleru dings Datenbanken mit Millionen von Eintr¨gen oder Webpr¨senzen mit mehreren hundert a a Seiten und tausenden von Abrufen pro Tag plant.de/list/listinfo/dsp-announce/ Christoph Reeg Seite 1 . Sie kann aber auch f¨r u alle anderen Server benutzt werden. Die Kenntnis der Sprache HTML wird vorausgesetzt und in dem vorliegenden Tutorial werden im Prinzip keine HTML-Befehle beschrieben. Dieses Tutorial erkl¨rt die Grundlagen einer Datenbank in Verbindung mit der Abfraa gesprache SQL und der Scriptsprache PHP.de/ und http://of. Neue Versionen werden per E-Mail angek¨ndigt.de/ Verwendung finden.

u o 2 3 Frequently Asked Questions Answer For Any Possible Question Christoph Reeg Seite 2 . kann es sich lohnen. die sp¨ter auch in die Dokumentation eingebaut werden. zu helfen. besonders wenn die Dokumentation nicht ganz a klar formuliert ist.php‘. u findest du das. Trotz ausf¨hrlicher Anleitungen kann es einem passieren. sollten zur Befehls¨bersicht immer die Original-Anleitungen zu Rau te gezogen werden. 1.und PHP-Teil werden die grundlegenden Befehle vorgestellt. u u 1. Sie eignet ¨ sich nur dann zum Erlernen von PHP. wie z. Eine weitere Informationsquelle sind die FAQs2 . Die Newsgroups zu PHP finden sich unter . Die Anleitung von MySQL [4] gibt es inzwischen nicht nur in englisch.lang.4 Unterteilung Dieses Dokument ist in verschiedene Teile unterteilt. Die ” deutsche Mailingliste wird vom PHP-Center [10] betrieben. dort mitzulesen. a Die Kommentare sind h¨ufig sehr wertvoll. die sich auf der PHP-Homepage [6] unter support“ finden.comp. schon irgendwo fertig oder zumindest Teile davon. Die PHP-FAQ [8] m¨ßte eigentlich AFAPQ3 heißen: Es gibt f¨r fast jede u u erdenkliche Frage eine Antwort. F¨r solche F¨lle gibt es Newsgroups und Mailinglisten u a im Internet. Kommentare zu den o einzelnen Seiten zu hinterlassen.3 Weitere Informationsquellen oder Hilfe Wie oben schon gesagt. Die Mailingliste zu MySQL findet sich auf der MySQL-Homepage [4] unter Documentation“. wenn man schon vorher programmieren konnte und nur die neue Syntax lernen muß. Nimm dir einfach mal einen Abend frei und surf los. Wenn du Gl¨ck hast. was du selbst programmieren wolltest. sondern auch in deutsch.1. Die Anleitung gibt es in verschiedenen Sprachen. daß man an der ein oder anu deren Stelle nicht weiterkommt. die deutsch” sprachige Newsgroup heißt . Neben der PHP-FAQ gibt es noch unz¨hlige weitere Informationsquellen zu PHP (und a h¨ufig auch MySQL) im Internet. auch wenn nicht alle komplett aus dem Englischen ubersetzt wurden. F¨r eine ausf¨hru u liche Befehls¨bersicht m¨ssen die Original-Anleitungen zu Rate gezogen werden.de. wo andere Leute in ihrer Freizeit versuchen.comp. Die FAQ von MySQL [9] ist noch im Aufbau und deshalb noch nicht so ausf¨hrlich. Auch wenn man keine aktuellen Probleme hat. B. sie enth¨lt jedoch schon einige n¨tzliche u a u Informationen. wobei die ersten drei auch einzeln f¨r sich gelesen werden k¨nnen. diese ist sehr ausf¨hrlich und eignet sich auch als Einf¨hrung f¨r u u u SQL. Vorwort Weitere Informationsquellen oder Hilfe Im SQL. Bei der (englischen) Online-Variante gibt es die M¨glichkeit.mysql‘.de. Bei PHP [6] sieht die Sache etwas anders aus. Gute Startpunkte daf¨r sind die PHP-Portale. Sie eignet sich aber auf jeden Fall als gutes Nachschlagewerk. a u [10] oder [11]. Zu PHP gibt es gleich mehrere Mailinglisten in Englisch.datenbanken.

IBM DB2. mehr dazu im ersten Teil Christoph Reeg Seite 3 . Die Einzelheiten werden sp¨ter im Tutorial a behandelt. Soweit nicht explizit angegeben. Wenn ein Befehl erst in PHP4 hinzu gekommen ist. Informix und Gupta. Adabas-D. was mit Begriffen wie a DB. besonders wichtig. Dieser Teil ist f¨r alle. sollte sich einfach die ¨ Original-Dokumentation zu Gem¨te f¨hren.-). das als Abfragesprache SQL4 benutzt. viel wichtiger ist. m¨ssen diesen Teil vollst¨ndig u a verstanden haben . Dieser Teil ist nicht existentiell. die von der Mehrheit der Relationalen DBS5 benutzt wird. dazu z¨hlen unter anderem: PostgreSQL. daß du weißt. 4 5 Structured Query Language Datenbanksysteme. Wenn wir dann wissen. um nachher Datenbanken zu entwickeln. die mit Datenbanken arbeiten wollen. mSQL. die u auch f¨r den Entwurf der Datenstrukturen verantwortlich sind. was eine DB ist. ¨ wo du nachschlagen kannst. unsere Kenntnisse am Computer zu testen. Wer mehr uber diese Sprache lernen will. Bis alle umgestellt haben. wie man aus einer Aufgabenstellung die passenden Datenstrukturen entwickelt. sowohl unter PHP3 als auch unter PHP4 verwendbar. wobei der Schwerpunkt hier nat¨rlich auf der u Datenbankabfrage liegt. Anschließend soll gekl¨rt werden. DBS oder DBMS gemeint ist und wo die Unterschiede liegen. was eine Datenbank ist. weil man u ¨ sich sonst viel Arger einhandeln kann.-). Vorwort Unterteilung Erster Teil Im ersten Abschnitt dieses Teils der Anleitung soll kurz gekl¨rt werden. wird es langsam Zeit. Mit ihr kann man sehr viel mehr machen als nur Datenbanken abzufragen. a Du mußt ubrigens nicht jeden Befehl auswendig kennen. o All diejenigen. Dritter Teil In diesem Teil wird die Scriptsprache PHP beschrieben. welche Software a verwendet wird und welche Rolle sie spielt. kann diesen Teil uberspringen. Und sei es nur. sind die Befehle.-)). SQL ist eine nach bestimmten Normen festgelegte Sprache. ¨ Zweiter Teil Nachdem wir uns dann im ersten Teil schon einige Zeit mit der Datenstruktur besch¨ftigt a haben. die in dieser Anleitung verwendet werden. allerdings unterst¨tzen nicht alle Hersteller den komu pletten Standard und jeder hat seine eigenen Erweiterungen. Wer lediglich mit schon vorhanden Datenstrukturen arbeiten muß. Soweit nicht anders angegeben. bzw. obwohl er eigentlich sehr interessant ist .andernfalls kommen sie sp¨ter mit Sicherheit stark ins Schleudern. Im Prinzip ist SQL standardisiert. Im Prinzip sollten alle PHP3-Scripte auch unter PHP4 laufen. sollten die in dieser Anleitung benutzten Befehle dem Standard entsprechen und auch mit anderen Datenbanken verwendet werden k¨nnen. um einmal die Begriffe geh¨rt zu o haben . kommen wir zu der Frage.1. Oracle. Als DBMS benutzen wir ‘MySQL‘. wird jedoch sicherlich noch einige Zeit lang PHP3 verbreitet sein. a MySQL. u u Seit einiger Zeit gibt es PHP in der Version 4. allerdings sollte man es sich schon einmal durchlesen. wird dies explizit erw¨hnt (sofern ich es nicht a vergessen habe .

sowie teilweise der SQL-Code syntaktisch hervorgehoben. werden einige Sachen hervorgehoben. Wie die jeweiligen Sprachelemente hervorgehoben werden. auf welche Weise was hervorgehoben wird. Teile davon fett besonders wichtige Dinge.1 zeigt.1: Typogr. . was wie oben nicht heißen soll. daß du im Zweifelsfall weißt. Wie kursiv in einfachen Anf¨hrungszeichen u in doppelten Anf¨hrungszeichen u nicht-proportionale Schriftart Was Internet-Adressen Bezeichnungen. sondern verstehe es einfach als Lesehilfe. sollte eigentlich relativ einfach zu erkennen sein. auf die man nicht immer auf Anhieb kommen w¨rde. da geht das dann noch schneller.junetz. Es gibt noch die Optionen -rf (really fast). Vierter Teil Hier werden ein paar Beispiele vorgestellt. 1. Um alle Mails zu lesen. dann schreib mir doch eine E-Mail an dsp-autor@ml. sie zu programmieren :-( ). Konventionen Christoph Reeg Seite 4 . Vorwort Typographische Konventionen Dieser Teil ist unbedingt notwendig. Namen Werte Beispiel Wenn du Anregungen hast. Wenn die Variable Tag den Wert 13“ und ” die Variable Monat den Wert Mai“ annimmt. sondern nur. muß man rm * eingeben (auf eigene Gefahr!). wo du nachschlagen mußt. In den Beispielen wird der PHP-Code. Hoffentlich helfen sie Dir. Befehle bzw.5 Typographische Konventionen ¨ Um die Ubersichtlichkeit zu erh¨hen. Und -rf steht f¨r recuru sive und force. Die Tabelle o 1.net/ in Aktion zu sehen (wenn ich es endlich mal schaffe.PHP‘. daß du jeden Befehl auswendig kennen mußt. ” sondern remove. ” hat ein wichtiger Mensch Geburtstag Zum Mail-Lesen wird auf Unix-Maschinen der Befehl rm (read mail) benutzt. Laß dich davon nicht irritieren.1. um in PHP programmieren zu k¨nnen und sollte o deshalb verstanden worden sein. SpaltenBezeichnungen Tabelle 1.MySQL‘ und . Der Befehl rm bedeutet nicht read mail“. HTML-Text.-) Ein paar der Beispiele sind auch unter http://reeg. in denen meines Erachtens Konstrukte benutzt werden. u Sollte noch etwas fehlen: Meine E-Mail-Adresse kennst du ja.de Wir benutzen hier . Hervorhebungen.

Vorwort Autoren 1. B. Auch die a a Mails.-) Team = Toll. habe ich dann weiter geschrieben. daß das Tutorial etliche Zugriffe verbuchen konnte. ein anderer macht’s! die war irgendwann 1998 die eigentlich gar nicht so toll war Christoph Reeg Seite 5 .-) Tilman Brock Ich bin einer von denen. der das DSP extensiv in die Schulen ge6 7 8 9 Ich lasse es mir nat¨rlich nicht nehmen. Nun folgen ein paar Worte von den einzelnen Autoren (vielleicht werden es irgendwann ja auch noch mehr . als Lektor. habe ich dann mit der Zeit immer mehr auch Neues hinzugef¨gt. Ich bin auch der Erste. Als ich dann aber in die Abrufstatistik von dem Server gesehen und festgestellt hatte. daß erst ein paar u Abschnitte und schließlich ganze Kapitel (wie z. uberall noch etwas zu korrigieren. so daß auch ein paar Anfangsfehler verschwunden sind. werde ich wohl auch noch die n¨chste Zeit damit besch¨ftigt sein und weiterschreiben.-) ). was ich da mache. Christoph Reeg Ich war derjenige. . Im Gegenzug ist Jens u ¨ immer noch so freundlich und korrigiert meine Sachen .junetz. Anstatt jedoch einfach nur Christophs (zahlreiche . die wird dann automatisch an alle weitergeleitet und irgendjemand im Autorenteam7 wird dann schon antworten. zeigen mir immer wieder. weiter zu schreiben und hatte sie einfach auf meiner Homepage9 liegen. also werde ich u zumindest als Lektor wohl immer was zu tun haben. daß es einen gewissen Sinn hat. Jens Hatlak Angefangen habe ich. der mit dem Ganzen angefangen hatte. auch meinen Teil zu dieser PHP/MySQLa u Anleitung zu schreiben. Da ich bis jetzt leider noch nichts Vergleichbares im Internet gefunden habe. was noch dringend beschrieben werden a m¨ßte – aber es steht ja noch die Umstellung auf neue Rechtschreibung an.6 Autoren Inzwischen schreibe ich zum Gl¨ck nicht mehr alleine an diesem Tutorial. So langsam f¨llt mir aber gar nichts mehr ein. wie Stefan Nagelschmitt.de schreiben. kannst du gerne eine Mail an dspautor@ml. die ich gelegentlich bekomme. Wenn du Anregungen zu dem Tutorial hast.-)) Rechtschreibfehler zu korrigieren. In der Zwischenzeit habe ich dann auch noch etwas dazu gelernt. Auf den jeweiu ligen Seiten steht in der Fußzeile. wer das Kapitel im Prinzip geschrieben hat6 . und dann ruht es wieder. Eigentlich war es nur im Rahmen des Jugendnetz FFM/OF gedacht gewesen und nach der ersten Version8 hatte ich auch keine große Lust mehr gehabt.1. jetzt f¨hle ich mich in der Lage. OOP) von mir geschrieben wurden. Uber das Jugendnetz und meine Programmierarbeit mit PHP habe ich das DSP sch¨tzen gelernt. Das ging dann irgendwann so weit. So geht es nun weiter: in gelegentlichen Abst¨nden ergreift mich der Ehrgeiz und ich setze mich wieder f¨r ein paar Wochen dran a u und es entstehen ein paar neue Kapitel. die zusammen mit Christoph beim Jugendnetz Frankfurt ar¨ beiten.

da weder ich noch die anderen Autoren viel an DSP gearbeitet haben und so wurde ich erst im Fr¨hling 2002 wieder – durch eine Mail von u Christoph – an DSP erinnert. ob ich helfen k¨nnte. Er hatte nichts o u dagegen und so konnte ich kurz darauf das erste Kapitel (¨ber XML) f¨r DSP bereitstellen. meine komplette Schule10 – soweit sie mit PHP/MySQL arbeitet – benutzt als erste Dokumentation http:// www. indem ich ein paar Artikel f¨r DSP schreibe.reeg. 10 die Ernst-Reuter Schule I in Frankfurt Christoph Reeg Seite 6 .1. David Peter Ich bin im Herbst 2001 per Zufall auf DSP gestoßen und hab kurz danach Christoph gefragt. u u Danach war eine Weile lang nichts los.net. Vorwort Autoren bracht hat.

Teil I Theoretische Grundlagen Christoph Reeg Seite 7 .

Der Besucher der Webseite bekommt nichts davon mit. die f¨r die Erfordernisse des modernen WWW – dyu namische Webseiten – konzipiert wurde und sich großer Beliebtheit erfreut. ASP. B. Damit jetzt jeder beliebige Surfer im Internet sich die Seiten ansehen kann. B. was die Benutzereingaben auswertet und dementsprechende Webseiten erstellt. Daf¨r ist der Webserver1 (z.html auf der Festplatte. a sondern eine Programmiersprache. wo statische Webseiten nicht ausreichen. o u Apache) da. ColdFusion. PHP und SQL? Weil es einige Bereiche gibt. wozu braucht man dann noch Datenbanken. Sie werden mit Hilfe eines ASCII-/Homepage-Editors erstellt und liegen dann als . 1 2 An dieser Stelle meine ich die Software. ob die Webseite statisch oder dynamisch ist: er bekommt immer HTML von dem Webserver zur¨ck. auch u gegen¨ber den Hochsprachen wie C oder Java finden sich dazu Beispiel wie der bewußte u Verzicht auf strenge Typisierung – aber das w¨rde hier zu weit f¨hren. aber auch neue und in dieser Form besondere Eigenheiten wurden hinzugef¨gt. Er erlaubt den Zugriff aus dem Netz auf die lokalen Dateien. u Der Webserver muß daf¨r sorgen. Wenn es so einfach ist. daß bei dynamischen Webseiten das entsprechende u Programm ausgef¨hrt wird und dessen Ausgabe an den Besucher zur¨ck gegeben wird.-) Christoph Reeg Seite 8 . statische HTML-Seiten eingebettet und bietet somit f¨r den Programmierer einige Vorteile. weshalb ich hier u u nur auf Kapitel 8 verweise. Entstanden ist sie unter dem Einfluß so bekannter Programmiersprachen wie C. muß auch er irgendwie darauf zugreifen k¨nnen. Zum Beispiel bei Suchmaschinen: Die Ergebnisseite h¨ngt von den Suchw¨rtern a o ab. Normalerweise l¨dt man seine Homepage aber auf den Server seines Providers und uberl¨ßt den dortigen a a ¨ Webservern die Bereitstellung der Webseiten.1 Apache: Der Webserver Fangen wir als erstes mit der einfachsten Form von Webseiten an: den statischen Webseiten. Also muß es auf dem Webserver ein Programm geben. denn PHP ist kein Rauschmittel2 . Den lokalen Beh¨rden war offensichtlich nicht klar. eine Webseite zu erstellen.2 Ben¨tigte Software o 2. die du eingegeben hast und es ist unm¨glich f¨r alle m¨glichen Suchw¨rter und deren o u o o Kombinationen statische Ergebnisseiten zu erstellen. nicht den Rechner Oder? . JSP) wird PHP in normale. o u 2. die Droge a u PHP konsumiert zu haben. Wie viele anu dere Programmiersprachen (z.2 PHP . Java und Perl. Von dort kannst du sie dir dann mit jedem beliebigen Browser abrufen und anzeigen lassen. u u Eine m¨gliche Programmiersprache f¨r solche Programme ist PHP.ist das gef¨hrlich? a In den USA stand tats¨chlich einmal ein Sch¨ler unter dem schweren Verdacht. in welches o Fettn¨pfchen sie sich mit dieser Anklage gesetzt hatten.

effiziente Suche. Im Normalfall ist das Betriebsystem f¨r die Nutu u zung von PHP und MySQL unbedeutend. effizient Daten l¨schen. 2. MySQL und PHP ist im Web-Bereich stark vertreten. DBMS).4 LAMP / WAMP Das Trio Apache. die das Thema ausf¨hrlich behandeln. W“ u u ” ” ” ” steht f¨r das verwendete Betriebsystem. WAMP“. a a o ¨ allerdings muß sich dann der Programmierer um einige Sachen. Viel einfacher ist o u es. diese Aufgaben einem Spezialisten zu uberlassen: Dem Datenbank Management System ¨ (kurz. Das L“ bzw. Zum Beispiel bei einem G¨stebuch a a werden die Eintr¨ge gespeichert. usw. Ben¨tigte Software o MySQL 2. Zu diesen Themen gibt es neben den Beschreibungen in der Dokumentation auch etliche Webseiten. Im Web-Bereich ist MySQL sehr verbreitet. Aus diesem Grund hat sich daf¨r auch eine Abk¨rzung etabliert: LAMP“ bzw. B. Apache und PHP wird in diesem Tutorial nicht beschrieben.3 MySQL H¨ufig wird mit Hilfe von PHP auch Daten verarbeitet.[12] u 3 z.2. Die Installation von MySQL. das uber Dateien zu l¨sen. Zumindest f¨r die Windowsu u Plattform gibt es aber ein fertiges Paket. wie zum Beispiel FileLocking3 . Was passiert wenn zwei Besucher zur genau selben Zeit die Seite aufrufen? Christoph Reeg Seite 9 . das einen kompletten Webserver mit Unterst¨tu zung f¨r PHP/MySQL und sogar SSL bereitstellt. selbst k¨mmern. Die einfachste Variante w¨re.

abfragen a und ausgeben k¨nnen. Zur Nutzung und Verwaltung der in der DB gespeicherten Daten ben¨tigt der Anwender ein o Datenbank-Verwaltungssystem (DBMS.3 Datenbanksystem 3. engl. engl. engl. ist Sache des Christoph Reeg Seite 10 . DBMS Anwendung n Datenbank Abbildung 3.1 Komponenten eines Datenbanksystems Eine Datenbank (DB. mit denen u er das Datenmodell beschreiben und einrichten kann. Auf der anderen Seite bietet es die Funktionen an. Data Base Management System). Wie die Daten zu speichern und zu verwalten sind. soll ” ” heißen: Der Entwickler teilt dem Programm die Datenlogik mit und der Anwender formuliert seine Abfrage.: Data Base System). das jedoch h¨ufig f¨lschlicherweise als Datenbank bezeichnet wird. mit denen die einzelnen Anwender Daten eingeben. ver¨ndern. Die Kombination aus DB und DBMS ist das Datenbanksystem (DBS.. a a Anwendung 1 . Data Base) ist eine systematische Sammlung von Daten. ” Auf der einen Seite stellt es dem Entwickler die Instrumente zu Verf¨gung.. o Alle Funktionen des DBMS werden durch was“ und nicht mehr wie“ spezifiziert.1: Struktur eines Datenbanksystems Das DBMS besteht aus einer Vielzahl von Werkzeugen und Generatoren ( Erzeugern“).

Das Betriebssystem zum o anderen bietet Programmen die Hardwarem¨glichkeiten an. Neben dem DBS bauen auch alle anderen Programme auf dieser Ebene auf. .3.. u 3.. Die Speicherlogik.. h¨ngt vom DBMS ab und kann dem Entwickler ziemlich egal a sein. 3. Dieses ist also zust¨ndig f¨r die technische Umsetzung der Anforderungen des a u Entwicklers und der Anwender. User n Programm n Konzeptionelle Ebene Interne Ebene Betriebssystem Abbildung 3. Datenbanksystem Ebenen eines Datenbanksystems DBMS. auf der jede Computeranwendung basiert.2 Ebenen eines Datenbanksystems User 1 Programm 1 . Man kann diese Ebene aber noch weiter unterteilen: Zum einen ist da die Hardware als absolut unterste Ebene.1 Betriebssystem/Hardware Dies ist die unterste Ebene. Den Anwender ¨ Christoph Reeg Seite 11 .2. die dabei verwendet wird. = DB+DBMS) besteht aus den vier Ebenen: 3. engl.: Data Base System.2.2 Interne Ebene Auf der internen Ebene erfolgt die physische Speicherung der Daten..2: Die vier Ebenen eines DBS Ein Datenbanksystem (DBS. deren M¨glichkeiten vom Betriebssystem (BS) verwaltet werden. da er lediglich uber die konzeptionelle Ebene auf die DB zugreift. ohne daß die Programme die o Hardware direkt ansprechen m¨ßten.

Wir verwenden im Folgenden lediglich das relationale Datenmodell. wird das Datenmodell beschrieben..3. der konzeptionellen Ebene.1 Tabellenstruktur Beim relationalen Datenmodell werden die Daten in zweidimensionalen Tabellen angeordnet. Tupel Relation ...2. Unter einem Datenmodell versteht man die datenm¨ßige Abbildung eines bestimmten Ausschnitts a der realen Umwelt. da es (noch) die gr¨ßte Verbreitung besitzt.3.. Jede Tabelle hat einen eindeutigen Relationsnamen.. n¨mlich die externe Ebene.. vernetzten. wie die Beziehungen in dem Datenmodell geregelt werden.3 Konzeptionelle Ebene Auf der dritten. jede einzelne Zeile davon als Tupel bzw... a 3. u Datensatz.2. An } Relationsschema . o 3. a Attribute Relationenname R A1 . objektorientierten. Allgemein wird in jeder Zeile eine Entit¨t abgebildet.3: Tabellenstruktur Um das Ganze etwas konkreter zu machen. Datenbanksystem Ebenen eines Datenbanksystems braucht weder die interne noch die konzeptionelle Ebene zu k¨mmern. unterscheidet man zwischen hierarchischen. die Zusammenh¨nge grafisch darzustellen. da er erst uber die u ¨ oberste. auf die DB zugreift. habe ich in Tabelle 3. die Spalten¨berschriften als Attributnamen oder Attribute und alle Attributu namen zusammen werden als Relationsschema bezeichnet.3 wurde versucht. Christoph Reeg Seite 12 . Abbildung 3. Im Datenmodell sind die Strukturen der Daten und ihre Beziehung zueinander festgelegt.1 ein kleines Beispiel dargestellt. Alle Zeilen der Tabelle (ohne die Spalten¨berschriftszeile) werden als Relation. a In Abbildung 3. . Nach der Art. objektrelationalen und relationalen Datenmodellen.

Datenbanksystem Ebenen eines Datenbanksystems Mitarbeiter MNr 1 2 3 4 5 6 AbtNr 3 1 1 1 2 2 Name Christoph Reeg junetz. In der Relation stehen 6 Datens¨tze a bzw.5. in diesem Fall werden die anderen Attribute als Schl¨sselkandidaten beo u zeichnet.de Uli JCP Maier Meier GebDat 13. Zum Einrichten der DB mit ihren Tabellen bedient man sich der Data Definition Language (DDL).: Data Query Language). a u Teilweise hat man in einer Relation mehrere Attribute. Der u u Schl¨ssel muß immer eindeutig sein und wird auch als Prim¨rschl¨ssel bezeichnet. ‘Name‘. engl. d. Der u a u Prim¨rschl¨ssel muß nicht immer aus nur einem Attribut bestehen. Christoph Reeg Seite 13 . Jeder Mitarbeiter hat die Attribute ‘MNr‘. Oder anders herum: Jeder Schl¨sselkandidat kann jederzeit als Prim¨rschl¨ssel u a u benutzt werden.1979 5. ‘GebDat‘ und ‘Telefon‘. zugreift. welche in unserem Beispiel die WWW-Seite ist. 3. Schl¨ssel u sein k¨nnten.4 Externe Ebene Auf der obersten Ebene befindet sich der Anwender.2 Schl¨ssel u Damit man jede Zeile gezielt ansprechen kann. wird ein Schl¨sselattribut eingef¨hrt. der auf das DBS mit einer DatenAbfragesprache (DQL.3. h. Es kann aber f¨r eine Tabelle immer nur einen Prim¨rschl¨ssel gleichzeitig u a u geben. mehrere Attribute zusammen als (zusammengesetzten) Prim¨rschl¨ssel zu verwenden.1: Beispiel f¨r Tabellenstruktur u Das Beispiel zeigt die Relation mit dem Namen ‘Mitarbeiter‘. Tupel. die eindeutig sind.2.1998 NULL NULL NULL NULL Telefon NULL 069/764758 NULL 069/764758 06196/671797 069/97640232 Tabelle 3.3.2.3. 3. Es ist auch m¨ga u o lich. einer Daten-Manipulationssprache (DML.: Data Manipulation Language) oder einer eigenen Anwendung. engl.

1 Vorgehensweise Die Entwicklung einer DB vollzieht sich in mehreren Schritten. o 4. treten Inkonsistenzen auf. einfach nicht so gut aussieht und er es gerne in Christoph ge¨ndert haben w¨rde. k¨nnen die Tabellen angelegt o werden. a anf¨lliger f¨r Fehler und auch aufwendiger. Dies bringt zwei Nachteile mit sich: Zum einen kostet es mehr Speicherplatz. Diesen Prozeß bezeichnet man als Datenmodelo lierung. a u a u Wenn dies nicht erfolgt. 5 In dem Muster 4 Gibt es nicht 1 Wie man leicht erkennen kann.4 Datenbanken entwickeln Umwege erh¨hen die Ortskenntnisse o unbekannt 4. welche Informationen gespeichert werden sollen.2 Grunds¨tze a ¨ Um sich einigen Arger zu ersparen. Am folgenden Beispiel wird dies besonders deutlich: In folgender Tabelle werden Adressen gespeichert: Vor-/Nachname Hans Maier J¨rgen M¨ller u u Christof Meier Vorname Hans J¨rgen u Christof Straße Musterstr. kommt der jeweilige Vorname in zwei Spalten vor. empfiehlt es sich. dabei a u Christoph Reeg Seite 14 . ohne großen Aufwand Fehler zu beheben. Wenn zum Beispiel Christof Meier feststellt. welche Datentypen f¨r die o u einzelnen Tabellenspalten ben¨tigt werden. was bei einigen ¨ 1000 Datens¨tzen schon etwas ausmacht. Ferner muß festgelegt werden. Erst wenn die Datenmodellierung abgeschlossen ist. mit ‘f‘ geschrieben. Zun¨chst ist festzustela len. Man sollte sich f¨r diesen Schritt ruhig ein wenig Zeit nehmen. da ja zwei Attribute ge¨ndert werden m¨ssen. weil es nachher h¨ufig u a unm¨glich ist. bzw. zum anderen werden Anderungen schwieriger.2. daß ein Christoph. Aufgrund dieser Erhebung kann man sich dann uberlegen. wel¨ che Tabellen ben¨tigt werden. ein paar Grunds¨tze bei der Datena modellierung zu beachten: 4. welche Informationen die Anwender vom DBS erwarten.1 Keine Redundanz Unter Redundanz versteht man das doppelte Vorhandensein einzelner Daten.

Das DBMS verf¨gt nicht uber einen definierten Zugriffsweg auf einen bestimmten Datenu ¨ satz.2 Eindeutigkeit Eine DB enth¨lt Angaben zu den Eigenschaften einer Person oder Sache. was man eigentlich machen will. Diese Vorgehensweise kennen diejenigen. u Beim Festlegen des Schl¨ssels kann man einen Schl¨ssel selbst definieren oder einen u u fremddefinierten ubernehmen. werden bei Relationalen Datenbanksystemen die Daten in Tabellen gespeichert. Deshalb sollten a diese Prozeßdaten bei jeder Abfrage neu errechnet werden. zum Beispiel. z. weil der Schl¨ssel nicht mehr eindeutig u ist. B. welche Daten uberhaupt anfallen ¨ ¨ und wie diese am besten organisiert werden. die durch einen Rechenprozeß aus gespeicherten Attributen gewonnen werden. Dieses Merkmal nennt man Schl¨ssel. ob alle Anforderungen a ¨ realisierbar sind. anfallen und wie diese organisiert werden sollen.4. dann die entsprechenden Prozeduren zu entwickeln und dabei zu sehen. Um die Eindeutigkeit der Tabellenzeilen zu gew¨hrleisten. Deshalb muß in jeder Zeile einer Tabelle ein Wert enthalten sein. daß durch eine Anderung solcher fremddefinierten Schl¨ssel u im DBS Inkonsistenzen auftreten. erst einmal dar¨ber nachzudeno u ken. Sp¨testens nach einem Jahr ist dieser Eintrag falsch. 4. erweitert man den Datensatz um ein Identifikationsmerkmal. An einer anderen Stelle im Programm w¨rde aber wieder der korrigierte Christoph u auftauchen. Anschließend kann man sich dazu die entsprechenden Funktionen ausdenken. Mittels dieser a Angaben muß eindeutig ein bestimmtes Tupel identifizierbar sein. die schon einmal programmiert haben.3. welche Art von Daten man braucht. wird einem a Artikeldatensatz eine Artikelnummer zugeordnet.3 Keine Prozeßdaten Prozeßdaten sind Daten. der diesen Eintrag eindeutig kennzeichnet bzw. u ¨ ¨ Um nicht Gefahr zu laufen. k¨nnten zum Beispiel die Briefe weiter a o an Christof Meier geschickt werden. Demzufolge ist der letzte Schritt bei der Datenmodellierung das Christoph Reeg Seite 15 .2. Datenbanken entwickeln Datenmodelle entwickeln aber nur das Attribut Vorname ge¨ndert wird. einen eigenen zu nehmen. 4. a 4. empfiehlt es sich h¨ufig. Andererseits kann man sich auch zuerst uberlegen.1 Tabellen erstellen Wie im letzten Kapitel dargestellt. man sollte aber trotzdem die ben¨tigten Funktionen nicht aus dem Auge verlieren.3 Datenmodelle entwickeln Es gibt mehrere Vorgehensweisen. Eine M¨glichkeit ist. welche Daten gebraucht werden bzw. weil hier das Attribut Vor-/Nachname verwendet wird. identifiziert.2. Da Datenbanken in der Regel zum Speichern von Daten gedacht sind. empfiehlt sich letztere Vorgehensweise. Bei einem Buch w¨rde sich da die ISBN-Nummer anbieten. 4. Folgendes einfaches Beispiel: Neben dem Geburtsdatum wird auch noch das Alter gespeichert. Im n¨chsten Schritt ist zu uberlegen. Also zusammenfassend: o Als erstes muß man feststellen.

Am Kreuzungspunkt einer Spalte mit einer Reihe darf also maximal ein Datenwert stehen. Siehe dazu auch folgende Tabelle ‘Auftrag‘. das Datum.1999 0815 01. erst mit dem ER-Modell eine Grundstruktur festlegen und diese dann mit den f¨nf Normalformen uberpr¨fen. Datenbanken entwickeln Die f¨nf Normalformen u Festlegen. gibt es f¨r einfache DBs im Prinzip zwei o u M¨glichkeiten: Entweder stur nach Schema-F uber die f¨nf Normalformen (Kapitel 4. mit deren Hilfe man uberpr¨fen kann. Um die ben¨tigten Tabellen zu entwickeln.4. 4. evtl. a Mit anderen Worten: Wiederholungsgruppen sind nicht erlaubt. notwendige u Werte werden der Einfachheit einfach mal unterschlagen). wenn alle Attribute maximal einen Wert haben. wird die Relation ‘Auftrag‘ in zwei gesonderte Relationen aufgespalten. u Erst wenn man gr¨ßere DBs entwickelt.4) o u ¨ oder etwas intuitiver uber das ER-Modell (Kapitel 4. [3] Ein kleines Beispiel: Es sollen alle Bestellformulare eines Versandhandels in einer Datenbank gespeichert werden.1998 54321 ArtikelNr 4692 0567 5671 0579 8971 5324 0579 Anzahl 5 2 3 1 2 5 9 Um die Wiederholungsgruppen zu vermeiden. ob sich ein u ¨ Datenmodell sauber mit Hilfe eines Relationalen DBMS implementieren l¨ßt. Eine einzelne Bestellung enth¨lt die Kundennummer.10.6). Normalform Definition: Ein Relationstyp ist in der 1. anschließend mit Kontrolle ¨ durch die f¨nf Normalformen (Kapitel 4. Das heißt. die Auftragsnuma mer und nat¨rlich die bestellten Artikel sowie deren Anzahl (weitere evtl. wie die Tabellen aussehen sollen.4 Die f¨nf Normalformen u Die Normalformen sind ein Regelwerk. Auftrag KundenNr 12345 AuftragNr 4711 Datum 03. u u ¨ 4.03. muß man mit beiden M¨glichkeiten gleichzeitig o o arbeiten. Man spricht a auch von Normalisierung.1 Die 1. Das Nichtvorhandensein von Daten ist zul¨ssig.4).4. Dadurch w¨rden sich die folgenden beiden Tabellen u ergeben: Christoph Reeg Seite 16 . Normalform.

Wie aber ist das in unserem Fall der bestellten Artikel zu erreichen? Nun. nehmen wir diese als Prim¨rschl¨ssel1 o a u f¨r ‘Auftrag‘. die AuftragNr und die ArtikelNr kommen zwar mehrfach vor. Wenn wir also diese Kombination w¨hlen. ist die o.zusammengesetzter Prim¨rschl¨ssel a u ¨ Damit ergeben sich f¨r unser Beispiel die folgenden beiden Relationen: u best. Diese a u 2 ‘ bezeichnet.3. Artikel‘ als Fremdschl¨ssel u bezeichnet. Forderung erf¨llt. g.10. Da die AuftragNr eindeutig ist.1999 0815 1. In dieser Konstellation wird die Spalte ‘AuftragNr‘ in ‘best. daß jede Zeile eindeutig ansprechbar sein muß. Nun f¨gen wir noch dieser Spalte entsprechend ihrer Werte der Relation u u ‘best. welche Artikel zu welcher o u Bestellung geh¨ren.10.3.1998 KundenNr 12345 54321 Jetzt ist aber die Zuordnung verloren gegangen. Artikel‘ hinzu.4. Wer hat welche(n) Artikel bestellt? Dieses Problem ist einfach zu l¨sen: Wir m¨ssen nur festhalten. und schon haben wir wieder unsere Zuordnung. Artikel ArtikelNr Anzahl 4692 5 0567 2 5671 3 0579 1 8971 2 5324 5 0579 9 AuftragNr 4711 0815 Auftrag Datum 3. Kombination wird ubrigens als . Datenbanken entwickeln Die f¨nf Normalformen u best.1998 Anzahl 5 2 3 1 2 5 9 KundenNr 12345 54321 1 2 Prim¨rschl¨ssel werden im folgenden durch eine f¨hrende Raute (#) gekennzeichnet a u u bei zusammengesetzten Prim¨rschl¨sseln wird im Folgenden jeder Teil mit einer f¨hrenden Raute (#) a u u gekennzeichnet Christoph Reeg Seite 17 . Artikel # AufragNr # ArtikelNr 4711 4692 4711 0567 4711 5671 4711 0579 0815 8971 0815 5324 0815 0579 Auftrag # AuftragNr Datum 4711 3. Weiterhin wurde schon auf Seite 15 gefordert. trotzdem ist die L¨sung aber ganz einfach: Die Kombination aus AuftragNr und ArtikelNr muß eindeuo tig sein.1999 1.

wenn ihr Prim¨rschl¨ssel nicht zusammengesetzt ist. Daraus w¨rden dann die folgenden zwei Relationen entstehen: u best. Normalform ist erf¨llt. Normalform.4. a u best. Damit w¨rde sich die folgende Artikel-Tabelle ergeben. NF gen¨gt. a ¨ Christoph Reeg Seite 18 .4.4. wenn die 2. a a ¨ Relationstypen. Normalform. Datenbanken entwickeln Die f¨nf Normalformen u 4. die in der 1. der ArtikelNr und der Menge soll auch der Hersteller des Artikels gespeichert werden. Normalform Definition: Die 3.3 Die 3. Normalform erf¨llt ist und die u u Nicht-Schlussel-Attribute funktional unabh¨ngig voneinander sind. [3] a u Ein kleines Beispiel: Neben der AuftragNr. Artikel # ArtikelNr Menge 4692 5 0567 2 5671 3 0579 1 8971 2 5324 5 0579 9 # AuftragNr 4711 4711 4711 4711 0815 0815 0815 Hersteller Blech-AG Keramik GmbH Baustoff KG Keramik GmbH Keramik GmbH Baustoff KG Keramik GmbH In diesem Beispiel ist das Attribut ‘Hersteller‘ nur vom Teilschl¨ssel ‘ArtikelNr‘ und u nicht auch von ‘AuftragNr‘ abh¨ngig. muß das a u Attribut ‘Hersteller‘ aus der Relation herausgenommen und der (neuen) Relation Artikel zugeordnet werden. sind automatisch in der 2. Normalform Definition: Ein Relationstyp ist in der 2. Damit die Relation der 2. Artikel Artikel # AufragNr # ArtikelNr Anzahl # ArtikelNr Hersteller 4711 4692 5 4692 Blech-AG 4711 0567 2 0537 Keramik GmbH 4711 5671 3 5671 Baustoff KG 4711 0579 1 0579 Keramik GmbH 0815 8971 2 8971 Keramik GmbH 0815 5324 5 5324 Keramik GmbH 0815 0579 9 4. Normalform sind. Normalform ist und jedes Attribut vom gesamten Prim¨rschlussel abh¨ngt. wenn er in der 1. u AuftragNr und ArtikelNr sind der zusammengesetzte Prim¨rschl¨ssel.2 Die 2.

W¨rde a u u man die zus¨tzliche Spalte einfach in die vorhandene Tabelle Artikel einf¨gen. Als Prim¨rschl¨ssel wird die ArtikelNr verwendet. wenn f¨r jedes Vorkommen ein und desselben Wertes von A immer derselbe u Wert von B auftreten muß. [3] Ein kleines Beispiel: Zu den einzelnen Artikeln sollen die ArtikelNr. Und diese a a funktionale Abh¨ngigkeit der beiden Nicht-Schl¨ssel-Attribute HerstellerNr und Hersteller a u ist nicht erlaubt. die wiederum abh¨ngig von der ArtikelNr ist. der Hersteller und die HerstellerNr gespeichert werden. erg¨be sich a u a damit folgende Tabelle: Artikel Bezeichnung HerstellerNr Putzeimer 5410 Waschbecken 5647 Gummi 6740 Teller 5647 Tasse 5647 Badewanne 5647 # ArtikelNr 4692 0567 5671 0579 8971 5324 Hersteller Blech-AG Keramik GmbH Baustoff KG Keramik GmbH Keramik GmbH Keramik GmbH Wie man unschwer erkennen kann. so ist B funktional abh¨ngig von a A. die Bezeichnung. Eine funktionale Abh¨ngigkeit kann auch von einer Gruppe von Attributen a bestehen. ist der Herstellername von der ArtikelNr uber die ¨ HerstellerNr transitiv abh¨ngig.4. Oder anders ausgedr¨ckt: Der Herstellername ist funktioa u nal abh¨ngig von der HerstellerNr. Was jetzt kommt. Datenbanken entwickeln Die f¨nf Normalformen u Sind A und B Attribute eines Relationstyps. es ergeben sich folgende Tabellen: # ArtikelNr 4692 0567 5671 0579 8971 5324 Artikel Bezeichnung Putzeimer Waschbecken Gummi Teller Tasse Badewanne HerstellerNr 5410 5647 6740 5647 5647 5647 Hersteller # HerstellerNr Hersteller 5410 Blech-AG 5647 Keramik GmbH 6740 Baustoff KG Christoph Reeg Seite 19 . ist nicht schwer zu erraten: Die Tabelle ‘Artikel‘ wird in die beiden Tabellen ‘Artikel‘ und ‘Hersteller‘ aufgespalten. Das heißt.

jeweils die gleiche Wertemenge von C auftreten muß. Sind A. B und C Attribute eines Relationstypes. f¨r die der Artikel bestellt ist. jeweils u u die gleiche Gruppe von Auftr¨gen auftreten. Normalform ist erf¨llt. die zusammen mit u u diesem Wert von A auftreten. Normalform k¨nnen Gruppeninkonsistenzen“ auftreo ” ten. Bei Verstoß gegen die 4. in denen ein Artikel vorkommt a Es soll nicht ausgesagt werden.4. in denen der Artikel aufbewahrt wird. Christoph Reeg Seite 20 . aus welchem Lager der Artikel f¨r einen Auftrag kommt. so ist C mehrwertig abh¨ngig a von A. u Folgende mehrwertige Abh¨ngigkeiten liegen vor: a • ‘Lager‘ ist mehrwertig abh¨ngig von ‘ArtikelNr : a F¨r jeden Artikel muß f¨r alle Auftr¨ge. NF gen¨gt. falls f¨r jeden Wert von A f¨r alle Werte von B. Normalform Definition: Die 4. [3] Kurzes Beispiel: Disposition ArtikelNr Lager AuftragNr 04532 SFO-4 2063 04532 NYC-4 2063 04532 SFO-4 2267 04532 NYC-4 2267 53944 ORD-1 2088 53944 SFO-1 2088 53944 LAX-1 2088 53944 ORD-1 2070 53944 SFO-1 2070 53944 LAX-1 2070 In der Relation Disposition sind folgende Informationen festgehalten: • der Lagerort f¨r jeden Artikel u • Auftr¨ge.4. jeweils die u u a u gleiche Gruppe von Lagern auftreten. wenn die 3. in welchem Zusammenhang Artikel und Lager stehen. Datenbanken entwickeln Die f¨nf Normalformen u 4. Die erste Relation beschreibt. F¨r verschiedene Werte von A k¨nnen unterschiedliche Wertemengen von u o C auftreten. a Damit die Relation der 4. muß sie in zwei neue Relationen (Artikel-Lager u und Artikel-Auftrag) aufgespalten werden. Normalform erf¨llt ist und wenn u u keine paarweise auftretenden mehrwertigen Abh¨ngigkeiten vorhana den sind. die zweite den Zusammenhang zwischen Artikel und Auftrag.4 Die 4. • ‘AuftragNr‘ ist mehrwertig von ‘ArtikelNr‘ : F¨r jeden Artikel muß f¨r alle Lager.

ohne gegen eine Normalisierungso form zu verstoßen. gibt es verschiedene Methoden. Trotza u dem sollte man sich immer im klaren dar¨ber sein. mit sich nicht ¨ndernden Daten a gegen die Normalformen zu verstoßen.4.4. bei kleineren f¨r manche sch¨ner: das Entity o a u o Relationship-Modell. Normalform Definition: Ein Relationstyp ist in der 5. Es ist jedoch zu pr¨fen. Artikel‘. Damit ist es dann m¨glich. anhand des Vorgangskatalogs zu uberpr¨fen. Eine Methode. Normalform. 4.4. oder? . mit ¨ der man relativ schnell einen Uberblick uber die vorhandenen Relationen einschließlich ¨ deren Attribute und Beziehungen bekommt. k¨nnen wir diesen Schritt getrost ubergehen. die denselben Prim¨rschl¨ssel a u haben. ‘Artikel‘ und ‘Hersteller‘ aus dem obigen Beispiel in der Abbildung 4.1 dargestellt. Bei diesen entf¨llt n¨mlich das Problem. Normalform ist und er sich unter keinen Umst¨nden durch Kombination einfacherer Relaa tionstypen mit unterschiedlichen Schl¨sseln bilden l¨ßt. ob man in der Normalisierungswut die u Tabellen nicht zu sehr auseinandergerissen hat. [3] u a Das ist doch eigentlich selbsterkl¨rend. Bei umfangreichen Datenbest¨nden mit hohen Zugriffszahlen kann es sich jedoch teilweia se empfehlen. o o ¨ Hierbei kann man sagen. ist das Streifendiagramm. wenn er in der 4. Tabellen. daß der Server ubera ¨ lastet werden k¨nnte. ob die a u ¨ Tabellen den Anforderungen der Vorg¨nge entsprechen.-) a 4.6 Das ER-Modell Bei gr¨ßeren Projekten unumg¨nglich. Als Beispiel habe ich die Relationen ‘Auftrag‘. a 4. Wer ein wenig Erfahrung mit Datenbanken hat und gut nachdenkt. die man nach den f¨nf Normalisierungen erhalten hat. k¨nnen ohne weiteres zusammengelegt werden.5 Die 5. wann man gegen die Normalformen u verstoßen hat! Als n¨chstes ist anhand des Streifendiagramms (Kapitel 4.5 Streifendiagramm Um die Tabellen grafisch dazustellen. Datenbanken entwickeln Streifendiagramm 4. daß es weniger problematisch ist. daß beim a a ¨ Andern nicht alle Daten ver¨ndert werden und dadurch Widerspr¨che entstehen. ob alle Vorg¨nge m¨glich sind und o u a o ¨ die Relationen stimmen.6 Denormalisierung der Tabellen Im Prinzip kann man die Tabellen. u 1:1 in der DB verwenden. Christoph Reeg Seite 21 . u Da wir aber keine so hohen Zugriffszahlen und Datenbest¨nde haben. kann auch mit Hilfe des ER-Modells Datenmodelle entwickeln.5) zu uberpr¨fen. ‘best. die allen Normalformen entsprechen. aus Performancegr¨nden wieder eine gewisse Denormalisierung herzustellen.

[gegebene] Gr¨ße [2] o Wer jetzt weiß. Daß eine Abteilung keinen Mitarbeiter haben kann. Es sollen alle Mitarbeiter u der Firma gespeichert werden. einem oder mehreren Mitarbeiter bestehen. -/-en. Eine Abteilung kann aus o keinem. Jeder Mitarbeiter hat einen Vorgesetzten und geh¨rt zu o einer Abteilung. die uber Attribute weiter beschrieben werden k¨nnen. der gestrichelte einer oder keiner.2 stellt die Beziehung der drei Entit¨ten und deren Attribute dar. sind wir beim zweiten Begriff angelangt: Relationship bedeutet so viel wie Beziehung“ oder Relation“. o ¨ Nachdem wir jetzt hoffentlich wissen. Außerdem verf¨gt jede Abteilung uber einige oder keine PKWs aus dem u ¨ Fuhrpark f¨r die Mitarbeiter. Philosophie: die bestimmte Seinsverfassung (Wesen) a des einzelnen Seienden. f¨r alle anderen u ¨ versuche ich.1: Streifendiagramm Es gibt verschiedene Formen. Der durchgezogene Strich a bedeutet genau einer. auch diese selbst. kann diesen Absatz uberspringen. wer u a o wann mit welchem Wagen wie viele Kilometer gefahren ist. wenn die u Abteilung gerade erst eingerichtet wurde? Christoph Reeg Seite 22 . B.: Ein Mitarbeiter geh¨rt zu genau einer Abteilung. a Was bedeutet eigentlich Entity-Relationship ?? F¨r Entit¨t gibt es verschiedene gebr¨uchliche Definitionen: u a a Entit¨t [mlat. mag auf den ersten Blick merkw¨rdig erscheinen. a a Die Zeichnung 4. was Entity bedeutet. a a Die Striche zwischen den Entit¨ten stellen deren Beziehung da. Dasein im Unterschied zum Wesen eines a Dinges (Philos. [1] Entit¨t [lat. was Entity bedeutet. ” ” Ein kleines Beispiel: F¨r ein Unternehmen soll eine Datenbank entwickelt werden. Beim ER-Modell a ¨ sind Entities Objekte. -en: 1.] die. Diese Realtit¨tsbeschreibung legt drei Entit¨ten nahe: Mitarbeiter. als auch nachher die Tabellen werden grunds¨tzlich in der Einzahl bezeichnet.-mlat. letztlich sind es konkrete Objekte der Realit¨t. Sowohl die a Entit¨ten. Abteilung. -. 2. Zus¨tzlich soll die Antwort auf die Frage m¨glich sein. Der Kr¨henfuß auf der ana deren Seite bedeutet einer oder mehrere. Datenbanken entwickeln Das ER-Modell Auftrag best. es anders zu erkl¨ren: Entity“ kann man mit Objekt“ oder Ding“ ins a ” ” ” Deutsche ubersetzen. a Wie man unschwer erkennen kann. was die o Beziehung aussagt.). stellen die Rechtecke die Entit¨ten da. Artikel Artikel Hersteller ArtikelNr ArtikelNr AuftragNr KundenNr Datum AuftragNr Anzahl HerstellerNr Bezeichnung HerstellerNr Hersteller Abbildung 4.]die.4. Ich benutze hier das sogenannte Kr¨henfuß-Diagramm. PKW. das ER-Modell zu zeichnen. Also z. Was ist aber. Die W¨rter an den Strichen zeigen.

Datenbanken entwickeln Das ER-Modell Mitarbeiter #* MNr * Name o GebDat o Tel-Nr gehört zu ist Vorgesetzter besteht aus Abteilung #* AbtNr * Name Untergebener von ist gefahren besitzt gehört zu PKW gefahren von #* PKWNr (#)* Kennzeichen * Typ Abbildung 4.2: ER-Beispiel 1 Christoph Reeg Seite 23 .4.

Mitarbeiter #* MNr * Name o GebDat o Tel−Nr Abteilung gehört zu ist Vorgesetzter #* AbtNr besteht aus * Name Untergebener von besitzt gehört zu Fahrtenbuch * Datum PKW #* PKWNr (#)* Kennzeichen * Typ Abbildung 4.7 Relationen erstellen Last but not least m¨ssen aus dem ER-Modell noch die Tabellen erstellt werden.4. Das u ist allerdings kein großes Problem mehr . Datenbanken entwickeln Relationen erstellen Wie wir bei der Entit¨t Mitarbeiter sehen. Daß diese Beziehung von beider Seite eine .3 dargestellt. Wenn man sich dieses ER-Modell einmal genauer ansieht. Attribute. Als a n¨chstes sucht man sich alle Prim¨rschl¨ssel.3: ER-Beispiel 2 4. mag auf den ersten Blick komisch erscheinen. bei den optionalen wird ein o verwendet. Wie das dann o genau aussieht. Um dieses Problem zu l¨sen. Aber nicht jeder Mitarbeiter hat einen Vorgesetzten. Prim¨rschl¨sselkandidaten dagegen durch (#) markiert.jede Entit¨t wird einfach zu einer Tabelle. werden mit einem * versehen. In unserem Beispiel erg¨be sich folgendes: a a u a Christoph Reeg Seite 24 . bei a u denen ein Wert eingetragen werden muß. Link-Relation erstellt. Uber diese Beziehung wird ausgesagt wer Vora gesetzter von wem ist. In den Rechtecken stehen die wichtigsten Attribute. daß es gegen die 1. der Chef hat keinen. kann es durchaus auch eine Beziehung zwia ¨ schen einer Entit¨t mit sich selber geben. Prim¨rschl¨ssel werden durch ein a u # gekennzeichnet.kann‘-Beziehung sein soll. Die Beziehung zwischen ‘Mitarbeiter‘ und ‘PKW‘ ist eine n:m Bezieo hung. NF verst¨ßt. wird eine sog. stellt man fest. ist in Abbildung 4.

Im Prinzip gibt es drei verschieu dene Datentypen: Zahlen. u Christoph Reeg Seite 25 . h. In den verschiedenen Datenbanken gibt es dazu dann entsprechend verschiedene Gr¨ßen. daß ein PKW u u ein neues Kennzeichen bekommt. o u Nachdem man die Prim¨rschl¨ssel herausgesucht hat. Datum PKWNr Die Relation ‘Fahrtenbuch‘ hat einen zusammengesetzten Prim¨rschl¨ssel. PKWNr. Bei ‘PKW‘ wurde nicht das Kennzeichen als Prim¨rschl¨ssel genommen.4. h¨tte man einen Verstoß gegen die 1. W¨rde man dagegen die u u Mitarbeiter-Nummer in ‘Abteilung‘ einf¨gen. obwohl es sich a u daf¨r eignen w¨rde (mit Sicherheit eindeutig). muß noch festgelegt werden. u a Aus unserem Beispiel erg¨ben sich also folgende Relationen (mit Angabe der zu den a Fremdschl¨sseln geh¨rigen Prim¨rschl¨ssel): u o a u Tabelle Mitarbeiter Abteilung Fahrtenbuch PKW Prim¨rschlussel a ¨ MNr AbtNr MNr. die einen Kr¨henfuß a a haben. Das ist auch logisch. Datum PKWNr Fremdschlussel ¨ AbtNr [Abteilung(AbtNr)] VNr [Mitarbeiter(MNr)] MNr [Mitarbeiter(MNr)] PKWNr [PKW(PKWNr)] AbtNr [Abteilung(AbtNr)] Als letztes m¨ssen noch die ben¨tigten Attribute den Relationen hinzugef¨gt und f¨r u o u u alle Attribute die entsprechenden Datentypen festgelegt werden. Allerdings kann es passieren. Die ‘MNr‘ a u oder auch das Datum f¨r sich alleine w¨ren nicht eindeutig. 4. NF. sondern grunds¨tzlich alle m¨glichen Ausnahmen in Betracht ziehen. B. Eine Auflistung m¨glicher Datentypen o o f¨r MySQL befindet sich im Kapitel 6. welche Datentypen f¨r die einzelnen Attribute verwendet werden sollen. bekommen den Prim¨rschl¨ssel der anderen Relation. Um auch dann noch die Datenintegrit¨t sicherstellen zu a k¨nnen. mehrere Leute gleichzeitig a Autos fahren. notwendig. Text und große Objekte. da ein Mitarbeiter ja nicht u a nur einmal Auto f¨hrt und zu einem Zeitpunkt ja auch ggf. B. es muß z.2. Alle Relationen. In der Kombination jedoch sind die drei Attribute eindeutig. PKWNr.8 Datentypen Nachdem jetzt die Datenstruktur feststeht. u ¨ Bei der Uberlegung. B. 5a“ auch eine u a ” g¨ltige Hausnummer ist. sollte man nicht vom Normalfall ausgehen. f¨r ‘Hausnummer‘ einen Text-Typ zu w¨hlen. D. habe ich ein neues Attribut eingef¨hrt. damit man die Beziehung zwischen den Relationen herstellen kann. Datenbanken entwickeln Datentypen Tabelle Mitarbeiter Abteilung Fahrtenbuch PKW Prim¨rschlussel a ¨ MNr AbtNr MNr. m¨ssen auch die Fremdschl¨ssel a u u u gesucht werden. Das ist mit dem Kr¨henfußdiagramm relativ einfach. So ist es a o z. die Aba u teilungsnummer in die Relation ‘Mitarbeiter‘ eingef¨gt werden. welcher Datentyp zu verwenden ist. denn u eine Abteilung kann nat¨rlich auch mehrere Mitarbeiter haben. da z.

Teil II Praktischer Teil SQL Christoph Reeg Seite 26 .

so daß es empfehlenswert ist. die Tabellenstruktur anzeigt oder beim Andern die alten Werte als Vorbelegung nimmt etc. das z.5 SQL benutzen Ein DBS kann auf drei Arten gesteuert werden: Entweder dialogorientiert. um die Informationen zu speichern. im BatchBetrieb oder durch andere Programme. Das nennt man dann Batch-Betrieb. sich zu u Hause ein DBMS zu installieren3 . Dann kann man n¨mlich ohne u a großen Aufwand dieselbe Tabellenstruktur in verschiedenen DBs verwenden. B. der dir die 1 2 3 unter Windows: MS-DOS Eingabeaufforderung unter DOS z. H¨ua fig wird daf¨r PHP verwendet.1 MySQL Um mit dem DBMS zu reden“. Yahoo) in irgendeiner Form eine Datenbank.3. Es muß dann ein Programm geben. In diesem Kapitel werden wir dialogorientiert arbeiten. c: > Das schließt nat¨rlich das Starten des Datenbank-Servers mit ein! u Christoph Reeg Seite 27 . Dialogorientiert bedeutet. daß man am Bildschirm seine Befehle eingibt und innerhalb von Sekunden das Ergebnis oder die Fehlermeldung a erh¨lt. k¨nnen aber auch in eine Text-Datei geschrieben werden. ¨ Uber den MySQL-Prompt hat man nat¨rlich die meisten M¨glichkeiten. f¨r die Erstellung von Tabellen. Ein sehr sch¨nes Programm dazu ist PHPMyAdmin. B. AltaVista. B. In beiden F¨llen a 2 . weil man jeden u o Befehl verwenden kann. alle Suchmaschinen im Internet (Google. So benutzen z. B. Dieses Programm kann im Prinzip in jeder beliebigen Sprache geschrieben werden. muß das Programm mysql von einem Rechner. was weiter unten noch beschrieben wird. daß eine oder welche Datenbank im Hintergrund arbeitet. Bei der Benutzung durch andere Programme merkt der Benutzer nicht. Benutzername und DB-Name sind nat¨rlich die entsprechenden Werte einu u zutragen (ohne die spitzen Klammern!). Sehr empfeh” lenswert ist dies z. Die mysql-Aufrufsyntax lautet: mysql -p<Paßwort> -u <Benutzername> <DB-Name> F¨r Paßwort. H¨ufig ist aber auch ein wenig Unterst¨tzung durch ein Programm a u ¨ praktisch. das die o eingegebene Anfrage an die Datenbank weiterreicht und dann die Ergebnisse formatiert ausgibt. mehr dazu o im Kapitel 7. Als normaler Nutzer sieht man aber nur die Suchmaske und bekommt dann die Ergebnisse sch¨n formatiert angezeigt. Das ganze ist vergleichbar mit der Konsole1 beim Betriebssystem. Diese bekommst du vom Provider. an dem man seine Befehle eingibt und im selben Fenster erscheint gibt es einen Prompt dann die Ausgabe. die hier direkt eingegeben werden. gestartet werden. Viele Provider erlauben dies leider aus Sicherheitsgr¨nden nicht. u 5. von dem ” aus man Zugriff auf den Rechner mit dem DBMS hat. die dann o dialogorientiert“ abgearbeitet wird. Alle Befehle.

bei den Tabellen. or \\g. kannst dann aber einige Befehle nicht nutzen. kommt folgende Ausgabe (oder ahnlich): ¨ Welcome to the MySQL monitor. . bekommst du zwar auch den mysql-Prompt. Einen. Der nur lesende Account bekommt ein ‘ ro‘ an das Ende des Benutzernamens angeh¨ngt. das Paßwort hinter -p anzugeben. der nur lesend zugreifen darf. ¨hnelt dem normalen mysql-Aufruf: a mysql -p{Paßwort} -u{Benutzername} {DB-Name} < dateiname Alle (Fehler-)Meldungen. SQL benutzen MySQL Datenbank zur Verf¨gung stellt.22. im Falle einer eigenen DB.2 uber MySQL-Nutzer durchlesen. Der Aufruf.-) Alternativ kannst du auch dein Paßwort abfragen lassen: mysql -u <Benutzername> -p <DB-Name> Enter password: ******** Wie du siehst.5. wenn in der letzten Zeile ein mysql> steht. kannst du deine Befehle eingeben. wird in diesem Fall das Paßwort explizit abgefragt. Wenn du keinen DB-Namen angibst. 4 American Standard Code for Information Interchange Christoph Reeg Seite 28 .und Spaltennamen (Attribute) sowie den eigentlichen Werten dagegen nat¨rlich nicht! u 5. gibst du dir selbst die u Daten. die normalerweise angezeigt werden. kann man die Befehle auch mit einem ASCII4 -Editor in eine a Datei schreiben und diese dann abarbeiten lassen. . solltest du dir auch a den Abschnitt 7. Solltest du einen eigenen Server mit MySQL betreiben. mysql> Immer dann. f¨r den u u sowohl Lese. Wir beim Jugendnetz richten immer zwei Accounts f¨r dieselbe DB ein. ¨ Wenn das alles geklappt hat. Diese Methode ist der M¨glichkeit. u weil nach einem solchen je nach Reihenfolge der Parameter der Datenbankname erwartet wird . Die Groß-/Kleinschreibung ist bei den Befehlen egal. aus zwei Gr¨nden vorzuziehen: Zum o u einen erscheint dann das Paßwort weder (unter Unix/Linux) in der . weil du mit keiner Datenbank verbunden wirst.. bzw. werden auf den Bildschirm geschrieben.1 Dateien abarbeiten Wie oben schon erw¨hnt.32 Type ’help’ for help.1. darauf achten zu m¨ssen. Commands end with . der das Abarbeiten der Datei startet. und einen anderen.bash history noch im Klartext auf dem Bildschirm und zum anderen hat man dann auch nicht das Problem. Your MySQL connection id is 1561 to server version: 3. . daß zwischen -p und dem Paßwort kein Leerzeichen stehen darf. Dann mußt du noch mit Hilfe von USE <DB-Name> die Datenbank angeben.als auch Schreibzugriffe erlaubt sind.

. SELECT * FROM Mitarbeiter.als Kommentarzeichen. und aus welcher Tabelle? */ Mitarbeiter.h.5. als Kommentar interpretiert. was hinter dem Zeichen bis zum Zeilenende steht. Es gibt auch noch # und .. Christoph Reeg Seite 29 .Diese Zeile macht dasselbe wie die dar¨ber u # ist kein Kommentarzeichen nach ANSI-Norm. SQL benutzen MySQL 5. Die beiden folgenden Anweisungen sind identisch: u SELECT * FROM Mitarbeiter. SELECT * /* Was soll alles ausgew¨hlt werden? */ a FROM /* . # Wir wollen alles SELECT * FROM Mitarbeiter. andere Datenbanken k¨nnen diese o Kommentare nicht erkennen. Bei diesen wird alles..1.2 Kommentare Kommentare k¨nnen wie in der Programmiersprache C mit /* und */ umrahmt in die o Datei eingef¨gt werden. d. -.

gefolgt von dem gew¨nschten Namen der Datenbank. B. Als theoretische Grundlage wird die Beispiel-Datenbank. h. die sich in einem solchen Unterverzeichnis befinden. indem man erst am Ende das Semikolon setzt. Helmut Walters Sobald man mit dem DBMS verbunden ist. Benutzername und Paßwort. mußt du das Einrichten der Datenbank auch selbst erledigen. bei a Portierungen von Datenbanken nach Unix/Linux. Im Allgemeinen wird wohl eine Datenbank vom Administrator (beim Jugendnetz: wir) eingerichtet werden. vermeidest du durch dieses Vorgehen sp¨teren Arger z. 6. bei der Installation eines Offline-Testwebservers). kann man die Befehle eingeben. Tabellen. Diese Dateien bestehen aus Bin¨rcode. also technisch. g. benutzt.und Kleinschreibung zu acha ten und diese konsistent zu halten. a Das bessere Ged¨chtnis ist wie ein a Sieb. auch hier l¨uft Mya ¨ SQL!) weniger restriktiv ist. Von diesem bekommst du dann auch die n¨tigen Zugangsdaten wie o Datenbankname. d. worauf es a ankommt. Selbst wenn Windows (ja. Christoph Reeg Seite 30 . sie k¨nnen und sollten a o ausschließlich von MySQL selbst gelesen werden (anders als etwa .6 SQL-Befehle Das gute Ged¨chtnis ist wie ein Sack. die in Kapitel 4. Bei der dialogorientierten Benutzung und im Batch-Betrieb m¨ssen die Befehle immer u mit einem . es beh¨lt nur. sind als Dateien realisiert.1 CREATE DATABASE Was eine Datenbank theoretisch ist.und Feldnamen grunds¨tzlich auf die Groß. ” Als Grundregel solltest du dir einfach angew¨hnen.sql Dateien). Relationen dieser Datenbank. die auch von PHP aus aufgerufen werden.6 beschrieben wurde. wie sie angelegt wurden. B. Wie aber sieht es auf dem Server. bei jeglichen Eingaben von Dateno bank-. aus? Im Falle von MySQL entspricht eine Datenbank hier ganz profan einem bestimmten Unterverzeichnis der MySQL-Installation. DateisystemAbh¨ngigkeit der Datenbank (Verzeichnischarakter) w¨re die Datenbank Termine“ n¨ma a a ” lich eine andere als termine“. Man kann ohne Probleme einen Befehl in mehrere Zeilen schreiben. die Tabellen. haben wir im letzten Kapitel 4 gelernt. abgeschlossen werden. der MySQL-Befehl hierzu lautet CREATE DATABASE. also auch in allen SQL-Befehlen diese Namen genau so zu verwenden.und Kleinschreibung. u Beim Anlegen wie auch beim sp¨teren Benutzen der Datenbank ist folgendes zu bedena ken: Unix/Linux unterscheidet Groß. Aufgrund o. a es beh¨lt alles. Bist du selbst jedoch der Administrator des Systems (wie z.

daß ein Wert (das kann auch ein leerer sein) eingetragen werden muß. die Teil des Schl¨ssels sind.2 CREATE TABLE Als erstes m¨ssen wir nat¨rlich die Tabellen erstellen.6. a Arbeitest du hingegen auf dem mysql-Prompt. Dazu dient der Befehl CREATE u u TABLE. der h¨chste Wert +1 genommen.2). h. Wenn UNIQUE bei einem Feld angegeben wurde. Es gibt keine Fehlermeldung (nur MySQL)! Wenn ein Zahlenfeld mit dem Schl¨sselwort AUTO_INCREMENT angelegt wurde.) oder UNIQUE (feld_name. Die Syntax lautet: CREATE TABLE table_name (create_definition. NULL ist nicht mit der Zahl 0 zu verwechseln. Bei zusammengesetzten Prim¨ra u a schl¨sseln sind alle Felder.. Sobald erst eine Kombination mehrerer Spalten den Prim¨rschl¨ssel bildet. wird. darf ein Wert in maximal einem Tupel vorkommen. u solange kein Wert f¨r dieses Feld angeben wurde. h..) oder FOREIGN KEY (feld_name. MySQL unterst¨tzt bis u u jetzt noch keine Fremdschl¨ssel und ignoriert folglich die Angaben.1 zu verwenden. Mit FOREIGN KEY wird die Fremdschl¨sselbeziehung angegeben. wird der Standardwert u genommen. Prim¨rschl¨ssel m¨ssen u u a u u eindeutig sein und es muß NOT NULL angegeben werden. d. u o AUTO_INCREMENT kann nur einmal pro Tabelle in einem Prim¨rschl¨sselfeld verwendet a u werden.... NULL bedeutet einfach kein ” Wert“. Mit PRIMARY KEY wird der Prim¨rschl¨ssel festgelegt. anzugeben.. daß mehrere ‘create definitions‘ durch Kommas getrennt hintereinander stehen k¨nnen.. u a Die drei Punkte hinter ‘create definition‘ bedeuten.) [reference_definition] F¨r ‘reference definition‘ muß man folgendes einsetzen: u REFERENCES table_name[(index_spalte. h. du kannst jetzt Tabellen mit entsprechenden Feldern anlegen (mehr dazu im n¨chsten Abschnitt: 6.) F¨r table name ist selbstverst¨ndlich der Name der zu erstellenden Tabelle einzusetzen.... Wenn bei INSERT kein Wert f¨r dieses Feld angegeben wurde. Bei Prim¨rschl¨sseln wird automatisch a u UNIQUE angenommen. mußt du zuerst die Datenbank wechseln: das geht mittels USE <DB-Name>. eindeutig ist.. jeder Wert muß eindeutig sein.. d. UNIQUE und PRIMARY KEY k¨nnen entweder direkt hinter einer Spaltendefinition angeo geben werden oder getrennt davon. AUTO_INCREMENT gibt es nur in MySQL... d.. u F¨r Typ ist einer der Datentypen aus Tabelle 6. u Christoph Reeg Seite 31 . SQL-Befehle CREATE TABLE Nach dem Einrichten der Datenbank ist diese bereits benutzbar. 6. Die ‘create definitions‘ m¨ssen innerhalb o u der runden Klammern stehen! F¨r ‘create definition‘ kann man folgendes einsetzen: u feld_name Typ [NOT NULL] [AUTO_INCREMENT] [UNIQUE] [PRIMARY KEY] oder PRIMARY KEY (feld_name.)] Mit NOT NULL wird festgelegt. muß der Prim¨rschl¨ssel getrennt angegeben a u a u werden.

127 0 . Text mit einer max. Format: HH:MM:SS. hour) Monat (engl.967.647 0 .295 -3402823e+31 .216 Zeichen a Zeit...483.. L¨nge von 65535 Zeichen a Text mit einer max. wird bei Vergleichen nicht auf Groß-/Kleinschreibung geachtet. 2. 3402823e+31 Kommazahl der L¨nge ‘length‘ und mit ‘dec‘ Dezimala stellen.. second) Jahr (engl. Soo lange nicht ‘BINARY‘ angegeben wurde. HHMM oder HH Datum. Alle Leerstellen am Ende werden gel¨scht. Format: YYYYMMDDHHMMSS.147. minute) Sekunde (engl.777.1: Verf¨gbare Datentypen in SQL u Typ TINYINT TINYINT UNSIGNED INT INT UNSIGNED BIGINT DECIMAL(length.483. die L¨nge betr¨gt: Stellen vor dem Komma + a a 1 Stelle f¨r Komma + Stellen nach dem Komma u Zeichenkette mit max ‘NUM‘ Stellen (1 ≤ N U M ≤ 255)..dec) Beschreibung -128 . day) Stunde (engl. L¨nge von 16. SQL-Befehle CREATE TABLE Tabelle 6. wird immer nur das erste automatisch ge¨ndert! a VARCHAR(NUM) [BINARY] TEXT MEDIUMTEXT TIME DATE TIMESTAMP Tabelle 6.147.6. 255 -2. wobei ‘-‘ jedes nicht numerische Zeichen sein kann setzt einen Datumswert beim Einf¨gen/Updaten einu zelner Felder automatisch auf das Systemdatum. 4. HHMMSS. month) oder Minute (engl.294.648 . Format: YYYY-MM-DD.2: Bedeutung der YMHSDs D H M S Y Tag (engl. year) Christoph Reeg Seite 32 . Wenn mehrere Felder den Typ ‘TIMESTAMP‘ haben.

2 erl¨utert.6.1 sind noch einmal s¨mtliche ‘CREATE TABLE‘-Definitionen aufgef¨hrt. Daraus u o ergibt sich folgender Befehl: CREATE TABLE Mitarbeiter ( MNr INT NOT NULL AUTO_INCREMENT. a Wenn ein Buchstabe mehrmals vorkommt. FOREIGN KEY(VNr) REFERENCES Mitarbeiter(MNr). Ein kleines Beispiel: Es soll eine Tabelle ‘Mitarbeiter‘ erstellt werden.3 SHOW Man kann sich die nun erstellten Tabellen und deren Felder auch ansehen. Die MNr ist Prim¨ra schl¨ssel und soll automatisch um 1 erh¨ht werden. obwohl sie unter MySQL keine Bedeutung haben. Mit SHOW COLUMNS FROM table lassen sich die Felder in der Tabelle ‘table‘ anzeigen. Im Anhang A. wird man eine Fehlermeldung erhalten. so bedeutet das. AbtNr INT NOT NULL. Dazu dient der Befehl SHOW. PRIMARY KEY(MNr). +--------------+ | Tables in cr | Christoph Reeg Seite 33 . Telefonnummer und die Mitarbeiter-Nummer (kurz MNr) zu speichern. Die Syntax lautet wie folgt (nur MySQL): SHOW TABLES oder SHOW COLUMNS FROM table SHOW TABLES zeigt alle angelegten Tabellen an.11) anpassen. Nach unserem obigen CREATE TABLE w¨rde sich folgende Ausgabe ergeben: u mysql> SHOW TABLES. Name VARCHAR(30) NOT NULL. Sie sind hier nur der Ubersichtlichkeit halber eingef¨gt. GebDat DATE. u 6. Der Name ist nicht optional. weil die referenzierte u Tabelle noch nicht existiert. ¨ Die mehrfachen Leerstellen sind optional. VNr INT. Es sind der Vollst¨ndigkeit halber auch s¨mtliche u o a a Fremdschl¨ssel mit angegeben. In diesem Fall kann man die Tabellenstruktur nachtr¨glich a mit ALTER TABLE (6. das Fremdschl¨ssel unu terst¨tzt. als erstes anzulegen. a u die f¨r unser Beispiel ben¨tigt werden. u Wenn man versucht. SQL-Befehle SHOW Die Bedeutung der YMHSDs ist in der Tabelle 6. Telefon VARCHAR(30). die Mitarbeiter-Tabelle bei einem DBMS. Zu jedem Mitarbeiter sind Name. FOREIGN KEY(AbtNr) REFERENCES Abteilung(AbtNr) ). daß es mehrere Stellen gibt.

wie wir sie wieder loswerden. empfiehlt es sich. Die Syntax lautet: DROP TABLE table_name Achtung: Es erfolgt keine Abfrage.) Die Feldnamen k¨nnen weggelassen werden.. wenn in alle Felder etwas eingef¨gt werden o u soll. vor allem aber in Programmen.6. ob du dies wirklich tun willst! Mit der Tabelle werden nat¨rlich auch alle Daten der Tabelle unwiderruflich gel¨scht! u o 6.) ] VALUES (werte.. Die Syntax lautet: u INSERT INTO table_name [ (feld_name.4 DROP TABLE Da wir jetzt wissen. wie wir Tabellen erstellen. welche Felder mit welchen Typen und Attributen in der jeweiligen Tabelle vorhanden sind. In diesem Fall muß man aber die Werte in genau der Reihenfolge eingeben. ‘GebDat‘ und ‘Telefon‘ sind u NULL-Werte zugelassen. u 6.00 sec) In der unteren Tabelle ist zu erkennen.. a Christoph Reeg Seite 34 . ist es auch wichtig zu wissen. In der Regel.. +---------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+----------------+ | MNr | int(11) | | PRI | 0 | auto_increment | | VNr | int(11) | YES | | NULL | | | AbtNr | int(11) | | | 0 | | | Name | varchar(30) | | | | | | GebDat | date | YES | | NULL | | | Telefon | varchar(30) | YES | | NULL | | +---------+-------------+------+-----+---------+----------------+ 5 rows in set (0. daß sich die Reihenfolge der Spalten nicht ¨ndert. Der Prim¨rschl¨ssel ist ‘MNr‘.01 sec) mysql> SHOW COLUMNS FROM Mitarbeiter. Wie man sieht. in der die Felder in der CREATE TABLE Anweisung definiert wurden. weil man sich nie darauf verlassen sollte.. die Feldnamen anzugeben. wurden die Fremda u schl¨ssel ignoriert. Deshalb wollen wir mit dem Befehl INSERT INTO ein paar Daten einf¨gen.. SQL-Befehle DROP TABLE +--------------+ | Mitarbeiter | +--------------+ 1 row in set (0.5 INSERT INTO Tabellen ohne Daten haben eigentlich keinen Sinn. Nur f¨r ‘VNr‘. Dies geschieht mit dem Befehl DROP TABLE.

6. SQL-Befehle

SELECT

Bei den Werten m¨ssen Zeichenketten und Datum in Hochkommata (Anf¨hrungszeiu u chen) stehen, nur f¨r Zahlen gilt das nicht. u In unsere oben erstellte Tabelle sollen folgende Werte eingef¨gt werden: u Name Christoph Reeg junetz.de GebDat 13.5.1979 5.3.1998 Telefon 069/764758

Damit ergeben sich folgende Befehle und Ausgaben (wie man hier bereits sieht, gibt der MySQL-Prompt automatisch die Zeichenfolge ‘->‘ aus, wenn ein mehrzeiliger Befehl eingegeben wird): mysql> INSERT INTO Mitarbeiter (Name,GebDat) -> VALUES (’Christoph Reeg’,’1979-5-13’); Query OK, 1 row affected (0.01 sec) mysql> INSERT INTO Mitarbeiter (Name,GebDat,Telefon) -> VALUES (’junetz.de’,’1998-3-5’,’069/764758’); Query OK, 1 row affected (0.00 sec) Wegen fehlender Fremdschl¨ssel konnten die Mitarbeiter in die DB eingef¨gt werden, u u obwohl wir keine Abteilung f¨r sie angegeben haben. Deshalb muß man immer selbst f¨r u u die Einhaltung der Beziehung(en) sorgen! Um die Datenbasis f¨r unser Beispiel in die DB einzutragen, wird der Befehl noch ein u paarmal benutzt. Diese konkrete Anwendung kann im Anhang A.2 nachgeschlagen werden. Bei den folgenden Kurzbeispielen gehen wir von der Datenbasis unseres Beispiels aus.

6.6 SELECT
Der Befehl SELECT ist der m¨chtigste Befehl in SQL. Die Grund-Syntax lautet: a SELECT [WHERE [GROUP [ORDER [LIMIT [DISTINCT | ALL] select_expression,... FROM tables ... where_definition] BY feld_name,...] BY feld_name [ASC | DESC] ,...] [offset,] rows]

Die k¨rzestm¨gliche SELECT-Anweisung lautet: u o SELECT * FROM table Es sollen z. B. alle Mitarbeiter ausgegeben werden: mysql> select * from Mitarbeiter; +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL |

Christoph Reeg

Seite 35

6. SQL-Befehle

SELECT

| 2 | 1 | 1 | junetz.de | 1998-03-05 | 069/764758 | | 3 | 1 | 1 | Uli | NULL | NULL | | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | +-----+------+-------+----------------+------------+--------------+ 6 rows in set (0.00 sec) mysql> DISTINCT und ALL sind exklusive, optionale Parameter; soll heißen, es kann immer nur einer, muß aber keiner benutzt werden. DISTINCT sorgt daf¨r, daß jede identische u Zeile nur einmal ausgegeben wird. Mit ALL werden die sich wiederholenden Werte auch mehrmals ausgegeben. Ohne Parameter verh¨lt sich das DBMS normalerweise, als ob man a ALL angeben w¨rde. u Es sollen alle Telefonnummern aus der Mitarbeiter-Tabelle ausgeben werden: mysql> SELECT Telefon from Mitarbeiter; +--------------+ | Telefon | +--------------+ | NULL | | 069/764758 | | NULL | | 069/764758 | | 06196/671797 | | 069/97640232 | +--------------+ 6 rows in set (0.01 sec) mysql> SELECT ALL Telefon from Mitarbeiter; +--------------+ | Telefon | +--------------+ | NULL | | 069/764758 | | NULL | | 069/764758 | | 06196/671797 | | 069/97640232 | +--------------+ 6 rows in set (0.00 sec) mysql> SELECT DISTINCT Telefon from Mitarbeiter; +--------------+ | Telefon | +--------------+

Christoph Reeg

Seite 36

6. SQL-Befehle

SELECT

| NULL | | 06196/671797 | | 069/764758 | | 069/97640232 | +--------------+ 4 rows in set (0.05 sec) mysql>

6.6.1 ORDER BY
Mit ORDER BY wird festgelegt, nach welcher Spalte bzw. welchen Spalten sortiert werden soll. Mit ASC 1 werden die Zeilen aufsteigend, mit DESC 2 absteigend sortiert. Ist nichts angegeben, wird aufsteigend sortiert. Als Beispiel alle Mitarbeiter, nach Namen sortiert: mysql> SELECT * from Mitarbeiter ORDER BY Name; +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 2 | 1 | 1 | junetz.de | 1998-03-05 | 069/764758 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | | 3 | 1 | 1 | Uli | NULL | NULL | +-----+------+-------+----------------+------------+--------------+ 6 rows in set (0.00 sec) mysql> SELECT * from Mitarbeiter ORDER BY Name ASC; +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 2 | 1 | 1 | junetz.de | 1998-03-05 | 069/764758 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | | 3 | 1 | 1 | Uli | NULL | NULL | +-----+------+-------+----------------+------------+--------------+ 6 rows in set (0.01 sec) mysql> SELECT * from Mitarbeiter ORDER BY Name DESC; +-----+------+-------+----------------+------------+--------------+
1 2

engl. ascending engl. descending

Christoph Reeg

Seite 37

6. SQL-Befehle

SELECT

| MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 3 | 1 | 1 | Uli | NULL | NULL | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 2 | 1 | 1 | junetz.de | 1998-03-05 | 069/764758 | | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | +-----+------+-------+----------------+------------+--------------+ 6 rows in set (0.00 sec) mysql> Als letztes soll nach dem Geburtsdatum sortiert werden. mysql> SELECT * from Mitarbeiter ORDER BY GebDat; +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 3 | 1 | 1 | Uli | NULL | NULL | | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 2 | 1 | 1 | junetz.de | 1998-03-05 | 069/764758 | +-----+------+-------+----------------+------------+--------------+ 6 rows in set (0.01 sec) mysql> Die ersten vier Mitarbeiter haben kein Geburtsdatum eingetragen. Um sie dennoch irgendwie zu sortieren, ist bei ihnen ein zweites Sortierkriterium notwendig. Das kann einfach mit einem Komma getrennt hinter ORDER BY geschrieben werden. Um zum Beispiel nach Geburtsdatum und, wenn das nicht eindeutig ist, dann nach Namen zu sortieren, ist folgende Anweisung notwendig: mysql> SELECT * from Mitarbeiter ORDER BY GebDat,Name; +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | | 3 | 1 | 1 | Uli | NULL | NULL | | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 2 | 1 | 1 | junetz.de | 1998-03-05 | 069/764758 | +-----+------+-------+----------------+------------+--------------+

Christoph Reeg

Seite 38

6. SQL-Befehle

SELECT

6 rows in set (0.00 sec) mysql>

6.6.2 GROUP BY
Die GROUP BY-Anweisung wird nur in Verbindung mit den Gruppenfunktionen aus Kapitel 6.7.5 benutzt, um mehrere Tupel mit identischen Attributen zu Gruppen zusammenzufassen. Ein kleines Beispiel: Es soll ausgegeben werden, wie viele Mitarbeiter in den jeweiligen Abteilungen arbeiten. mysql> SELECT count(*), AbtNr from Mitarbeiter GROUP BY AbtNr; +----------+-------+ | count(*) | AbtNr | +----------+-------+ | 3 | 1 | | 2 | 2 | | 1 | 3 | +----------+-------+ 3 rows in set (0.00 sec) mysql> Die sechs Tupel (Datens¨tze), die wir in der Mitarbeiter-Tabelle haben, werden zu drei a Gruppen zusammengefaßt; anschließend wird die Anzahl der Tupel pro Gruppe ausgeben. Eigentlich d¨rfen in der select_expression nur Spalten angegeben werden, die in u GROUP BY auftauchen, MySQL ignoriert dies allerdings. Folgende Anweisung w¨re eigenta lich unzul¨ssig, zudem ist sie v¨llig sinnlos - was besagt schon die Spalte ‘Name‘? a o mysql> SELECT Name,count(*),AbtNr from Mitarbeiter GROUP BY AbtNr; +----------------+----------+-------+ | Name | count(*) | AbtNr | +----------------+----------+-------+ | junetz.de | 3 | 1 | | Maier | 2 | 2 | | Christoph Reeg | 1 | 3 | +----------------+----------+-------+ 3 rows in set (0.00 sec) mysql>

6.6.3 LIMIT
Mit LIMIT [offset,] rows kann angegeben werden, wie viele Zeilen man maximal von der SELECT-Anweisung zur¨ckgeliefert haben will. Mit ‘offset‘ kann man festlegen, ab u welcher Zeile angefangen werden soll. Ohne Angaben wird 0 angenommen. Mit ‘rows‘ legt man fest, wie viele Zeilen man maximal ausgegeben haben m¨chte. o

Christoph Reeg

Seite 39

Mitarbeiter.7 werden die Funktionen ausf¨hrlich beschrieben.6. Damit wird einfach alles angezeigt. was angezeigt werden soll.de | 069/764758 | | Uli | NULL | | JCP | 069/764758 | | Maier | 06196/671797 | | Meier | 069/97640232 | +----------------+--------------+ 6 rows in set (0. da nicht zu umst¨ndlich.00 sec) mysql> Christoph Reeg Seite 40 .4 select expression F¨r select_expression muß eingesetzt werden.Telefon from Mitarbeiter. In Kapitel 6. es k¨nnen o dabei auch sog.10. mysql> select * from table LIMIT 5. mysql> select * from table LIMIT 0. Im einfachsten u Fall ist das ein ‘*‘.5. Aliase verwendet werden.6. # gibt die Zeilen 6-15 zur¨ck u # gibt die ersten 5 Zeilen zur¨ck u # dasselbe nochmal 6. gefolgt von einem Punkt. weil mehrere Tabellen angegeben wurden. vorangestellt werden. SQL-Befehle SELECT mysql> select * from table LIMIT 5. Die beiden Ausgaben sind ¨quivalent. ist die erstere allerdings eher empfehlenswert. muß der Tabellenname.Name. Solange nur aus a einer Tabelle ausgelesen wird. a mysql> select Name.de | 069/764758 | | Uli | NULL | | JCP | 069/764758 | | Maier | 06196/671797 | | Meier | 069/97640232 | +----------------+--------------+ 6 rows in set (0. Im Normalfall werden die ben¨tigten Spalten durch Kommas getrennt angegeben. Neben den reinen Spaltenwerten k¨nnen auch Werte. +----------------+--------------+ | Name | Telefon | +----------------+--------------+ | Christoph Reeg | NULL | | junetz. u Als Beispiel sollen der Mitarbeitername und die Telefonnummer ausgegeben werden. wie man unschwer erkennen kann. Soo bald die Spaltennamen nicht mehr eindeutig sind. Telefon from Mitarbeiter. Mehr dazu weiter unten. die aus den Spaltenwerten berecho net oder durch sonstige Funktionen erstellt wurden.02 sec) mysql> select Mitarbeiter. +----------------+--------------+ | Name | Telefon | +----------------+--------------+ | Christoph Reeg | NULL | | junetz. ausgegeben werden.

AbtNr = 1.AbtNr -> FROM Mitarbeiter M -> WHERE M.01 sec) mysql> 6. Aliase werden verwendet.6. mysql> select M. 6. Man kann sowohl f¨r Spalten als auch f¨r u u ” Tabellen Aliase definieren.00 sec) mysql> select Mitarbeiter.Name. weil sie in der Regel k¨rzer sind als der Spaltennau me. welches in der ersten Zeile bei der select_expression benutzt wird. braucht man Spalten-Aliase. Auf den a ersten Blick mag es vielleicht egal sein.6. Der einzige Unterschied liegt in den ersten beiden Zeilen.6.Name.Telefon.5 Alias Alias bedeutet so viel wie ein anderer Name“.1 Tabellen-Alias Tabellen-Aliase k¨nnen sowohl bei der select_expression als auch bei der ‘wheo re definition‘ zur eindeutigen Spaltenbeschreibung anstelle des Tabellennamens verwendet werden. Mitarbeiter.Telefon. daß erstere o k¨rzer ist. +-----------+------------+-------+ | Name | Telefon | AbtNr | +-----------+------------+-------+ | junetz. Sp¨ter in Verbindung mit a Christoph Reeg Seite 41 . Die folgenden zwei Anweisungen sind v¨llig identisch.5. -> Mitarbeiter. M.de | 069/764758 | 1 | | Uli | NULL | 1 | | JCP | 069/764758 | 1 | +-----------+------------+-------+ 3 rows in set (0. SQL-Befehle SELECT 6.AbtNr -> FROM Mitarbeiter -> WHERE Mitarbeiter.de | 069/764758 | 1 | | Uli | NULL | 1 | | JCP | 069/764758 | 1 | +-----------+------------+-------+ 3 rows in set (0. Aliase werden bei tables mit einer Leerstelle getrennt hinter dem Tabellennamen eingegeben. wie die Spalten heißen. abgesehen davon. +-----------+------------+-------+ | Name | Telefon | AbtNr | +-----------+------------+-------+ | junetz. Im ersten Beiu spiel wird bei der FROM-Anweisung ein Alias definiert.2 Spalten-Alias ¨ Wenn man die Uberschrift der Spalten ¨ndern will. M.AbtNr = 1.6.5.

6.00 sec) mysql> Das einzige st¨rende ist. u u Christoph Reeg Seite 42 . 6. wenn o o a ” sie z.6.7.00 sec) mysql> SELECT count(*) AS Anzahl -> FROM Mitarbeiter. SQL-Befehle SELECT PHP ist das allerdings wichtig und sobald Funktionen in der Abfrage verwendet werden. +--------+ | Anzahl | +--------+ | 6 | +--------+ 1 row in set (0. welche Bedingungen erf¨llt sein m¨ssen. B. sind die Spalten¨berschriften auch nicht mehr so sch¨n. o mysql> SELECT count(*) -> FROM Mitarbeiter. Viel sch¨ner w¨re es doch. u o Zum Umbenennen der Spalten wird einfach hinter den Spaltennamen bzw. Dazu wird eine Funktion ben¨tigt o (siehe Kapitel 6. Ein kleines Beispiel: Es soll die Anzahl der Mitarbeiter ausgegeben werden. Ausdruck der Aliasname geschrieben. das soll uns aber nicht weiter st¨ren). Alternativ kann auch AS aliasname benutzt werden. ist das AS optional.6 where definition Da es nicht immer sinnvoll ist. kann man uber die ‘where definition‘ ¨ angeben. +----------+ | count(*) | +----------+ | 6 | +----------+ 1 row in set (0. daß die Spalte count(*)“ heißt. Anzahl“ heißen w¨rde: u ” mysql> SELECT count(*) Anzahl -> FROM Mitarbeiter. damit die Zeile ausgegeben wird. alle Zeilen auszugeben.00 sec) mysql> Wie man unschwer erkennen kann. +--------+ | Anzahl | +--------+ | 6 | +--------+ 1 row in set (0.

SQL-Befehle SELECT ¨ Die ‘where definition‘ wird auch beim L¨schen (DELETE) und Andern (UPDATE) von o ausgew¨hlten Datens¨tzen gebraucht. AbtNr -> FROM Mitarbeiter -> WHERE NOT (AbtNr < 3). Als Operatoren stehen die Vergleichsoperatoren sowie die Operatoren ‘LIKE‘. +----------------+-------+ | Name | AbtNr | +----------------+-------+ | Christoph Reeg | 3 | +----------------+-------+ 1 row in set (0. Bei Vergleichen mit Strings u (=VARCHAR) wird im Normalfall nicht auf die Groß-/Kleinschreibung geachtet. AbtNr -> FROM Mitarbeiter -> WHERE AbtNr > 2. Die Reihenfolge der Teilbedingungen kann durch Klammern beeinflußt werden. einer weiteren Spalte oder einer Funktion.3: Verf¨gbare Vergleichsoperatoren in SQL u Operator = <> oder != > < >= <= Bedeutung gleich ungleich gr¨ßer o kleiner gr¨ßer gleich o kleiner gleich verneinender Operator <> bzw. bei denen die Abteilungsnummer gr¨ßer o als 2 ist: mysql> SELECT Name. die mit AND und OR verkn¨pft u werden m¨ssen.00 sec) Christoph Reeg Seite 43 . a a Eine Bedingung kann aus mehreren Teilbedingungen. Schreibfaule k¨nnen an Stelle o o von NOT auch einfach ! verwenden. Tabelle 6. das Ergebnis ist dasselbe. +----------------+-------+ | Name | AbtNr | +----------------+-------+ | Christoph Reeg | 3 | +----------------+-------+ 1 row in set (0.6. so muß beim Anlegen der Tabelle bei VARCHAR die Option BINARY angegeben werden. Alle Vergleichsoperatoren aus Tabelle 6. != = <= >= < > Es sollen alle Mitarbeiter ausgegeben werden. Wenn man jedoch unterscheiden will.3 stehen zur Verf¨gung. Die Teilbedingungen k¨nnen auch mit NOT verneint werden. bestehen. Eine Teilbedingung besteht aus einem Spaltennamen. ‘BETWEEN‘ und ‘IN‘ zur Auswahl.00 sec) mysql> SELECT Name. einem u Operator sowie entweder einer Konstanten.

VNr -> FROM Mitarbeiter -> WHERE AbtNr = 1 -> AND VNr = 1. VNr -> FROM Mitarbeiter -> WHERE AbtNr = 1 -> OR VNr IS NULL. AbtNr. die keinen Vorgesetzten haben oder der Abteilung 1 angeh¨ren: o mysql> SELECT Name. mysql> SELECT Name.de | 1 | 1 | | Uli | 1 | 1 | Christoph Reeg Seite 44 . +----------------+-------+------+ | Name | AbtNr | VNr | +----------------+-------+------+ | Christoph Reeg | 3 | NULL | | junetz.6.02 sec) mysql> Es sollen alle Mitarbeiter ausgegeben werden. AbtNr.de | 1 | 1 | | Uli | 1 | 1 | | JCP | 1 | 3 | +----------------+-------+------+ 4 rows in set (0. AbtNr. die der Abteilung 1 angeh¨ren und als o Vorgesetztennummer ebenfalls die 1 haben.de | 1 | 1 | | Uli | 1 | 1 | +-----------+-------+------+ 2 rows in set (0.01 sec) mysql> SELECT Name. +-----------+-------+------+ | Name | AbtNr | VNr | +-----------+-------+------+ | junetz. VNr -> FROM Mitarbeiter -> WHERE NOT (AbtNr <> 1) -> OR VNr IS NULL. SQL-Befehle SELECT mysql> Es sollen alle Mitarbeiter ausgegeben werden. +----------------+-------+------+ | Name | AbtNr | VNr | +----------------+-------+------+ | Christoph Reeg | 3 | NULL | | junetz.

+----------------+-------+------+ | Name | AbtNr | VNr | +----------------+-------+------+ | Christoph Reeg | 3 | NULL | | junetz.00 sec) mysql> ¨ Bei der Uberpr¨fung auf keinen Vorgesetzten ist IS NULL verwendet worden. verneint.de | 1 | 1 | | Uli | 1 | 1 | | JCP | 1 | 3 | +----------------+-------+------+ 4 rows in set (0. Statt dessen ist nur IS NULL oder. auf diese L¨sung zu kommen. VNr -> FROM Mitarbeiter -> WHERE NOT (AbtNr <> 1 AND VNr IS NOT NULL). VNr -> FROM Mitarbeiter -> WHERE NOT (AbtNr < 1 OR AbtNr > 1) -> OR VNr IS NULL. o o Da der erste Korrekturleser mir das nicht glauben wollte. VNr -> FROM Mitarbeiter -> WHERE (AbtNr <= 1 AND AbtNr >= 1) -> OR VNr IS NULL.de | 1 | 1 | | Uli | 1 | 1 | | JCP | 1 | 3 | +----------------+-------+------+ 4 rows in set (0. hier noch ein paar M¨glichkeiten o mehr: mysql> SELECT Name.00 sec) mysql> SELECT Name. IS NOT NULL m¨glich. AbtNr. +----------------+-------+------+ | Name | AbtNr | VNr | +----------------+-------+------+ | Christoph Reeg | 3 | NULL | | junetz. o Es gibt mit Sicherheit noch 1001 andere M¨glichkeiten. da bei Veru gleichen mit NULL-Werten nicht mit den normalen Operatoren gearbeitet werden kann.6. SQL-Befehle SELECT | JCP | 1 | 3 | +----------------+-------+------+ 4 rows in set (0. AbtNr. AbtNr.00 sec) mysql> SELECT Name. +----------------+-------+------+ | Name | AbtNr | VNr | +----------------+-------+------+ Christoph Reeg Seite 45 .

VNr -> FROM Mitarbeiter -> WHERE POW(13.de | 1 | 1 | | Uli | 1 | 1 | | JCP | 1 | 3 | +----------------+-------+------+ 4 rows in set (0. wenn mit NULL-Werten gerechnet o wird: Das Ergebnis ist NULL. wird festo stellen.02 sec) mysql> Es sind noch nicht 1001 M¨glichkeiten.42) IS NULL.AbtNr) = 13 -> OR POW(VNr. AbtNr. Bei der letzten M¨glichkeit sieht man. +----------------+-------+------+ | Name | AbtNr | VNr | +----------------+-------+------+ | Christoph Reeg | 3 | NULL | | junetz.00 sec) mysql> SELECT Name.6. in Kapitel 6.de | 1 | 1 | | Uli | 1 | 1 | | JCP | 1 | 3 | +----------------+-------+------+ 4 rows in set (0. VNr -> FROM Mitarbeiter -> WHERE AbtNr & 1 = 1 -> OR VNr IS NULL. Christoph Reeg Seite 46 . werde ich daran o weiterarbeiten . aber wenn ich vieeel Zeit habe.-). AbtNr.7 werden diese noch genauer beschrieben. +----------------+-------+------+ | Name | AbtNr | VNr | +----------------+-------+------+ | Christoph Reeg | 3 | NULL | | junetz.de | 1 | 1 | | Uli | 1 | 1 | | JCP | 1 | 3 | +----------------+-------+------+ 4 rows in set (0. daß dort unbekannte Befehle verwendet werden. SQL-Befehle SELECT | Christoph Reeg | 3 | NULL | | junetz. Wer sich die beiden letzten L¨sungen genau angesehen hat.01 sec) mysql> SELECT Name. was passiert.

Allerdings ist unbekannt.6.6. ” ob er sich mit ei“ oder ai“ schreibt. wenn man in Textfeldern im Suchmuster Platzhalter oder Jokerzeichen (auch o regul¨re Ausdr¨cke3 genannt) verwenden will.1 LIKE Immer dann. +-------+--------------+ | Name | Telefon | +-------+--------------+ | Maier | 06196/671797 | +-------+--------------+ 1 row in set (0. Es sollen also alle M¨glichkeiten ausgegeben werden. schicke mir bitte eine E-Mail an die Adresse dsp@reeg. o ” ” mysql> SELECT Name -> FROM Mitarbeiter -> WHERE Name LIKE ’M_ier’.6. 3 engl. Ein Beispiel zur Verdeutlichung: Es sollen alle Mitarbeiter ausgegeben werden. Telefon -> FROM Mitarbeiter -> WHERE Telefon LIKE ’%96/%’. Falls du eine M¨glichkeit findest.00 sec) mysql> Es soll ein Mitarbeiter mit Namen Meier“ ausgegeben werden. ich bevorzuge o ubrigens den Operator LIKE. bei denen die Telefon-Vorwahl auf 96“ ” endet.net.6. ¨ mysql> SELECT Name.6. das mit Vergleichsoperatoren (und ohne Funktioo nen) zu l¨sen. zum Beispiel den BETWEENOperator.2 BETWEEN Neben dem LIKE-Operator gibt es auch noch andere. SQL-Befehle SELECT 6. k¨nnen die Vergleichsoperatoren nicht vera u wendet werden. +-------+ | Name | +-------+ | Maier | | Meier | +-------+ 2 rows in set (0. gibt es zwei Jokerzeichen: % DOS-Pendant: * steht f¨r eine beliebige (auch 0) Anzahl beliebiger Zeichen u DOS-Pendant: ? steht f¨r genau ein beliebiges Zeichen u 6. die zwischen a dem oberen und unteren Wert liegen. Er tut das.00 sec) mysql> Wie wir sehen.: regular expressions Christoph Reeg Seite 47 . was man von ihm erwartet: er w¨hlt alle Spalten aus.

+-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | +-----+------+-------+----------------+------------+--------------+ 3 rows in set (0. Zur Verdeutlichung: Es sollen alle Mitarbeiter ausgegeben werden.01 sec) mysql> Man kann es aber noch etwas vereinfachen: mysql> SELECT * FROM Mitarbeiter -> WHERE AbtNr BETWEEN 2 AND 5. deren Abteilungs-Nummer zwia schen 2 und 5 liegt. Datumsspalten und numerischen Spalten verwendet werden. Mit dem bisherigen Wissen w¨rde man folgende Anweisung nehmen: u mysql> SELECT * FROM Mitarbeiter -> WHERE AbtNr >= 2 AND AbtNr <=5.6.de | 1998-03-05 | 069/764758 | Christoph Reeg Seite 48 . wenn man nicht mit einem einzelnen Wert. deren Telefonnummer 06196/671797“ oder 069/764758“ ist.3 IN Der Operator IN schließlich wird benutzt. 6.6. +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | +-----+------+-------+----------------+------------+--------------+ 3 rows in set (0. SQL-Befehle SELECT Beispiel: Es sollen alle Mitarbeiter ausgew¨hlt werden. Mit den bisherigen Operatoren w¨rde sich folgende u ” ” Abfrage ergeben: mysql> SELECT * FROM Mitarbeiter -> WHERE Telefon = ’06196/671797’ OR Telefon = ’069/764758’. +-----+------+-------+-----------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+-----------+------------+--------------+ | 2 | 1 | 1 | junetz.6.00 sec) mysql> BETWEEN kann bei Textspalten. sondern mit einer Wertemenge vergleichen will.

. +-----+------+-------+-----------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+-----------+------------+--------------+ | 2 | 1 | 1 | junetz. Datumsspalten und numerischen Spalten verwendet werden.6. Als Beispiel sollen alle Mitarbeiter ausgegeben werden. hier das ganze nochmal mit dem IN-Operator: a u mysql> SELECT * FROM Mitarbeiter -> WHERE Telefon IN (’06196/671797’. SQL-Befehle SELECT | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | +-----+------+-------+-----------+------------+--------------+ 3 rows in set (0. deren Telefonnummer nicht 06196/671797“ oder 069/97640232“ ist.de | 1998-03-05 | 069/764758 | | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | +-----+------+-------+-----------+------------+--------------+ 3 rows in set (0.’069/764758’). aber da diese M¨glichkeit bei großen Mengen von Werten sehr o umst¨ndlich und un¨bersichtlich wird.00 sec) mysql> SELECT * FROM Mitarbeiter -> WHERE Telefon NOT IN (’06196/671797’.’069/764758’). +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 3 | 1 | 1 | Uli | NULL | NULL | Christoph Reeg Seite 49 . a mysql> SELECT * FROM Mitarbeiter -> WHERE NOT (Telefon = ’06196/671797’ OR Telefon = ’069/764758’). Die Verneinung des IN-Operators ist NOT IN. .00 sec) mysql> Der IN-Operator kann bei Textspalten. +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 3 | 1 | 1 | Uli | NULL | NULL | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | +-----+------+-------+----------------+------------+--------------+ 3 rows in set (0. Erst ” ” umst¨ndlich mit OR und dann elegant.00 sec) mysql> Das funktioniert zwar.

den Betrag von allen Stellenanzahlen a auf einmal zu berechnen.1 Mathematische Funktionen Es k¨nnen nicht nur Spaltennamen angegeben werden.6. Grades) schneidet nach n Kommastellen von x ab Tabelle 6.00 sec) mysql> 6. zum einen die sog.5 sind sie der Vollst¨ndigkeit halber noch einmal aufgef¨hrt. w¨hrend die Gruppenfunktionen immer auf a eine Gruppe von Zeilen angewendet werden.2 Logische Operatoren Die logischen bzw. Es w¨re zum Beispiel Schwachsinn.7. SQL-Befehle Funktionen | 6 | 5 | 2 | Meier | NULL | 069/97640232 | +-----+------+-------+----------------+------------+--------------+ 3 rows in set (0. Eine Auswahl der mathematischen Funktionen ist in Tabelle 6.n) SQRT() TRUNCATE(x.6. booleschen Operatoren haben wir bereits im Kapitel 6. u +-*/ % ABS() COS() DEGREES() MOD() PI() POW(X.Y) RAND() ROUND() ROUND(x.4 aufgef¨hrt. Es gibt zwei Arten von Funktionen.4: Mathematische Funktionen in SQL 6. sondern auch mathematische Reo chenoperationen mit Spalten und/oder Konstanten. a u Christoph Reeg Seite 50 . 6. bei der Summe paßt das schon eher.6 kennengelernt. In Tabelle 6. zu versuchen. Singlerow” Funktionen werden auf jede Zeile angewendet.7 Funktionen Bei select_expression und where_expression k¨nnen neben Konstanten und Spalo tenwerten auch Funktionen verwendet werden.n) addieren/subtrahieren/multiplizieren/dividieren modulo (ganzzahliger Rest) Betrag von Cosinus in rad Umrechnung von rad in deg (Grad) Modulo (ganzzahliger Rest) die Zahl Pi rechnet X hoch Y aus liefert eine Zufallszahl zwischen 0 und 1 rundet Wert rundet Wert von x auf n Stellen Wurzel (2. singlerow“-Funktionen und zum anderen die Gruppenfunktionen.7.

u schneidet n Buchstaben von ‘str‘ ab und gibt diese zur¨ck u l¨scht alle Leerzeichen am Anfang von ‘str‘ o verschl¨sselt den Klartext ‘str‘ u dreht ‘str‘ um. NOT NULL gibt NULL zur¨ck. wenn u eines der Argumente weder 0 noch NULL ist (sonst R¨ckgabe 0). Die Tau bellen sind nicht vollst¨ndig! a | & bitweises ODER bitweises UND Tabelle 6. Alle anderen Zeichen werden so wie sie sind ausgegeben. wenn u das Argument 0 ist (sonst R¨ckgabe 0).7: String-Funktionen in SQL 6. wenn u alle Argumente weder 0 noch NULL sind (sonst R¨ckgabe 0).7.6 und 6. teilweise praktische Funktionen aufgef¨hrt. Teilweise ist es praktischer. mit PHP zu formatieren. Wird genau dann wahr (gibt 1 zur¨ck). weil man dann die Formatierungsanweisung in der SQL-Abfrage hat und mit PHP nur ausgeben muß. In PHP gibt es auch eine Datum-Formatierungsfunktion. mit Hilfe der a MySQL-Funktion das Datum zu formatieren. u u logisches UND. u logisches ODER. u Tabelle 6. Die Funktion erwarten zwei Parameter.4 Datums-Funktionen Mit Hilfe von DATE_FORMAT kann man Datumswerte aus Tabellen so formatieren. ist h¨ufig egal.n) LTRIM(str) PASSWORD(str) REVERSE(str) LCASE(str) LOWER(str) UCASE(str) UPPER(str) Tabelle 6.7. Sobald ein Argument NULL ist. SQL-Befehle Funktionen NOT ! AND && OR || logisches NOT.5: Logische Funktionen in SQL 6.6.3 Sonstige Funktionen In Tabelle 6. der durch Zusammenf¨hren der Aru u gumente entstanden ist. letzter Buchstabe ist dann am Anfang Wandelt ‘str‘ in Kleinbuchstaben und gibt das Ergebnis zur¨ck u Wandelt ‘str‘ in Großbuchstaben und gibt das Ergebnis zur¨ck u LEFT(str.9) werden durch die entsprechenden Werte ersetzt. . Wird genau dann wahr (gibt 1 zur¨ck). zum a anderen den Formatierungs-String. Zum einen das Datumsfeld. d. str2. Die Formatierungszeichen (siehe Tabelle 6.. wird NULL zur¨ckgegeben.6: Bit-Funktionen in SQL CONCAT(str1. Wird genau dann wahr (gibt 1 zur¨ck). wie man sie gerne h¨tte. Andererseits kann es aber auch praktischer sein.. wenn man zum Beispiel dasselbe Datum an Christoph Reeg Seite 51 .h. Ob man nun mit der MySQLFunktion das Datum formatiert und dann mit PHP ausgibt oder mit Hilfe der PHPFunktion das Datum formatiert.7 sind sonstige.) Gibt den String zur¨ck.

B. mysql> SELECT count(GebDat) -> FROM Mitarbeiter. .1. f¨ngt a die Woche mit Montag an.27 sec) mysql> Christoph Reeg Seite 52 . Gruppeno funktionen heißen so. 6. 1. Beispiel: Es soll ausgegeben werden. 7 = Samstag) Gibt den Tag des Monats zur¨ck u Gibt den Tag im Jahr zur¨ck u Gibt die Woche des Datums zur¨ck.8: Datum-Funktionen in SQL mehreren Stellen auf der Seite verschieden formatiert haben will. 2 = Montag. allerdings hat dies im Normalfall wenig Sinn.6. . wenn der Spaltenname in der GROUP BY-Anweisung steht. In Tabelle 6.first) MONTH(date) YEAR(date) DATE FORMAT(date. u Tabelle 6.10 sind ein Teil der verf¨gbaren Gruppenfunktionen aufgef¨hrt. u u F¨r ‘expr‘ ist immer der Name der Spalte einzusetzen.5 Gruppenfunktionen Es k¨nnen aber auch die sogenannten Gruppenfunktionen verwendet werden. . SQL-Befehle Funktionen DAYOFWEEK(date) DAYOFMONTH(date) DAYOFYEAR(date) WEEK(date) WEEK(date. Ist ‘first‘ z. Wie gesagt. weil sie immer auf eine Gruppe von Tupeln (Datens¨tzen) angewena det werden. u Wenn ‘first‘ nicht angegeben wird bzw.format) UNIX TIMESTAMP(date) Gibt den Wochentag-Index des Datums zur¨ck (1 u = Sonntag. es kommt auf den Einzelfall und die Vorlieben des Programmierers an. Die einzige Ausnahme ist dann gegeben. Gibt den Monat zur¨ck u Gibt das Jahr zur¨ck u Formatiert das Datum date entsprechend dem ubergebenen format String.7.1970) des Datums date zur¨ck. mit der diese Operation erfolgen u soll. ¨ Gibt den Unix-Timestamp (Sekunden seit dem 1. f¨ngt a die Woche mit Sonntag an. wie viele Mitarbeiter ihren Geburtstag angegeben haben. 0 ist. MySQL sieht das etwas lockerer und gibt keine Fehlermeldung bei Verwendung von Spaltennamen in der select_expression aus. +---------------+ | count(GebDat) | +---------------+ | 2 | +---------------+ 1 row in set (0. . In Verbindung mit Gruppenfunktionen darf streng genommen kein Spaltenname mehr mit in der select_expression stehen.

.23) Stunde (00 .59) Minuten (00 . numerisch (1 . Formatierungen f¨r DATE FORMAT o u COUNT(expr) AVG(expr) MIN(expr) MAX(expr) SUM(expr) z¨hlt die Zeilen. . Tag der Woche (00 .6.52) Monatsname Monat.12) Jahr (4stellig) Jahr (2stellig) Uhrzeit (24 Std. mit Sonntag als 1. 6=Samstag) Tag des Monats (00 .12) Stunde (00 .10: Gruppenfunktionen in SQL Christoph Reeg Seite 53 .31) Tag des Monats (0 .52) Woche.366) Woche.9: m¨gl. deren Werte ungleich NULL sind a durchschnittlicher Wert kleinster Wert gr¨ßter Wert o Summe Tabelle 6.31) Tag im Jahr (001 .59) Sekunden (00 .12) Stunde (0 . .59) Stunde (00 . Tag der Woche (00 . .12) Monat. mit Montag als 1. SQL-Befehle Funktionen %W %w %d %e %j %U %u %M %m %c %Y %y %T %S %s %i %H %k %h %I %l %% Wochentag Tag in der Woche (0 = Sonntag. numerisch (01 .23) Stunde (0 .) (hh:mm:ss) Sekunden (00 .12) % Tabelle 6.

o u Hierbei aber nicht die Abteilungsnummer. m.Name.AbtNr -> FROM Mitarbeiter m. wollen wir mal ein paar Tao bellen miteinander verbinden. a. w¨rden wir folgende Abfrage starten: u mysql> SELECT m. geh¨ren nur die Mitarbeiter o o und Abteilungen zusammen. Eine entsprechend modifizierte Abfrage w¨rde demnach folgendermaßen lauten: u u mysql> SELECT m.Name.Name. a. m. Wie wir oben jedoch unschwer erkennen k¨nnen.07 sec) mysql> 6. Nach dem. obwohl sie eigentlich zusama mengeh¨ren.AbtNr -> FROM Mitarbeiter m.de | 1 | Chefetage | 3 | | Uli | 1 | Chefetage | 3 | | JCP | 1 | Chefetage | 3 | | Maier | 2 | Chefetage | 3 | | Meier | 2 | Chefetage | 3 | +----------------+-------+------------+-------+ 18 rows in set (0.1 Equi-Join Die obige Abfrage ergibt allerdings nicht ganz das erw¨nschte Resultat. a.8 Joins Nachdem wir jetzt die Tabellen perfekt abfragen k¨nnen. SQL-Befehle Joins 6.6.Name. deshalb hatten wir diese auch ¨ eingef¨gt.de | 1 | Verwaltung | 2 | | Uli | 1 | Verwaltung | 2 | | JCP | 1 | Verwaltung | 2 | | Maier | 2 | Verwaltung | 2 | | Meier | 2 | Verwaltung | 2 | | Christoph Reeg | 3 | Chefetage | 3 | | junetz. Zum Beispiel w¨rde ich gerne alle Mitarbeiter mit deren Abteilungen sehen.AbtNr.AbtNr.8. sondern den Namen der Abteilung. Abteilung a. was so viel bedeutet wie jeder a ” mit jedem“. Bei dieser Art u der Abfrage entsteht n¨mlich das kartesische Produkt. deren AbtNr ubereinstimmen. was wir bis jetzt wissen.4) befinden sich einige Informationen n¨mlich in verschiedenen Tabellen. a.de | 1 | EDV | 1 | | Uli | 1 | EDV | 1 | | JCP | 1 | EDV | 1 | | Maier | 2 | EDV | 1 | | Meier | 2 | EDV | 1 | | Christoph Reeg | 3 | Verwaltung | 2 | | junetz. Abteilung a Christoph Reeg Seite 54 . Nach unserer Normalisierung (siehe Kapitel 4. +----------------+-------+------------+-------+ | Name | AbtNr | Name | AbtNr | +----------------+-------+------------+-------+ | Christoph Reeg | 3 | EDV | 1 | | junetz.

6.Name. +----------------+-------+------------+-------+ | Name | AbtNr | Name | AbtNr | +----------------+-------+------------+-------+ | junetz. m.2 Self-Join So. ist es auch m¨glich.6. werden (n-1) WHERE-Bedingungen ben¨tigt. Es ist zwar sch¨n. u ¨ Uber die AbtNr entsteht die Verbindung zwischen den beiden Tabellen. eine o Tabelle mit sich selbst zu verbinden. equal. v.MNr -> FROM Mitarbeiter m. in deutsch: gleich.5). Falls bei der Verkn¨pfung von mehreren Tabellen nicht das gew¨nschte Ergebnis erscheint. Gleichheit u deutsch: Verkn¨pfung u Christoph Reeg Seite 55 . daß man zu jedem Mitarbeiter die Mitarbeiter-Nummer seines o Vorgesetzten abrufen kann. da die Namen nicht eindeutig sind.VNr. Mitarbeiter v -> WHERE m.de | 1 | Christoph Reeg | 1 | | Uli | 1 | Christoph Reeg | 1 | | Maier | 1 | Christoph Reeg | 1 | | JCP | 3 | Uli | 3 | | Meier | 5 | Maier | 5 | +-----------+------+----------------+-----+ 4 5 Kurzform f¨r engl.de | 1 | EDV | 1 | | Uli | 1 | EDV | 1 | | JCP | 1 | EDV | 1 | | Maier | 2 | Verwaltung | 2 | | Meier | 2 | Verwaltung | 2 | | Christoph Reeg | 3 | Chefetage | 3 | +----------------+-------+------------+-------+ 6 rows in set (0. Notwendig ist dies in unserem Beispiel beim Vorgesetzten. wurden Aliase verwendet (siehe Kapitel 6.8. aber der Name w¨re doch noch viel sch¨ner: a o mysql> SELECT m.MNr. wie man mehrere Tabellen miteinander verbinden kann. Um nicht jedes Mal den kompletten Tabellennamen benutzen zu m¨ssen.6. In solchen F¨llen kann man einfach nachz¨hlen: Wenn n Tabellen miteinander verkn¨pft a a u werden sollen. SQL-Befehle Joins -> WHERE m. +-----------+------+----------------+-----+ | Name | VNr | Name | MNr | +-----------+------+----------------+-----+ | junetz.AbtNr. fehlt h¨ufig u u a eine WHERE-Bedingung. v.Name.00 sec) mysql> Vor den Spaltennamen muß jeweils die entsprechende Tabelle genannt werden. so daß bei einigen Tabellen das kartesische Produkt entsteht. o Diese Art der Verbindung wird Equi4 -Join5 genannt.VNr = v.AbtNr = a.

Der einzige Sch¨nheitsfehler bei der Abfrage ist. daß der Mitarbeiter Christoph Reeg“ o ” nicht aufgelistet wird.de | 1 | Christoph Reeg | 1 | | Uli | 1 | Christoph Reeg | 1 | | JCP | 3 | Uli | 3 | | Maier | 1 | Christoph Reeg | 1 | | Meier | 5 | Maier | 5 | +----------------+------+----------------+------+ 6 rows in set (0. Um nachher die Spalten eindeutig bezeichnen zu k¨nnen. v. a 6.03 sec) mysql> 6 Wer vergeßlich ist. Um beim oben gezeigten Beispiel zu bleiben: Es sollen alle Mitarbeiter mit deren Vorgesetzten (sofern vorhanden) angezeigt werden.MNr -> FROM Mitarbeiter m LEFT JOIN Mitarbeiter v ON m. Dumm ist es trotzdem.Name. gleich sein. o Die Syntax unter MySQL lautet (wo sonst die Tabellennamen stehen): haupttabelle LEFT JOIN tabelle2 ON bedingung oder haupttabelle LEFT JOIN tabelle2 USING (spalte) Bei der unteren M¨glichkeit m¨ssen die Spaltennamen in den beiden Tabellen. muß die obere Syntax benutzt werden.6. wenn nicht zu jedem Tupel der Haupttabelle ein passender Tupel existiert. das eingesetzt werden. da er keinen Vorgesetzten hat. v. Bei der oberen M¨glichkeit muß an die Stelle. wird der Outer-Join ben¨tigt. m¨ssen Tabellen-Aliase6 vergeben o u werden. +----------------+------+----------------+------+ | Name | VNr | Name | MNr | +----------------+------+----------------+------+ | Christoph Reeg | NULL | NULL | NULL | | junetz.VNr = v. Im Prinzip ist das logisch.13 sec) mysql> Die Tabelle ‘Mitarbeiter‘ muß zwei Mal innerhalb der FROM-Anweisung auftauchen.8. Da die Spaltennamen ungleich sind (in der Haupttabelle ‘VNr‘ und in der nachgeordneten Tabelle ‘MNr‘). m.MNr. und deshalb kommen wir zur n¨chsten Form des Joins: dem Outer-Join.Name. mysql> SELECT m. In beiden F¨llen kann auch LEFT OUTER JOIN anstelle von LEFT JOIN u a geschrieben werden – das OUTER ist optional und nur aus Gr¨nden der SQL-Kompatibilit¨t u a erlaubt. kann auf Seite 41 nachschlagen :-) Christoph Reeg Seite 56 . SQL-Befehle Joins 5 rows in set (0. uber die o u ¨ die Verbindung entsteht.3 Outer-Join Um beim Join alle Tupel der Haupttabelle mit den dazu passenden Tupeln der nachgeordneten Tabelle zu bekommen. wo o ‘bedingung‘ steht. was man beim Equi-Join als ‘where condition‘ schreiben w¨rde.VNr.

AbtNr. mysql> SELECT a. ” Wie man unschwer erkennen kann.de | Christoph Reeg | | Uli | Christoph Reeg | | JCP | Uli | | Maier | Christoph Reeg | | Meier | Maier | +----------------+----------------+ 6 rows in set (0. in welcher Beziehung die u o einzelnen Mitarbeiter zu den Vorgesetzten stehen.Name as Vorges -> FROM Mitarbeiter m LEFT JOIN Mitarbeiter v ON m. aber mit deren Autos. .Name. ¨ Ubrigens: Man muß nat¨rlich nicht sowohl VNr als auch MNr abfragen (also zwischen u SELECT und FROM angeben). kann man sogar ganz auf das Abfragen ¨ der Nummern verzichten. k¨nnen in diesem u o Fall beide Syntaxvarianten verwendet werden: 7 Sonst w¨rde dieses Beispiel auch nicht im Kapitel Outer-Join stehen .Name AS Mitarb. Um nicht v¨llig den Uberblick zu verlieren. +-----------+-------------+---------+ | Name | Kennzeichen | Typ | +-----------+-------------+---------+ | Chefetage | MTK-CR 1 | RR | | EDV | F-JN 1 | VW-Golf | +-----------+-------------+---------+ 2 rows in set (0. Wenn man nur wissen m¨chte. .AbtNr = p. Also das ganze u u nochmal als Outer-Join. SQL-Befehle Joins Die Mitarbeitertabelle mit dem Alias m“ ist in unserem Fall die Haupttabelle. v. PKW p -> WHERE a.Kennzeichen. vergeben wir dabei o noch Aliase: mysql> SELECT m. da deren Werte wegen der ON-Bedingung (in der sie wiederum stehen m¨ssen) immer gleich sind. f¨hrt der Equi-Join nicht zum gew¨nschten Ergebnis7 .VNr = v. Da die Schl¨sselspalten denselben Namen haben. p. NULL als Wert genommen.04 sec) mysql> Wie man sieht.Typ -> FROM Abteilung a.6.MNr.03 sec) mysql> Ein neues Beispiel: Ich will alle Abteilungen aufgelistet haben. wird bei den Attributen. bei denen keine Werte existieren (in diesem Beispiel die beiden rechten Spalten in der ersten Zeile). p.-) u Christoph Reeg Seite 57 . . +----------------+----------------+ | Mitarb | Vorges | +----------------+----------------+ | Christoph Reeg | NULL | | junetz.

Typ -> FROM Abteilung a LEFT JOIN PKW p USING (AbtNr). p.Kennzeichen.AbtNr.Name.Name. +------------+-------------+---------+ | Name | Kennzeichen | Typ | +------------+-------------+---------+ | EDV | F-JN 1 | VW-Golf | | Verwaltung | NULL | NULL | | Chefetage | MTK-CR 1 | RR | +------------+-------------+---------+ 3 rows in set (0. p.AbtNr = p. aber nicht u ausreichend. +------------+-------------+---------+ | Name | Kennzeichen | Typ | +------------+-------------+---------+ | EDV | F-JN 1 | VW-Golf | | Verwaltung | NULL | NULL | | Chefetage | MTK-CR 1 | RR | +------------+-------------+---------+ 3 rows in set (0. +------------+-------------+------+ | Name | Kennzeichen | Typ | +------------+-------------+------+ | Verwaltung | NULL | NULL | +------------+-------------+------+ 1 row in set (0.Kennzeichen.00 sec) mysql> SELECT a. p. Um Daten wieder l¨schen zu k¨nnen.Typ -> FROM Abteilung a LEFT JOIN PKW p ON a.9 DELETE FROM Immer nur Daten einf¨gen und anzeigen zu lassen. p.6.00 sec) mysql> Als kleine Herausforderung h¨tte ich jetzt gerne die Abteilungen.Typ -> FROM Abteilung a LEFT JOIN PKW p USING (AbtNr) -> WHERE Typ IS NULL. die keinen PKW haben. SQL-Befehle DELETE FROM mysql> SELECT a. ist zwar ganz praktisch.Kennzeichen.03 sec) mysql> 6.Name. p. wird der Befehl DELETE FROM benutzt. daß bei der Abteilung ohne PKW (n¨mlich Verwaltung“) ‘Kennzeichen‘ und ‘Typ‘ NULL sind. o o Die Syntax lautet: Christoph Reeg Seite 58 . p. a ” mysql> SELECT a. a Die L¨sung ist eigentlich einfach. Wenn man sich das obige Ergebnis ansieht. stellt man o fest (wie auch etwas weiter oben schon beschrieben).

) oder ADD INDEX (index_spalte. o o kann man erst ein SELECT * statt DELETE machen.11 ALTER TABLE ¨ Schließlich kommen wir noch zum Andern von Tabellen. in der einzelne u a Eintr¨ge ge¨ndert werden sollen. u 6.. erst die Daten zu l¨schen.10 UPDATE ¨ Als letztes fehlt noch das Andern von Daten. k¨nnen diese Zuweisungen einfach durch a o je ein Komma getrennt hintereinander geschrieben werden. Wenn nur Daten angezeigt werden. Wenn keine ‘where definition‘ angegeben wird.) oder DROP feld_name oder DROP PRIMARY KEY oder RENAME new_table_name F¨r ‘create definition‘ gilt dasselbe wie schon f¨r ‘CREATE TABLE‘. Die Syntax lautet: u ALTER TABLE table_name alter_spec alter_spec: ADD [COLUMN] create_definition [AFTER column_name | FIRST] oder CHANGE alter_feld_name create_definition oder ADD PRIMARY KEY (index_spalte.6. um sie danach wieder ge¨ndert einzuf¨gen. die Datentypen f¨r einzelne Spalten zu ¨ndern und Spalten hinzuzuf¨gen u a u bzw. Es ist doch etwas unpraktisch. Die Syntax des UPDATE-Befehls o a u lautet: UPDATE table_name SET feld_name=expression... die gel¨scht werden sollen.) oder ADD UNIQUE (index_spalte. werden alle Daten ohne Nachu frage gel¨scht! Die ‘where definition‘ muß denselben Anforderungen gen¨gen wie bei der o SELECT-Anweisung. dessen Werte ge¨ndert werden sollen und ‘expression‘ durch den neuen Wert.. Falls a Werte mehrerer Felder ge¨ndert werden sollen. ob auch wirklich nur die richtigen Daten gel¨scht werden. beim L¨schen gehen nat¨rlich die Daten der gel¨schten Spalte verloren! o o u o Der Befehl daf¨r ist ALTER TABLE. Es ist m¨glich.. die o Daten enthalten. SQL-Befehle UPDATE DELETE FROM table_name [WHERE where_definition] F¨r ‘table name‘ ist selbstverst¨ndlich der Name der Tabelle einzusetzen. o 6. u u Christoph Reeg Seite 59 . ersetzt man das SELECT * durch DELETE. Um vor dem L¨schen zu testen. ‘feld name‘ ist durch den Namen des Feldes zu erseta a zen.... in der gel¨scht u a o wird.. [WHERE where_definition] F¨r ‘table name‘ ist selbstverst¨ndlich der Name der Tabelle einzusetzen.. bei Tabellen.. Wenn keine ‘where definition‘ angegeben wird.. zu l¨schen. werden alle Tupel ge¨ndert! Die ‘where definition‘ muß denselben Ana forderungen gen¨gen wie bei der SELECT-Anweisung.

6. Query OK. u mysql> ALTER TABLE temp -> ADD drei VARCHAR(30) AFTER zwei. -> zwei VARCHAR(20). Query OK. a u mysql> ALTER TABLE temp -> ADD fuenf VARCHAR(30). +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | PRI | | | | zwei | varchar(20) | YES | | NULL | | | fuenf | varchar(30) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 3 rows in set (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 Christoph Reeg Seite 60 . Query OK.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SHOW columns FROM temp.00 sec) mysql> Als n¨chstes soll die Spalte ‘fuenf‘ vom Typ VARCHAR(30) eingef¨gt werden. hier ein kleines praktisches Beispiel (der Befehl SHOW COLUMNS wird hierbei jeweils nur zur Verdeutlichung der Ergebnisse benutzt): Es wird folgende Tabelle angelegt: mysql> CREATE TABLE temp ( -> eins VARCHAR(10) NOT NULL. 0 rows affected (0.00 sec) mysql> Nun wird die Spalte ‘drei‘ vom Typ VARCHAR(30) nach der Spalte ‘zwei‘ eingef¨gt. 0 rows affected (0. SQL-Befehle ALTER TABLE Um das Ganze etwas zu verdeutlichen. -> PRIMARY KEY(eins) -> ).00 sec) mysql> SHOW columns FROM temp. +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | PRI | | | | zwei | varchar(20) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 2 rows in set (0. 0 rows affected (0.

Query OK.00 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SHOW columns FROM temp. SQL-Befehle ALTER TABLE mysql> SHOW columns FROM temp. 0 rows affected (0. Also benennen wir einfach die Spalte ‘fuenf‘ in a ‘vier‘ um: mysql> ALTER TABLE temp -> CHANGE fuenf vier VARCHAR(30).01 sec) mysql> Jetzt soll die Spalte ‘eins‘ nicht mehr Prim¨rschl¨ssel sein (nicht die erste Spalte der a u SHOW-Anweisung!): mysql> ALTER TABLE temp -> DROP PRIMARY KEY. +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | Christoph Reeg Seite 61 . +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | PRI | | | | zwei | varchar(20) | YES | | NULL | | | drei | varchar(30) | YES | | NULL | | | vier | varchar(30) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 4 rows in set (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SHOW columns FROM temp.6. 0 rows affected (0.00 sec) mysql> So gef¨llt uns das aber noch nicht ganz. Query OK. +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | PRI | | | | zwei | varchar(20) | YES | | NULL | | | drei | varchar(30) | YES | | NULL | | | fuenf | varchar(30) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 4 rows in set (0.

6. SQL-Befehle ALTER TABLE +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | | | | | zwei | varchar(20) | YES | | NULL | | | drei | varchar(30) | YES | | NULL | | | vier | varchar(30) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 4 rows in set (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SHOW columns FROM temp. Prim¨rschl¨ssel m¨ssen aber als ‘NOT a u a u u ¨ NULL‘ definiert werden. Deshalb zuerst einmal eine kleine Anderung des Datentyps: mysql> ALTER TABLE temp -> CHANGE drei drei VARCHAR(30) NOT NULL. 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SHOW columns FROM temp.01 sec) mysql> Die Spalte ‘drei‘ soll nun Prim¨rschl¨ssel werden. 0 rows affected (0. Query OK. Query OK. +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | | | | | zwei | varchar(20) | YES | | NULL | | | drei | varchar(30) | | PRI | | | | vier | varchar(30) | YES | | NULL | | Christoph Reeg Seite 62 .00 sec) mysql> Und nun definieren wir den Prim¨rschl¨ssel neu: a u mysql> ALTER TABLE temp -> ADD PRIMARY KEY(drei). +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | | | | | zwei | varchar(20) | YES | | NULL | | | drei | varchar(30) | | | | | | vier | varchar(30) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 4 rows in set (0.

0 rows affected (0. Query OK. SQL-Befehle ALTER TABLE +-------+-------------+------+-----+---------+-------+ 4 rows in set (0. 0 rows affected (0. +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | | | | | zwei | varchar(20) | YES | | NULL | | | vier | varchar(30) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 3 rows in set (0.temp’ doesn’t exist mysql> SHOW columns FROM test. ERROR 1146: Table ’cr. +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | | | | | zwei | varchar(20) | YES | | NULL | | | vier | varchar(30) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 3 rows in set (0. alle Spalten der Reihe u nach zu l¨schen.00 sec) mysql> SHOW columns FROM temp. Deshalb benennen wir die Tabelle in ‘test‘ um: mysql> ALTER TABLE temp -> RENAME test. o o mysql> ALTER TABLE temp -> DROP drei. wo wir alles m¨hsam erstellt haben.00 sec) mysql> Zum Schluß l¨schen wir wieder die ganze Tabelle: o Christoph Reeg Seite 63 . Als erstes soll die Spalte ‘drei‘ gel¨scht werden.01 sec) mysql> Jetzt.00 sec) mysql> Der Name ‘temp‘ klingt aber irgendwie langweilig.6. fangen wir wieder an.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SHOW columns FROM temp. Query OK.

Christoph Reeg Seite 64 . Query OK. SQL-Befehle ALTER TABLE mysql> DROP TABLE test. daß die Tabelle nicht existiert.00 sec) mysql> SHOW columns FROM test. wenn man sich beim Tabellennamen verschrieben hat (auch Groß/Kleinschreibung).test’ doesn’t exist mysql> Die letzte Fehlermeldung besagt.6. 0 rows affected (0. Diese Fehlermeldung bekommt man auch. ERROR 1146: Table ’cr.

de | 0.8871 | | 6 | Meier | 0. wie im folgenden Beispiel zu sehen ist. aber noch wird nicht richtig danach sortiert.1324 | | 4 | JCP | 0. die zuf¨llige Werte produziert. Das n¨chste Beispiel zeigt die Idee. Ab dieser Version ist es n¨mlich m¨glich.1 zuf¨llige Daten ausw¨hlen a a H¨ufig ben¨tigt man ein paar zuf¨llige Datens¨tze aus einer Tabelle. ergeben sich folglich zuf¨llige Reihenfolgen.7790 | | 5 | Maier | 0. der ausgegebenen Tabelle eine Spalte mit den zuf¨lligen Werten a anzuf¨gen. Ab MySQL-Version 3. +-----+----------------+--------+ | MNr | Name | sort | +-----+----------------+--------+ | 3 | Uli | 0.6487 | | 6 | Meier | 0. a u Der Trick besteht darin. RAND() ist eine a o MySQL-Funktion.5510 | | 3 | Uli | 0. mysql> SELECT MNr. oder will die vorhana o a a denen Datens¨tze zuf¨llig sortiert anzeigen. a Bei ¨lteren Versionen funktioniert das nicht: wir m¨ssen etwas in die Trickkiste greifen.Name.0881 | | 1 | Christoph Reeg | 0.0092 | | 5 | Maier | 0. a Sobald jedoch eine Spalte mit in die Berechnung von sort einbezogen wird.2160 | +-----+----------------+--------+ 6 rows in set (0.23 ist das etwas einfacher geworo den. a a Es gibt verschiedene L¨sungen.RAND() AS sort -> FROM Mitarbeiter -> ORDER BY sort.6311 | Christoph Reeg Seite 65 . ORDER BY RAND() zu nutzen. funktioniert das Ganze.8742 | | 2 | junetz. u a mysql> SELECT MNr. +-----+----------------+--------+ | MNr | Name | sort | +-----+----------------+--------+ | 1 | Christoph Reeg | 0.0*MNr+RAND() AS sort -> FROM Mitarbeiter -> ORDER BY sort. Wenn nach der Ausgabe dieser Funktion a sortiert wird.00 sec) Die Spalte sort enth¨lt schon die Zufallswerte.7 Tips & Tricks 7.Name.

Tips & Tricks Nutzer in MySQL | 4 | JCP | 0. wie man entsprechende Anpassungen vornimmt. Auch f¨r den Systemverwalu o u ter gibt es einige Einstellungsm¨glichkeiten wie das Anlegen neuer Nutzer inklusive dem o obligatorischen MySQL-Neustart oder Rechtevergabe. z. aber alle Rechte hat: Sein Name ist root. 7.5) bestimmen. ein Abfragenutzer.3) einen Datensatz ausgeben lassen. u 7. der vollen Zugriff auf die Datenbank hat. o Um die Datenbank effizient nutzen zu k¨nnen. wenn wort du einen eigenen (Offline-) Server betreibst. Was im Endeffekt schneller l¨uft. h.6. Aufgrund der Komplexit¨t dieses Themas verweise ich aber an dieser Stelle nur auf a das (englische) MySQL-Manual: Dort findest du durch Suche nach dem Begriff privileges“ ” eine ausf¨hrliche Beschreibung. h. u f¨r die sie Rechte besitzen) sehen und bearbeiten k¨nnen. genau einen zuf¨lligen Datensatz auszuw¨hlen. ist nur etwas mehr Programmieraufwand. k¨nnen wir uns auch mit a o Hilfe von LIMIT (siehe auch 6. 1 2 IMHO sollte schon richtig nach der Spalte ‘sort‘ sortiert werden Das solltest du aber.8183 | | 2 | junetz. mit o a a a Hilfe von PHP: erst mit Hilfe von COUNT (siehe auch 6. Eine andere M¨glichkeit. Datenbanken. d. sobald es geht. auf eine neu erstellte Datenbank problemlos zugreifen k¨nnen. uber einen gew¨hnlichen Web-Browser eine MySQL-Datenbank zu vero o ¨ walten (Benutzer.de | 0. wie viele Datens¨ta ze es gibt. der nur Leserechte hat und ein Adminnutzer. auch wenn (komischerweise1 ) nicht nach ‘sort‘ sortiert wura de. d. B.2 Nutzer in MySQL Bei der Installation von MySQL wird standardm¨ßig ein Nutzer eingerichtet.7. ¨ndern und l¨schen). ¨ndern. h¨ngt von dem jeweiligen Datenbankdesign a a ab.7. es stellt eine M¨glichkeit dar. Funktioniert im Endeffekt genauso. eines setzen! a Jens Hatlak Seite 66 .00 sec) Der Summand 0 ∗ M N r beeinflußt das Endergebnis nicht.1982 | +-----+----------------+--------+ 6 rows in set (0. Tabellen und Datens¨tze anlegen.user (Datenbank mysql. daß alle MySQL-Nutzer eines o Systems sich einloggen und dabei nat¨rlich nur ihre eigenen Datenbanken (genauer: die. Generell m¨ssen solche Nutzer dem MySQL-Ansatz u der Rechtevergabe folgend in mysql. Die Reihenfolge ist zuf¨llig. trotzdem funktioniert das Sortieren. der kein Paßa 2 . w¨re z. Tabelle user) eingetragen werden. a a o Dabei besteht die M¨glichkeit. sollten allerdings sp¨ter geeignete Nutzer o a angelegt werden. Nachdem wir nun die zuf¨llige Reihenfolge erhalten haben. das System so einzurichten. dann mit PHP eine Zufallszahl bestimmen und genau den korrespondierenden Eintrag ausgeben. B. Mit diesem Nutzer solltest Dd also.3 PHPMyAdmin PHPMyAdmin ist ein PHP-basiertes MySQL-Administrierungssystem.

Die eine oder andere Datenbank bietet dazu proa priet¨re Funktionen (z. die auch die PHPMyAdmin-eigene Dokumentation nicht beantworten kann und die von allgemeinem Interesse sind.4 B¨ume in SQL a An der ein oder anderen Stelle hat man das Problem.und Nachteile aufzuzeigen versuchen. . MySQL). um trotzdem B¨ume abspeichern zu k¨nnen. daß man eine Baumstruktur in einer SQL-Datenbank speichern will. ist bei Anbietern von serverseitiger PHP. A. so ist Zugang zu u einem Unix-basierten System von Vorteil. u Sollten noch Fragen offen bleiben. andere nicht (z. was auch kein Sicherheitsrisiko dar” stellt angesichts der Tatsache. lediglich ein Nutzer mit Leserechten u a auf die mysql“-Datenbank muß angelegt werden. Es gibt nat¨rlich u 3 Bei der Authentifizierung wird ja nur mit demselben Algorithmus verschl¨sselt und dann verglichen u . verschiedene Endungen verschiedenen PHP-Interpreter¨ Versionen zugeordnet sind. Dies ist dann von besonderem Interesse. F¨r letzteres ist n¨mlich nicht viel zu machen. Im Laufe der Zeit wurden a hier entsprechende Varianten entworfen. daß es Versionen f¨r zwei verschiedene u Endungen (.phpmyadmin. also i. kann PHPMyAdmin fast vollst¨ndig das . B. n¨mlich den Verzeichnisbaum. o trotzdem entsprechende M¨glichkeit zu bekommen. etwas anderes unter einem Baum.und Export von fertigen SQL-Dateien ist m¨glich. Im Zweifelsfall lohnt es sich. Ich a o werde hier einige vorstellen und die jeweiligen Vor. o F¨r Nutzer von Billig-Webhosting Angeboten ist ein Zugriff auf die mysql-Komu mandozeile gar nicht m¨glich und dadurch PHPMyAdmin eine sehr einfache Alternative. Auf diese Weise halten h¨ufig gestellte a Fragen (FAQ) sicher Einzug in sp¨tere DSP-Versionen. ob dieses System angeboten wird und f¨r Mitglieder auch frei verf¨gbar u u ist.mysql‘ Kommandozeilena programm ersetzen. nicht unter a Windows. denn sogar Im. einfach o mal zu fragen.7. wenn. 7. Der u u a Informatiker dagegen versteht i. Von o Vorteil ist nat¨rlich die Umsetzung des Systems in HTML: W¨hrend beim Kommandozeiu a ¨ lenprogramm schnell die Ubersichtlichkeit verloren geht. o Auf der PHPMyAdmin-Homepage http:// www.1 Was ist ein Baum? Jeder kennt sicher die nat¨rliche Variante (die mit den komischen gr¨nen Bl¨ttern). Dem Paket liegt zwar ein Script zum Andern der Endungen in frei w¨hlbare bei. kannst du diese gerne an die vorne angegebene E-Mail-Adresse schicken.php und .und MySQL-Unterst¨tzung oftmals PHPMyAdmin schon deshalb installiert.4. B. a 7.net/ finden sich immer die aktuellen Versionen des Pakets.-) Wenn man nachfragt. Jeder kennt mindestens eine Baumstruktur von seinem Computer.php4 gew¨nscht. macht PHPMyAdmin von gew¨hnlichen HTML-Tabellen Gebrauch und o bietet dabei direkt sinnvolle Editierm¨glichkeiten und Vereinfachungen.so auch bei uns. wenn große Tabellen ausgegeben werden sollen. Tips & Tricks B¨ume in SQL a Richtig eingesetzt. die Verwendung der Endung . damit die Administratoren u selbst effizienter arbeiten k¨nnen .php3) gibt.eine Entschl¨sselung ist gar nicht vorgesehen (und sollte nicht m¨glich sein) u o Christoph Reeg Seite 67 . daß die dort abgelegten Paßworte durch den verwendeten Verschl¨sselungs-Algorithmus praktisch unknackbar sind3 . B. Ist also z. Oracle). wie beim Jugendnetz Frankfurt/Offenbach. dieses funktioniert aber leider nur mit der Bash. Zu beachten ist. A.

DOS und WIN) existierten. in dem genau ein Knoten keinen Vorg¨nger hat und alle anderen Knoten mindestens einen Vorg¨nger haben. wo ich die Elemente so benannt habe. a Ein Baum ist ein azyklischer Graph. auf dem verschiedene Verzeichnisse (z. B. In Abbildung 7. Ein Baum ist ein ungerichteter.4. die wieder Unterverzeichnisse hatten (z. was ein Baum ist. SYSTEM im WINVerzeichnis). Tips & Tricks B¨ume in SQL a auch verschiedene Definitionen. An Stelle von Nachfolger und Vorg¨nger wird auch h¨ufig Sohn und Vater gesagt. trotzdem versuche ich es anders zu erkl¨ren. Root A B C A1 B1 B2 C1 A1I C1I C1II Abbildung 7.1 habe ich den Baum einmal grafisch dargestellt.7. B. a Bei dem guten alten DOS gab es ein Laufwerk C:. a 7. zusammenh¨ngender Graph. daß eigentlich klar sein sollte. a a Die letzte Definition kann man sogar fast verstehen. zyklenfreier.1: Unser Baum-Beispiel Christoph Reeg Seite 68 . wo sie sich im Baum befinden sollten.2 Beispieldaten In diesem Kapitel werde ich von einem Beispielbaum ausgehen. Die a a Elemente in der Mitte des Baumes werden Knoten genannt und die Elemente ohne Nachfolger heißen Bl¨tter. Wenn man nun C: als Wurzel bezeichnet und DOS und WIN als Nachfolger von C:. sowie SYSTEM als Nachfolger von WIN hat man einen Baum.

h. Da uber die Vater-ID auf den Vater (¨bergeordneter Knoten) gezeigt wird.4.3 Baumdarstellung mit Vater-Zeiger Eine sehr beliebte Variante zur Baumdarstellung ist.: Wurzel) ist. ID 1 2 3 4 5 6 7 8 9 10 11 Name Root A B C A1 B1 B2 C1 A1I C1I C1II Vater-ID 0 1 1 1 2 3 3 4 5 8 8 Tabelle 7. das u den Baum als Summe von Mengen betrachtet. da Mengen Relationen sind. Tips & Tricks B¨ume in SQL a 7. B.de/ ) habe ich diese Vao riante kennen gelernt. Konkret ergeben sich daraus die Werte ” in Tabelle 7.1.1: Baumdarstellung mit Vater-Zeiger Der Vorteil dieser Variante ist das relativ einfache Erstellen des Baumes. daß mit relationalen Datenbanken sehr effizient damit gearbeitet werden kann. Auch das Umh¨ngen von einzelnen Asten a a ist relativ einfach. ergibt sich die u ¨ Bezeichnung Baumdarstellung mit Vater-Zeiger“.6. so daß ich hier versuche.2 grafisch dargestellt. wobei eine Vater-ID mit 0 bedeutet. in der alle anderen Elemente enthalten sind. bei der Bestimmung der maximalen Tiefe4 . oder beim Feststellen. Die dort liegenden Folien sind jedoch zum Verstehen etwas knapp gehalten. daß es die Root (engl.4. das etwas ausf¨hrlicher zu zeigen. u Wie aber funktioniert das nun? Wir betrachten den Baum als Summe sich uberlappender ¨ Mengen. aber ansonsten ist noch alles OK. Dies hat den Vorteil. Das große Problem kommt allerdings z. D. bei der Ausgabe des Gesamtbaumes. eine falsche Vater-ID f¨hrt nur“ zu einem falsch angeu ” ¨ h¨ngten Ast.1 o 7. ob ein Knoten ¨ noch S¨hne hat. das Element Root“ bildet eine Menge. Nichts leichter als das: Jedes Element bekommt zwei zus¨tzliche Felder. wobei immer ein Knoten mit allen Nachfolgern eine Menge bildet. die einzelnen Knoten mit einer eindeutigen ID zu versehen und dann bei jedem Knoten die jeweilige Vater-ID zu speichern.koehntopp.4.7. Auch ist er relativ robust gegen falsche Daten. Auf der Seite von Kristian K¨hntopp (http:// www. ” ” Das Ganze ist in Abbildung 7.4 Nested Set Modell Eine andere sehr elegante Methode f¨r Baumstrukturen ist das Nested Set Model. Jetzt stellt sich nur noch die Frage. Siehe dazu auch die Ubung 7. wie viele Knoten hintereinander h¨ngen a Christoph Reeg Seite 69 . wie man dieses Mengenkonstrukt optimal in die Datenbank bringt. bei A“ ” ” sind nur die Elemente A1“ und A1I“ enthalten usw. a 4 Tiefe bei einem Baum heißt.

l¨ßt sich mit BETWEEN erledigen. ’ C ’ . l int .13). bis ich unten angekommen bin.l‘ eine . setzen wir das Ganze in SQL um.5‘ und gehe wieder z¨hlend hoch. Dann nehme ich wieder die Abbildung 7. (4. gehe dann zu dem linken Nachfolger und schreibe dort in das Feld .21).7.r‘ eine .3 ist das Ganze grafisch dargestellt und dann sollte es eigentlich klar werden.l‘ eine .2: Baumdarstellung als Summe von Mengen ich nenne sie einfach mal . Die an dieser Stelle wichtigste Abfrage. Tips & Tricks B¨ume in SQL a B1 A A1I A1 Root C C1 C1II B B2 C1I Abbildung 7. r int ). ’ B ’ .14. ob ein Element Nachfolger eines anderen ist (gleichbedeutend mit in der Menge enthalten“).l‘ und .2.1. (2. Christoph Reeg Seite 70 . ’ Root ’ .r‘. Wer dem jetzt nicht folgen a konnte: Keine Angst. ’ A ’ . Dort schreibe ich in das Feld . fange bei der Wurzel an und schreibe in das Feld .22). in Abbildung 7. (3. a ” Aber nun genug der Theorie. Dazu als erstes unser CREATE TABLE mit den INSERT Anweisungen: CREATE TABLE NestedSet ( ID int not null primary key .1‘.2‘ usw. Name varchar (100).8.7). INSERT INSERT INSERT INSERT INTO INTO INTO INTO NestedSet NestedSet NestedSet NestedSet VALUES VALUES VALUES VALUES (1.1.

l BETWEEN v.9. ’ C 1 I I ’ .l. ’ A1I ’ .6).16.l AND v. (7. zeigt folgende Abfrage: o mysql> SELECT v.11. ’ C1 ’ . (6.r -> ORDER BY s.17).15. v. (8.Name AS Nachfolger -> FROM NestedSet v. ’ C1I ’ .20). +-------+------------+ | Vater | Nachfolger | +-------+------------+ | Root | Root | | Root | A | | A | A | | Root | A1 | | A | A1 | | A1 | A1 | Christoph Reeg Seite 71 .l.Name AS Vater. Wie sch¨n diese Struktur ist. (11.7. ’ B1 ’ . (9. Tips & Tricks B¨ume in SQL a Root 1 22 A 2 A1 3 A1I 4 5 6 9 7 8 B1 10 11 B 13 B2 12 15 14 C1 20 C 21 C1I C1II 16 17 18 19 Abbildung 7.4.12).3: Baumdarstellung im Nested Set Modell INSERT INSERT INSERT INSERT INSERT INSERT INSERT INTO INTO INTO INTO INTO INTO INTO NestedSet NestedSet NestedSet NestedSet NestedSet NestedSet NestedSet VALUES VALUES VALUES VALUES VALUES VALUES VALUES (5.5). s. (10.3. ’ B2 ’ .10). NestedSet s -> WHERE s.18.19). ’ A1 ’ .

Tips & Tricks B¨ume in SQL a | Root | A1I | | A | A1I | | A1 | A1I | | A1I | A1I | | Root | B | | B | B | | Root | B1 | | B | B1 | | B1 | B1 | | Root | B2 | | B | B2 | | B2 | B2 | | Root | C | | C | C | | Root | C1 | | C | C1 | | C1 | C1 | | Root | C1I | | C | C1I | | C1 | C1I | | C1I | C1I | | Root | C1II | | C | C1II | | C1 | C1II | | C1II | C1II | +-------+------------+ 31 rows in set (0.Name AS Nachfolger -> FROM NestedSet v. wer alles Vorg¨nger zu einem bestimmten a Knoten ist.l. NestedSet s -> WHERE s.l AND v.01 sec) Ich bekomme mit einer Abfrage das Ergebnis.l BETWEEN v.Name AS Vater. s.7. Durch eine entsprechende Eingrenzung kann man sich auch alle Vorg¨nger zu genau a einem Knoten ausgeben lassen: mysql> SELECT v.r -> AND s. +-------+------------+ | Vater | Nachfolger | +-------+------------+ | Root | C1I | | C | C1I | | C1 | C1I | | C1I | C1I | +-------+------------+ 4 rows in set (0.Name = ’C1I’ -> ORDER BY v.00 sec) Christoph Reeg Seite 72 .

Tips & Tricks B¨ume in SQL a Die Abfrage.00 | B | | 0. wie viele Nachfolger ein Knoten hat. gibt es auch hier Ubungen o a Christoph Reeg Seite 73 .00 | B2 | | 3. ” ” mysql> SELECT (r-l-1)/2 AS Nachfolger.00 | C1I | | 0.00 | B1 | | 0. mit ihrer Tiefe: mysql> SELECT s. l¨ßt sich ganz einfach uber die Diffea ¨ renz von l“ und r“ feststellen.00 | C1II | +------------+------+ 11 rows in set (0. NestedSet s -> WHERE s.00 | A1 | | 0.00 | C | | 2.l.00 | A1I | | 2.00 sec) ¨ Bevor wir den Baum gleich durch L¨schen & Co ver¨ndern.Name. +------+-------+ | Name | Level | +------+-------+ | Root | 1 | | A | 2 | | A1 | 3 | | A1I | 4 | | B | 2 | | B1 | 3 | | B2 | 3 | | C | 2 | | C1 | 3 | | C1I | 4 | | C1II | 4 | +------+-------+ 11 rows in set (0.7.00 | A | | 1.00 | Root | | 2.00 sec) Auch sehr interessant: alle Knoten.l AND v.l BETWEEN v.r -> GROUP BY s.00 | C1 | | 0. +------------+------+ | Nachfolger | Name | +------------+------+ | 10. count(*) AS Level -> FROM NestedSet v. Name -> FROM NestedSet -> ORDER BY l.

in den Vater” ” ” knoten nicht vergessen!) • Tabelle wieder freigeben Um das zu verstehen. mysql> LOCK TABLE NestedSet WRITE. o ” Die beiden Nachfolger B1“ und B2“ sollen dann direkt unter Root“ h¨ngen. parallelen L¨schvorgang die Tabelle o durcheinander kommt. so schwierig ist sie beim Andern der o Datenstruktur. Man muß immer aufpassen. Tips & Tricks B¨ume in SQL a (7.7. Im Prinzip sind folgende Schritte notwendig: • Sperren der Tabelle • l“ und r“ von dem zu l¨schenden Element auslesen o ” ” • Element l¨schen o • l“ und r“ der Nachfolger um 1 reduzieren ” ” • l“ und r“ des rechten Nachbarbaums um 2 reduzieren ( r“ im bzw. indem wir sie sperren. a ” ” ” Als erstes verhindern wir. mit der Zeit kommt das Verst¨ndnis f¨r diese Struktur. falls das Ganze noch nicht klar geworden ist. weil sonst der ganze Baum durcheinander kommt.4. sollte kein großes Problem sein: o mysql> DELETE FROM NestedSet -> WHERE Name = ’B’. indem wir aus dem Beispiel den Knoten B“ l¨schen. +------+------+ | l | r | +------+------+ | 8 | 13 | +------+------+ 1 row in set (0. u Den Knoten zu l¨schen. daß durch einen evtl.4. sich einfach mal ein Blatt Papier und einen Stift zu nehmen und das exemplarisch durchzugehen. keinen der Zeiger falsch zu belegen.2) zum Vertiefen.4. Query OK.6. ist es hilfreich.01 sec) Christoph Reeg Seite 74 . Wir machen das jetzt hier in SQL.00 sec) Nun brauchen wir l“ und r“ von unserem Element: ” ” mysql> SELECT l. a u 7. Keine Angst.00 sec) Diese m¨ssen wir uns nun merken. 0 rows affected (0. Query OK.r -> FROM NestedSet -> WHERE Name = ’B’.1 L¨schen o ¨ So sch¨n diese Methode auch zum Abfragen ist. 1 row affected (0.

Query OK. daß es tats¨chlich funktioniert hat. Query OK. Query OK.00 sec) Rows matched: 4 Changed: 4 Warnings: 0 mysql> UPDATE NestedSet -> SET r=r-2 -> WHERE r > 13. ” ” ” mysql> UPDATE NestedSet -> SET l=l-1. Query OK. 0 rows affected (0. ” mysql> UPDATE NestedSet -> SET l=l-2 -> WHERE l > 13. 4 rows affected (0. die zwischen 8“ und 13“ (siehe letzte Abfrage) liegen.00 sec) Christoph Reeg Seite 75 . 5 rows affected (0. +----+------+------+------+ | ID | Name | l | r | +----+------+------+------+ | 1 | Root | 1 | 20 | | 2 | A | 2 | 7 | | 5 | A1 | 3 | 6 | | 9 | A1I | 4 | 5 | | 6 | B1 | 8 | 9 | | 7 | B2 | 10 | 11 | | 4 | C | 12 | 19 | | 8 | C1 | 13 | 18 | | 10 | C1I | 14 | 15 | | 11 | C1II | 16 | 17 | +----+------+------+------+ 10 rows in set (0. a ¨ mysql> SELECT * -> FROM NestedSet -> ORDER BY l. r=r-1 -> WHERE l BETWEEN 8 AND 13. zu erkennen an deren l“ ” ” ” bzw.00 sec) Rows matched: 2 Changed: 2 Warnings: 0 Nicht zu vergessen der rechte Nachbarbaum (in diesem Fall alle C*“ Elemente). Wer das Prinzip des Baumaufbaus verstanden o hat. kann sich auch noch davon uberzeugen. r“. mysql> UNLOCK TABLES.7.00 sec) Rows matched: 5 Changed: 5 Warnings: 0 Und als letzter wichtiger Schritt muß nat¨rlich noch die Tabelle wieder freigegeben u werden.00 sec) Das war jetzt das L¨schen eines Elements. 2 rows affected (0. Tips & Tricks B¨ume in SQL a Kommen wir nun zu den Nachfolgern (hier B1“ und B2“).

4.1 angelegt werden.4.6 Ubungen 7.1): • Gib die Wurzel aus • Wie viele S¨hne hat die Wurzel? o • Welches sind die S¨hne der Wurzel? o • Gib die Wurzel mit den S¨hnen aus o • Gib den kompletten Baum aus. Bei ¨ Anderungen sieht es schon schlechter aus: Es m¨ssen alle Datens¨tze. a a ¨ 7. muß erstmal die Tabelle 7. Tips & Tricks B¨ume in SQL a L¨schen von ganzen Teilb¨umen funktioniert analog.1. Aber u wie sieht es mit der Geschwindigkeit aus? Bei der Abfrage d¨rfte es kaum ein schnelleres u Modell geben. Eine SELECT-Abfrage mit einem Join und der ganze Baum ist ausgelesen. man muß die Schritte nur in u o der umgekehrten Reihenfolge durchlaufen. o Christoph Reeg Seite 76 . Die o Abfrage soll allgemein sein. die unterhalb oder u a rechts von dem eingef¨gten/gel¨schten Datensatz liegen. ver¨ndert werden.4.4. Schritt 3 kann dabei allerdings o a entfallen (es gibt ja keinen Nachfolger mehr) und bei Schritt 4 muß man nicht 2.4. o Nachdem die Tabelle nun existiert.6. kommen wir zu den h¨ufigsten Abfragen (L¨sung a o im Anhang B. sondern entsprechend der entfernten Elemente subtrahieren. gefolgt von den S¨hnen mit Angabe der Tiefe.1 Vater-Zeiger Um das Folgende machen zu k¨nnen. also auch bei gr¨ßeren Tiefen funktionieren. 7. 7. Normalerweise u o a sind das im Durchschnitt die H¨lfte der Datens¨tze.2 Einf¨gen u Das Einf¨gen funktioniert im Prinzip analog zum L¨schen.5 Performance vom Nested Set Modell Wie wir gesehen haben. so daß etwa das Folgende herauskommt: +-------+------+ | Tiefe | Name | +-------+------+ | 0 | Root | | 1 | A | | 2 | A1 | | 3 | A1I | | 1 | B | Also immer der Vaterknoten.7. lassen sich die Basisoperationen relativ einfach ausf¨hren.

2 Nested Set Etliche Abfragen wurden schon gezeigt.00 | 1 | 0 | | A | 2.00 | 4 | 0 | | B | 2.00 | 3 | 0 | | C1I | 0. von daher kommt hier noch eine richtig sch¨ne o (und damit nicht ganz einfache). • Nicht immer braucht man den gesamten Baum.00 | 4 | 0 | +------+------------+-------+--------+ 7.5 IF-Ausdr¨cke in SQL u Man kann – wie auch in PHP (siehe 8. Oder andersherum ausgedr¨ckt. Gib alle Knoten. Gegeben sei folgende Tabelle: mysql> select a.00 | 2 | 1 | | A1 | 1.00 | 3 | 1 | | B2 | 0. Wie sieht die dazu passende Abfrage aus? +------+------------+-------+--------+ | Name | Nachfolger | Tiefe | Bruder | +------+------------+-------+--------+ | Root | 10. die Tiefe des Elements und ob es auf gleicher Tiefe noch ein Element gibt. Aber zur Einstimmung erstmal was einfaches. Anzahl der Nachfolger (bzw.7. +-----+-----+ | a | b | Tilman Brock Seite 77 . gibt es einen oder keinen).6.00 | 3 | 0 | | C | 3. braucht man folgende Ino formationen: Name des Elements.2.00 | 4 | 1 | | C1II | 0. mit ihrer Tiefe im Baum aus.00 | 2 | 1 | | B1 | 0.14) – in MySQL if-Anweisungen benutzen. Das Ergebnis sollte so aussehen: ” +------+-------+ | Name | Level | +------+-------+ | C | 2 | | C1 | 3 | | C1I | 4 | | C1II | 4 | +------+-------+ • Um einen Baum sauber in HTML ausgeben zu k¨nnen.00 | 3 | 0 | | A1I | 0.b from if_test1.00 | 2 | 0 | | C1 | 2. Tips & Tricks IF-Ausdr¨cke in SQL u 7. folgende Tabelle enth¨lt alle notwendigen Informau a tionen.4. die unterhalb des Knotens C“ liegen.

5.1) gegeben werden. o Dieses IF m¨ssen wir jetzt noch in eine SELECT-Anweisung verpacken. u u Die IF-Anweisung ist folgendermaßen definiert: IF(Bedingung.00 sec) Die Fragestellung lautet: Ist a gr¨ßer oder gleich b? o Die ’traditionelle Methode’ w¨re jetzt folgende: man zieht sich alle Werte aus der Tabelle a und geht dann mittels einer geeigneten Programmiersprache (z. Funktionen auf Spalten oder andere IF-Anweisungen (siehe unten). Dem IF muß in der SELECT-Anweisung ein Alias o (siehe 6.ja --> ’a gr¨ßer b’ o . -> IF(a>=b. Tips & Tricks IF-Ausdr¨cke in SQL u +-----+-----+ | 6 | 1 | | 2 | 11 | | 5 | 5 | | 233 | 123 | +-----+-----+ 4 rows in set (0. B. da sonst der Wert nicht benutzt werden kann.6.’a groesser gleich b’. gleich oder kleiner als b?“.’a gr¨ßer gleich b’. mysql> select a. Um die Fragestellung zu beantworten. damit wir auch u mit dem Ergebnis arbeiten k¨nnen.’a kleiner b’) as vergleich -> from if_test1. Wir k¨nnen mit dieser o o Zwei-Wege-Form des IF nicht fragen: Ist a gr¨ßer. brauchen wir eine geschachtelte IF-Anweisung. wenn_falsch) wenn_wahr und wenn_falsch sind hierbei Zeichenketten. die die gew¨nschten Informationen enthalten. Um diese o ” Frage zu beantworten. +-----+-----+---------------------+ | a | b | vergleich | +-----+-----+---------------------+ | 6 | 1 | a groesser gleich b | | 2 | 11 | a kleiner b | | 5 | 5 | a groesser gleich b | | 233 | 123 | a groesser gleich b | +-----+-----+---------------------+ 4 rows in set (0. wenn_wahr.nein Ist a gleich b? .00 sec) Eine dreifach geschachtelte Aussage ist so jedoch nicht m¨glich. PHP) daran. modellhaft also etwas in dieser Art: Ist a gr¨ßer b? o .7.’a kleiner b’). ist also folgendes IF n¨tig: o IF(a>=b.b.ja Tilman Brock Seite 78 . die Werte zu extrahieren – es geht aber auch einfacher: mittels der IF-Anweisung in MySQL kann man der Ergebnistabelle leicht Felder hinzuf¨gen. Spaltennamen.

+-----+-----+--------------+ | a | b | vergleich | +-----+-----+--------------+ | 6 | 1 | a groesser b | | 2 | 11 | a kleiner b | | 5 | 5 | a gleich b | | 233 | 123 | a groesser b | +-----+-----+--------------+ 4 rows in set (0.1.’a gleich b’. +---------------+----------+------------+--------+ | MitarbeiterNr | Name | Geschlecht | Gehalt | +---------------+----------+------------+--------+ | 351 | Meier | m | 2000 | | 729 | M¨ller u | m | 1142 | | 921 | Guglhupf | w | 4500 | | 523 | Schmitt | w | 3488 | | 331 | Reeg | m | 2 | 5 Wer will.05 sec) 7.’a gleich b’. -> IF(a>b.’a groesser b’. a ” IF(a>b. Tilman Brock Seite 79 . Wir schreiben also (laut Modelldarstellung) in den ’wenn falsch’-Teil des ¨ußeren IF ein neues IF. IF(a=b. -> IF(a=b.1 Beispiele 7.nein --> ’a kleiner b’ Wie oben gesehen ist eine IF-Anweisung aus einer Bedingung. das die Frage Ist a gleich b“ stellt. brauchen wir 2 geschachtelte IF-Anweisungen.5. da es ja o allgemein bekannt sein d¨rfte. in der folgendes steht: mysql> select * from mitarbeiter.1 Firma Ausbeuter & Co KG Die Firma Ausbeuter & Co KG m¨chte geschlechtsspezifische Zulagen vergeben.b.5. ’a kleiner b’) ) MySQL liefert nun das gew¨nschte Resultat: u mysql> select a.7.’a groesser b’. ’a kleiner b’) -> ) as vergleich -> from if_test1. darf diesen Satz auch umdrehen. daß M¨nner schlechter arbeiten als Frauen5 . Die Firma hat u a eine Mitarbeitertabelle. einem Teil ’wenn wahr’ und einem Teil ’wenn falsch’ aufgebaut. Um das eben gezeigte Modell als IF nachzubauen. Tips & Tricks IF-Ausdr¨cke in SQL u --> ’a gleich b’ .

Tips & Tricks IF-Ausdr¨cke in SQL u +---------------+----------+------------+--------+ 5 rows in set (0. die f¨r M¨nner 180 EUR. -> IF(Geschlecht = ’w’.00 sec) Die Zulage f¨r Frauen soll 250 EUR betragen. Da nur Mann u u a und Frau unterschieden werden sollen.180) Eingebunden in das SELECT ergibt sich dieses: mysql> select MitarbeiterNr. Gehalt.250.7. Geschlecht. 250. brauchen wir ein klassisches 2-Wege-IF: IF(Geschlecht = ’w’. +---------------+----------+------------+--------+--------+ | MitarbeiterNr | Name | Geschlecht | Gehalt | Zulage | +---------------+----------+------------+--------+--------+ | 351 | Meier | m | 2000 | 180 | | 729 | M¨ller u | m | 1142 | 180 | | 921 | Guglhupf | w | 4500 | 250 | | 523 | Schmitt | w | 3488 | 250 | | 331 | Reeg | m | 2 | 180 | +---------------+----------+------------+--------+--------+ 5 rows in set (0. Name.00 sec) Christoph Reeg Seite 80 . 180) as Zulage -> from mitarbeiter.

Teil III Einfuhrung PHP ¨ Christoph Reeg Seite 81 .

in HTML2 eingebettete Scriptsprache . ob dazu eine Aktion o ¨ auf dem Server (wo die Webseite liegt) oder auf dem Client (wo die Webseite angezeigt wird) notwendig ist. A. ist zu uberlegen. Als Script werden Programme be” zeichnet. h. der die Seite ausu druckt (sofern JavaScript aktiviert ist). B. hat der Server. and the Universe trying to produce bigger and better idiots. A.8 PHP Grundlagen 8. der PHP-Code wird durch den Server ausgef¨hrt und die Ausgabe dann. Es ist auch m¨glich. Dies sind zwei vona 1 2 3 4 PHP Hypertext Preprocessor Hypertext Markup Language Beides kann zwar auch serverseitig laufen. enth¨lt f¨r gew¨hnlich keinen PHP-Code4 . die keine eigenst¨ndigen Programme sind.1 Einleitung Programming today is a race between software engineers striving to buy bigger and better idiot-proof programs. wobei sie dann PHP ersetzen. Immer wenn man sich fragt.oder mit anderen Worten: PHP-Scripte werden auf dem Server ausgef¨hrt. o u Im Gegensatz zu HTML und JavaScript erscheint der eigentliche PHP-Code i. der Serveradministrator oder der Scriptautor einen Fehler gemacht Christoph Reeg Seite 82 . wird es aber clientseitig eingesetzt Falls doch PHP-Code beim Client gelandet ist. den man sich im Browser auch ansehen kann. Da PHP aber auf dem Server ¨ ausgef¨hrt wird. an den Client gesandt. ob etwas m¨glich ist. the Universe is winning. zusammen mit den nicht interpretierten u HTML-Scriptanteilen. mit einem PHP-Befehl die aktuelle Webseite o auszudrucken? Die Antwort ist ganz einfach: Damit auf dem Client die Seite ausgedruckt wird. kann es diesen Befehl folglich nicht selbst in die Tat umsetzen. nicht auf der Clientseite. a u o wie bei normalen Seiten auch. jetzt wird PHP erkl¨rt. PHP-Scripte ganz ohne o (sichtbare) Ausgabe laufen zu lassen . zum ublichen u ¨ 3 . das einen Befehl anbietet. Der HTML-Code wird beim Abruf der Webseite.: Ist es m¨glich. A. JavaScript ausgef¨hrt. Auf dem u Client wird aber z. im Gegensatz z. der Quellcode. d.was durchaus sinnvoll sein kann. 1:1 an den Client geschickt. muß dem Browser ein Befehl ubermittelt werden. B. Der Programmcode wird in die HTML-Quelldatei geschrieben und JavaScript und Java somit i. So far. o Im vorigen Kapitel wurde SQL beschrieben. Rich Cook PHP1 ist eine serverseitige. B. F¨r viele andere Aktionen ist aber nicht einmal u JavaScript n¨tig. nicht in einer extra PHP-Datei“ abgelegt. weil sie nicht kompliziert genug sind a und andere Programme ben¨tigen. um ausgef¨hrt zu werden. Z. I.

Die Sprache PHP ist haupts¨chlich von C.php“ ¨ ” ” ” gebr¨uchlicher. die erst einmal nichts miteinander zu tun haben5 ! Auch a wenn es Funktionen in beiden Sprachen gibt. Im obigen Beispiel wird jeweils Hello world!“ ausgegeben. sie ist kurz. da der Server sonst versucht. 8. Im weiteren Verlauf wird gezeigt. u u ihn als PHP-Befehl zu interpretieren. m¨ssen jeweils der Anfang und das Ende des u u PHP-Teils gekennzeichnet werden. ?> 2 <? php echo ” H e l l o w o r l d ! ”. to quote: zitieren Christoph Reeg Seite 83 . die ¨hnlich heißen.‘ abgeschlossen und a eine Funktion bzw. bei PHP4 ist dagegen . muß nat¨rlich in Anf¨hrungsstrichen stehen. ?> 3 < script language = ”php ”> echo ” H e l l o w o r l d ! ”. Bei den Anf¨hrungsstrichen gibt es zwei verschiedene: einmal das einfache ’“ und u ” das doppelte ” Es gibt auch einen Unterschied zwischen den beiden: Bei den doppelten “. der Strings ausgibt. die diese o Variante nicht erkennen.8. Außerdem gibt es Server. wie man die beiden Programmiersprachen zusammenf¨hrt. Damit der Server weiß. </ script > Die erste M¨glichkeit ist die k¨rzeste und damit bei vielen die beliebteste (wer ist nicht o u gerne faul?). u u was SQL und was PHP ist. so daß sp¨ter Probleme auf den Proa grammierer zukommen k¨nnen. der ausgegeben ” werden soll. ” 5 6 7 SQL ist dem Sinn und Zweck nach viel weniger eine Programmiersprache als PHP Extensible Markup Language. aber auch von Java und Perl (die ihrerseits a von C beeinflußt wurden) gepr¨gt.php3“ und .1 Der echo-Befehl Den wichtigsten Befehl haben wir oben schon verwendet: den echo-Befehl. Daf¨r gibt es drei M¨glichkeiten: u o 1 <? echo ” H e l l o w o r l d ! ”. Damit der Server dar¨ber hinaus noch weiß.phtml“ ublich.2. k¨nnen sie sich doch a o deutlich unterscheiden. eine HTML nicht un¨hnliche Ausdruckssprache zum einheitlichen und a doch hochflexiblen Speichern von Daten aller Art von engl. Sie ist allerdings nicht XML6 -konform. Auch dann muß man sich weiter im Klaren dar¨ber sein. in welcher Datei er nach PHP-Scripten suchen soll. Ich benutze immer die zweite Variante. Bei PHP3 waren . m¨ssen die Dateien die richtige Endung (Extenu sion) haben. welche u Ausdr¨cke er in der Datei interpretieren soll. Aber auch f¨r Pascal/Delphi-Programmierer ist die a u Sprache nicht schwer zu erlernen. PHP Grundlagen Grundbefehle einander unabh¨ngige Sprachen. Grunds¨tzlich gilt (merken!): Eine Anweisung wird immer mit einem ‘. Dieses Vorgehen wird Quoten oder Quoting7 genannt. wenn man sie benutzt. einen Funktionsaufruf erkennt man an runden Klammern ‘()‘. 8.2 Grundbefehle PHP wird einfach in den HTML-Quellcode geschrieben. aber dennoch XML-konform. daß er jede beliebige a u Endung als PHP-Script identifiziert. Man kann nat¨rlich den Webserver so konfigurieren. Der Text.

print ( $ v a r 1 .3 Zuweisungen Wenn man der Variablen $a den Wert der Variablen $b zuweisen will. wohingegen print ein Ausdruck (Expression) ist. a 8 engl. in allen Teilstrings zu escapen.2. direkt aus. $ v a r 2 = ”Welt ! ”. Christoph Reeg Seite 84 . ” ”.2 Der print-Befehl Neben dem echo. das zweite hingegen Die ” ” Variable 123 hat den Wert 123!“ mit folgendem Zeilenumbruch. erfahren wir daher noch sp¨ter. echo ist ein internes Sprachkonstrukt. echo $ v a r 1 . print kann nur genau ein Argument haben. ” ”.6. ” ”. Dieses Vorgehen nennt man Escapen8 .2. $ v a r 2 ).8. echo ”Say \ ”Hello World \ ” my f r i e n d ”. in diesem Fall PHP. bei den einfachen hinu gegen behandelt er ihn nicht speziell. muß man dies mithilfe des Gleichheitszeichens machen. echo $ v a r 1 . 8. sondern gibt ihn z. 8. PHP Grundlagen Grundbefehle Anf¨hrungsstrichen versucht der Server. B.2. Das bedeutet aber auch. echo ’ D i e V a r i a b l e $ v a r h a t den Wert 1 2 3 ! \ n ’ .gibt es auch den print-Befehl. Es ist insbesondere f¨r das Ausgeben von u HTML-Quelltext in Verbindung mit echo und print n¨tig und kann u. wenn man vergißt. Die Ausgabe bei diesem echo ist “Say “Hello World!“ my friend“. $ v a r 2 . echo kann mehrere Argumente haben. wie man dies erreicht. m¨su sen doppelte Anf¨hrungsstriche. die nicht in Klammern stehen d¨rfen. besonders gekennzeichnet u werden. U. daß man Vergleiche in PHP nicht mit dem einfachen Gleichheitszeichen machen kann. $ v a r 2 . u Alle folgenden Anweisungen sind zul¨ssig und geben dasselbe aus: a $ v a r 1 = ” H a l l o ”.4. $ r e s = print ( $ v a r 1 . den Text zu interpretieren. Weitere Erkl¨rungen a zu Anf¨hrungszeichen finden sich in Kapitel 8. Wie man sieht. Im Endeffekt leisten beide dasselbe: Sie geben Text aus. ” ”. zu Problemen o f¨hren. $ v a r 2 ). u $ v a r = 123. Hintergrund: Das escapete Zeichen entkommt“ der vorgesehenen Inter” pretierung durch die Sprache. to escape: entkommen. Das erste echo gibt Die Variable $var hat den Wert 123!\n“ aus. echo ” D i e V a r i a b l e $ v a r h a t den Wert 1 2 3 ! \ n ”. Siehe auch Kapitel 13 (Fehleru suche). die ausgegeben werden sollen.

Bit-. Ist ein Operand eine Kommazahl. 1. bestimmte Bits in einer Integervariablen zu setzen. 8.2. $ i --: // // // // entspricht entspricht entspricht entspricht $a $a $i $i = = = = $a $a $i $i + ∗ + − 5.$b $a * $b $a / $b $a % $b Name Addition Subtraktion Multiplikation Division Modulo Ergebnis Summe von $a und $b Differenz von $a und $b Produkt von $a und $b Quotient von $a und $b Rest der Division von $a und $b Tabelle 8.4.4. wird das Ergebnis auch eine Kommazahl. “noch etwas Text“‘ abk¨rzen: u $a = ” H e l l o ”. $a *= 2. ist das Ergebnis ebenfalls integer.(Text). ”World ! ”. 8.4. String. wird irgendwann langweilig.4 Operatoren Nur irgendwelche Werte in irgendwelche Variablen zu schreiben. 8.2. $a = ” H e l l o ”.1 Arithmetische Operatoren Beispiel $a + $b $a . 1. // j e t z t i s t $b = ” H e l l o World ! ” Auch hier lassen sich Befehle der Form ‘$a = $a . $b = $a . $ i ++.8. logischen (booleschen) und Vergleichs-Operatoren unterscheiden.2. 8. Deshalb gibt es auch ein paar Operatoren.1: Arithmetische Operatoren in PHP Wenn beide Operanden bei der Division vom Typ integer (ganzzahliger Wert) sind. Christoph Reeg Seite 85 . PHP Grundlagen Grundbefehle $a = $b .2 String-Operatoren Es gibt nur einen echten String-Operator: den Verbindungsoperator (‘. Befehle wie ‘$a = $a + 5‘ kann man etwas abk¨rzen: u $a += 5.‘). Dabei muß man zwischen den arithmetischen (Zahlen). 2.3 Bit-Operatoren Bitweise Operatoren erlauben es.2.= ”World ! ”. $a .

wenn true. weil die Sprache (in diesem Fall PHP) u erkennt. indem man h¨ufiger wahr werdende oder weniger Laufzeit in Anspruch a nehmende Ausdr¨cke weiter vorne (links) hinschreibt. h.8. der zu false evaluiert. ausnutzen. einer ($a oder $b) true ist genau einer ($a oder $b) true ist $a false ist beide ($a und $b) true sind mind. 8. nicht das Skript!). B.2. Diesen Umstand kann man u z. daß logische Verkn¨pfungen mittels der angegebenen Operau toren immer von links nach rechts evaluiert (ausgewertet) werden. was zu true oder false evaluu u ieren kann). Der Fachbegriff hierf¨r lautet Kurzschlußlogik. die rechts von einem stehen.3: Logische Operatoren in PHP Der Unterschied zwischen den beiden UND und ODER liegt in deren Priorit¨t verglichen a mit anderen Operatoren. ” Beispiel $a and $b $a or $b $a xor $b !$a $a && $b $a || $b Name UND ODER Exklusiv-ODER NICHT UND ODER Ergebnis true. B. in einem Ausdruck! a Ganz analog verh¨lt es sich bei ODER-Verkn¨pfungen: Wird hier einer der booleschen a u Ausdr¨cke wahr. boolesche Operatoren werden zum Beispiel zum Verkn¨pfen von mehreren u Vergleichen bei einer Bedingung ben¨tigt. wenn true.4. werden die anderen nicht mehr bearbeitet. daß der boolesche Ausdruck nicht mehr wahr werden kann und deshalb gleich abbricht (nur die Evaluierung. Das ist wichtig zu wissen. gar nicht erst abgefragt.2. PHP Grundlagen Grundbefehle Beispiel $a & $b $a | $b ~$a Name UND ODER NICHT Ergebnis Bits. werden gesetzt Bits. wenn beide ($a und $b) true sind mind. Christoph Reeg Seite 86 . denn so kann man bestimmte Voraussetzungen abfragen. bevor man z. B. daß diese Kurzschlußlogik nicht bei den bitweisen Operatoren & und | zum Einsatz kommt. true“ ist ubrigens der Wahrheitswert. wenn true. dessen o ¨ ” Verneinung lautet false“.4 Logische Operatoren Logische bzw. wenn true. u Zu beachten ist. eine Funktion aufruft oder eine Abfrage startet. einer ($a oder $b) true ist Tabelle 8. die in $a oder $b gesetzt sind.4. wenn true. d. werden gesetzt Bits. die in $a und $b gesetzt sind. die in $a gesetzt sind. die von einem Parameter abh¨ngt – und das alles z.5 Kurzschlußlogik Wichtig ist auch zu wissen. bei einer UNDVerkn¨pfung (&&) werden alle booleschen Ausdr¨cke (alles.2: Bit-Operatoren in PHP 8. werden nicht gesetzt und umgekehrt Tabelle 8.

Der Variablentyp kann auch bei der ersten Benutzung festgelegt werden. In Tabelle 8.2. a Es gibt auch noch das hexadezimale System (Basis: 16) und Oktalsystem (Basis: 8). Die erste und die letzte Zeile sind Befehle. Wird einer Integervariablen ein Wert außerhalb des oben genannten Wertebereichs zugewiesen. ina dem er davor in Klammern angegeben wird.648 bis +2.8.482. der Rest sind Kommentare. double. die in Kapitel 8.2.4: Typen in PHP int. F¨r uns sind sie im Moment eher weniger interessant. integer real. den es f¨r u richtig h¨lt. PHP verwendet den Typ. was wir meinen. Man kann Zahlen nicht nur in dem uns gel¨ufigen Dezimalsystem (Basis: 10) eingeben.7 beschrieben werden.2. /∗ D i e s i s t e i n Kommentar .double‘. wird bei Hexadezimalzahlen ein 0x“ und bei Oktalzahlen eine ” 0“ vorangestellt.6 Variablen God is real. Tabelle 8. PHP Grundlagen Grundbefehle 8.6. d e r a uch u e b e r m e h r e r e Z e i l e n g e h e n kann ∗/ // D i e s i s t w i e d e r e i n Kommentar . a u Christoph Reeg Seite 87 .2.5 Kommentare F¨r Kommentare gibt es zwei M¨glichkeiten der Schreibweise: u o echo ”Noch k e i n Kommentar ! ”. // d e r j e w e i l s b i s zum Ende d e r Z e i l e g e h t echo ”Kein Kommentar mehr ! ”. Diese Zahlensysteme werden h¨ufig wegen ihrer st¨rkeren Hardwarea a ” N¨he benutzt. 8.147. Die Variablen m¨su sen nicht vorher definiert oder deklariert werden.147.647 (entspricht −231 − 1 bis +231 ) als Wert annehmen. float boolean string array object Integer Double Boolean String Array Objekt 8.482. Damit PHP weiß.4 sind die verf¨gbaren Typen u aufgelistet. Neben Variablen gibt es noch Konstanten. erfolgt die Umwandlung in den Typ . unless declared integer Alle Variablen werden durch ein vorangestelltes ‘$‘ gekennzeichnet.1 Integer Eine Integer-Variable kann (auf 32-Bit-Maschinen) alle ganzen Zahlen im Bereich von -2.

Eine Ubersicht der escaped characters gibt es in ” Tabelle 8. ASCII-Code 0x09) Backslash Dollar-Zeichen doppeltes Anf¨hrungszeichen u Tabelle 8. d e r u m g e w a n d e l t werd en s o l l ∗ @return array Array m i t den e i n z e l n e n B u c h s t a b e n ∗ des Textes 9 engl.6. CR.2.7E308 bis ca.Float‘.2.7E308 (entspricht −21024 − 1 bis 21024 − 1) mit einer Genauigkeit von grob 14 Stellen.4 String In Strings werden Buchstaben-/Zeichenketten gespeichert. wird mit $string[n] auf das n-te Zeichen im String zugegriffen. muß der String erst konvertiert werden. B.Boolean‘ eingef¨hrt worden.8. PHP Grundlagen Grundbefehle 8. weil es sonst den String beenden w¨rde. -1. Erfordert eine Funktion als Parameter nun unbedingt ein richtiges Array.1‘ interpretiert. Buchstaben mit einem vorangestellten Backslash werden u ¨ als escaped characters9“ bezeichnet.2 Double/Float F¨r reelle Zahlen gibt es den Datentyp . 8.Double‘ bzw. Um z. 1. Dadurch kann man problemlos auf einzelne Zeichen zugreifen. Die einfachste mir bekannte M¨glichkeit ist mit Hilfe o einer kleinen for-Schleife (hier in eine Funktion verpackt): /∗ ∗ ∗ Die F u n k t i o n w a n d e l t e i n e n S t r i n g i n e i n Array um ∗ und g i b t d i e s e s z u r u c k ¨ ∗ ∗ @param string Der T e x t . ASCII-Code 0x0A) carriage return (Abk. character: Buchstabe (wird h¨ufig auch als char abgek¨rzt) a u Christoph Reeg Seite 88 . muß ihr Inhalt in Anf¨hrungszeichen geschrieben werden (siehe auch Kapitel 8.6. innerhalb der u Anf¨hrungszeichen eines echo. muß dieses mit einem Backslash (\) versehen werden. ASCII-Code 0x0D) horizontaler Tabulator (Abk. B.5: escaped characters Auch bei den einfachen Anf¨hrungszeichen gibt es escaped characters: Es k¨nnen genau u o zwei verwendet werden. Wenn man Strings definiert. a u Ein String ist im Prinzip ein Array aus Zeichen.6. daß es ausgegeben wird).5.2. u Betrachten wir als erstes die doppelten Anf¨hrungszeichen (“). Z.1). . HT.oder print-Befehls ein Anf¨hrungszeichen zu schreiben u u (so. n¨mlich \‘ (einfaches Anf¨hrungszeichen) und \\ (Backslash). \n \r \t \\ \$ \” line feed: neue Zeile (Abk. Der Wertebereich geht (auf u 32-Bit-Maschinen) von ca. LF. PHP3 hat den booleschen u Wert true“ als Integer mit dem Wert . ” 8.2.3 Boolean Mit PHP4 ist auch der Datentyp .

6 Array Ein Array ist eine n-dimensionale Liste. PHP Grundlagen Grundbefehle ∗/ function str2array ( $ t e x t ){ $ a r = array (). Wieso aber u ” eine 7“ ausgegeben wird. Beim letzten ist es allerdings schon schwieriger. u 8.2. In der Regel ist das auch kein großes Problem. Mehr zu Funktionen im Kapitel 8. Was soll das heißen? Nehmen wir folgendes Beispiel: $monat [1] $monat [2] $monat [3] $monat [4] $monat [5] = = = = = ” J a n u a r ”. bei ganzen Zahlen ergeben a sich keine Rundungsfehler beim Wandeln von Dezimalsystem in das Dualsystem. ” Die l¨ngere Version: Computer rechnen intern im Dualsystem. 0 xbad . 0123. a 8.-) . Eigentlich w¨rde man als Ausgabe doch eher eine 8“ erwarten. ”Maerz ”. Die ersten Werte sind noch einfach nachzuvollziehen. $ i < strlen ( $ t e x t ). ”Mai ”. kann man in Worte gefaßt einfach Rundungsfehler nennen. ” A p r i l ”. $ i ++){ $ a r [] = $ t e x t [ $ i ]. In diesem Beispiel tritt gerade so einer auf. muß man Integer als Datentyp nehmen.7. ( double ) $a .6. u $a $b $a $a // $a i s t e i n I n t e g e r // $b i s t e i n D o u b l e m i t dem Wert 1 2 3 4 // O k t a l z a h l ( e n t s p r i c h t 8 3 d e z i m a l ) // H e x a d e z i m a l z a h l // ( e n t s p r i c h t 2 9 8 9 d e z i m a l ) echo floor ((0. Wenn es zu keinen Rundungsfehlern kommen darf.7)*10).6. zum Beispiel kann man Preise einfach in Euro Cent abspeichern und schon braucht man keine Nachkommastellen mehr.8.5 Beispiel Ein kleines Beispiel zu den bis hierher beschriebenen Datentypen: Die Funktion int floor(float number) schneidet die Nachkommastellen ab und gibt einen Integer zur¨ck. Christoph Reeg Seite 89 . ” F e b r u a r ”. Das soll uns aber nicht weiter st¨ren.1+0. Bei der Darstellung als Fließkommazahl (float) kommt es aber gelegentlich schon zu Rundungsfehlern. } Die bisher unbekannten Befehle sollen erstmal nicht weiter st¨ren. Ich habe dieses Beispiel hier nur zur allgemeinen o Verwirrung eingef¨gt . for ( $ i =0. // A u s g a b e i s t 7 = = = = 1234. } return $ a r .2. sie werden weiter o unten erkl¨rt.

$monat [10] = ” O k t o b e r ”. PHP Grundlagen Grundbefehle $monat [6] = ” J u n i ”. Oder als Tabelle: Zeile 1 2 3 4 5 6 7 8 9 10 11 12 Name Januar Februar Maerz April Mai Juni Juli August September Oktober November Dezember Bei dieser Tabelle spricht man von einer 1-dimensionalen Tabelle. $monat [9] = ” S e p t e m b e r ”. $monat [11] = ”November ”. braucht man eine 2-dimensionale Tabelle: Zeile 1 2 3 4 5 6 7 8 9 10 11 12 Und das 10 Name Tage Januar 31 Februar 28 Maerz 31 April 30 Mai 31 Juni 30 Juli 31 August 31 September 30 Oktober 31 November 30 Dezember 31 ganze in PHP: Schaltjahre werden der Einfachheit einfach mal nicht beachtet Christoph Reeg Seite 90 . Wenn man neben dem Monatsnamen auch die Anzahl der Tage10 im jeweiligen Monat abspeichern will. $monat [12] = ”Dezember ”. weil eine Koordinate (die Zeilennummer) ausreicht. $monat [7] = ” J u l i ”. um jedes Feld eindeutig zu bestimmen. Der Index (=Zeilennummer) wird in eckigen Klammern hinter dem Array-Namen angegeben. $monat [8] = ”August ”.8.

Folgendes Beispiel sollte das Gesagte verdeutlichen: 1 $ v a r = ” v a r i a b l e r Wert ”. B. $monat [5][ ”Tage ”] = 31. $monat [10][ ”Tage ”] = 31. $monat [8][ ”Tage ”] = 31.7 Konstanten In PHP gibt es neben Variablen auch Konstanten. PHP Grundlagen Grundbefehle $monat [1][ ”Name ”] = ” J a n u a r ”. string Primitivtypen sind z. im Gegensatz z. $monat [10][ ”Name ”] = ” O k t o b e r ”. $monat [2][ ”Tage ”] = 28. zu Arrays oder Objektreferenzen. 4 echo $ v a r . werden also nicht mit einem Dollarzeichen eingeleitet. Weitere Una ¨ terschiede zu Variablen sind.8. $monat [8][ ”Name ”] = ”August ”. dazu sp¨ter mehr a Christoph Reeg Seite 91 . $monat [12][ ”Tage ”] = 31. sondern nur Daten in ihnen speichern. $monat [7][ ”Tage ”] = 31. 3 $ v a r = CONST .: integer. n¨mlich mittels einer PHPa a Funktion namens define(). 11 12 Skalare Datentypen sind u. $monat [1][ ”Tage ”] = 31. String oder Integer. B. f¨r die Indizes beliebige skalare11 Datentypen verwenden. Als ersten Parameter ubergibt man dieser Funktion den Na¨ men der zu definierenden Konstante und als zweiten deren Wert. $monat [9][ ”Tage ”] = 30. o Wie kann man sich n-dimensionale Arrays vorstellen? Bei 3 Dimensionen ist es noch relativ einfach: Nimmt man mehrere 2-dimensionale Arrays und legt diese aufeinander. Zum anderen kann man bei PHP. außerdem sind sie uberall abrufbar. In diesem Beispiel sehen wir zwei wichtige Eigenschaften von Arrays in PHP: Zum einen werden bei mehreren Dimensionen die Indizes einzeln in eckigen Klammern hinter dem Array-Namen angegeben. $monat [4][ ”Name ”] = ” A p r i l ”. Bei Konstanten ist. Dadurch u werden sogenannte assoziative Arrays m¨glich. $monat [3][ ”Tage ”] = 31. $monat [6][ ”Name ”] = ” J u n i ”. und sind v¨llig unabh¨ngig von Variablen gleichen Namens. a Konstanten werden auch grunds¨tzlich anders definiert. ” k o n s t a n t e r Wert ”). 8. $monat [7][ ”Name ”] = ” J u l i ”. der Wert nicht ver¨nderlich. $monat [3][ ”Name ”] = ”Maerz ”. $monat [11][ ”Tage ”] = 30. $monat [6][ ”Tage ”] = 30. nimmt man daher f¨r die Namen von Konstanten u h¨ufig nur Großbuchstaben. hat man die 3. Ab der 4. $monat [9][ ”Name ”] = ” S e p t e m b e r ”. Um o a die Unterscheidung deutlich zu machen. daß Konstanten nur Werte von Primitivtypen12 annehmen k¨nnen und uberhaupt grunds¨tzlich von Variablen unterschieden werden m¨ssen: Kono a u ¨ stantennamen bestehen nur aus alphanumerischen Zeichen. Dimension wird das schon etwas schwerer. $monat [4][ ”Tage ”] = 30. a. $monat [2][ ”Name ”] = ” F e b r u a r ”. im Gegensatz zu gew¨hnlichen o Programmiersprachen. 2 define ( ”CONST”. wie der Name schon sagt. $monat [5][ ”Name ”] = ”Mai ”. $monat [12][ ”Name ”] = ”Dezember ”.2. Aber im Zweifelsfall muß man sich die Arrays nicht vorstellen. Dimension. $monat [11][ ”Name ”] = ”November ”.

. Der Beispielcode w¨rde zu keinem Problem f¨hren. // $Auto = ” C a b r i o ” // a l t e r n a t i v e S y n t a x Nat¨rlich darf man bei diesem Vorgehen nicht gegen die Regeln f¨r die Vergabe von u u Variablennamen verstoßen. d. 8. gleichzeitig hat durch die Zuweisung in Zeile 3 auch $var den Wert der Konstante angenommen13 . wenn man den Wert bestehender Variablen mit festen Strings kombiniert um damit einen neuen Variablennamen zu erzeugen:14 $ o b j e k t = ”Auto ”. denn in unserer sch¨nen Skriptsprache ist das gar kein Problem: o $ o b j e k t = ”Auto ”. Christoph Reeg Seite 92 . was per definitionem nicht erlaubt a u ist: einer Konstanten einen neuen Wert zuweisen. B. o in PHP zu programmieren. h. die Namen von Funktionen bzw. kommt man auch nicht so schnell durcheinander. ausgewertet werden. u Nat¨rlich kann man auch mit dem Stringoperator . Innerhalb der geschweiften Klammern macht man hier von dem Umstand Gebrauch.-) a Man kann tats¨chlich sogar soweit gehen. PHP Grundlagen Grundbefehle 5 $CONST = ”Problem ? ”. $ $ o b j e k t = ” C a b r i o ”. dem durch das Dollarzeichen eine besondere Bedeutung zugewiesen wird. u a Wirklich interessant wird es aber erst.2. wenn man diesen a o String wieder mit Hilfe anderer Variablen zusammenzusetzen. was man erwartet – will man nun den ersten Eintrag aus $array als Namen f¨r u eine andere Variable benutzen oder nicht vielmehr den ersten Eintrag aus dem Array 13 14 Das heißt aber nicht. Dann n¨mlich w¨rde etwas versucht. Somit liegt es gar nicht so fern. daß Variablen in Strings.8. u Bei Arrays ist schließlich noch zu beachten. den man als Namen einer anderen Variable benutzen m¨chte. . Methoden (in der OOP) a mittels Variablen zusammenzusetzen. der String. nicht mit einer Zahl beginnen. die in doppelten Anf¨hrungsstrichen stehen. $ { ” m e i n $ o b j e k t ”} = ” C a b r i o ”. . . In diesem Fall w¨re es doch eine sch¨ne Sache. denn CONST hat weiterhin den Wert. daß $$array[0] vielleicht nicht immer das macht. da der Name der neuen Variable o dann ung¨ltig w¨re. andererseits aber auch leicht verwirrende M¨glichkeit. . . Da in PHP f¨r die Definition einer u Konstanten jedoch eine Funktion benutzt wird. darf z. wenn man in der letzten Zeile das Dollaru zeichen entfernte. . arbeiten. . daß nun die Variable wirklich einen konstanten Wert h¨tte . Das dachten sich sicher auch die PHP-Erfinder. Bei diesem Konzept nutzt man die Eigenschaft des Wortcharakters“ von Variablennamen aus: Der Name einer Variablen ist ” ja eigentlich auch nur ein String. die denselben Namen hat wie die Konstante.8 Variable Variablen Eine einerseits sehr vorteilhafte. So sollte man jedoch ausdr¨cklich nicht programmieren! Es sollte u nicht allzu schwierig sein. diesen Variablennamen selbst als einfachen String aufzufassen. // $meinAuto = ” C a b r i o ”. einen anderen Namen zu finden . Durch die letzte Zeile wird einfach eine neue Variable angelegt. . u u der der Konstante mittels define() zugewiesen wurde. Zu einem Fehler w¨rde es erst dann kommen. sind variable Variablen. Das wollen wir aber nicht vertiefen . $ { $ o b j e k t } = ” C a b r i o ”.

entweder die eckigen Klammern mitsamt der Indexangabe (z. B. Zwei Variablen sind demnach z. Als Beispiel: u if ( $a > $b ) print ”a i s t g r o e s s e r a l s b ”. wenn sie dieselbe Zahl als Wert abgespeichert haben – egal. [0]) in die geschweiften Klammern schreiben oder dahinter.4.9.2. wenn ihr Inhalt gleich aussieht“. B. Christoph Reeg Seite 93 . So kommt es auch. a a u ¨ Dazu gibt es in PHP die Operatoren === (gleicher Wert und Typ) und !== (weder gleicher Wert noch Typ). Daß das zu unerw¨nschten Effekten f¨hren kann (Intentionsfehler). ob einmal u als Integer und einmal als String oder beidesmal z. die Syntax ist identisch zu C: if (expr) statement ‘expr‘ ist Platzhalter f¨r die Bedingung und ‘statement‘ f¨r den Befehl. 8.1) wurden bereits die g¨nigen Operatoren f¨r Zuweisungen behandelt. als Integer. ” gleich bez¨glich ==. daß Variablen verschiedener Typen i. h. Umgehen l¨ßt sich dieses Problem. indem man die alternative Syntax mit den geschweiften Klammern benutzt. d. 8. ben¨tigt man jedoch o zus¨tzlich Vergleichsoperatoren: a == != > < >= <= Gleich Ungleich Gr¨ßer o Kleiner Gr¨ßer gleich o Kleiner gleich Tabelle 8.1.1 Typensichere Vergleiche PHP ist von sich aus erst einmal eine nicht streng typisierte Sprache. auch der u Leerstring ““. schon dann gleich im Sinne von == sind. Das bedeutet im Zusammenhang mit Vergleichen.9 Vergleichsoperatoren Weiter oben (8.2.6: Vergleichsoperatoren in PHP 8. zeigt ein u u Codebeispiel in Kapitel 9. daß jeder String bez¨glich == gleich der Integerzahl 0 ist. dessen Name derselbe ist wie der Wert von $array? Diese Problematik l¨ßt a sich leicht umschiffen. indem man zus¨tzlich auf Typgleichheit uberpr¨ft. F¨r a u u das folgende Kapitel. der bei erf¨llter u u u Bedingung ausgef¨hrt werden soll.10 IF Die IF-Abfrage ist eines der wichtigsten Elemente der Programmierung. in dem zum ersten Mal Vergleiche vorkommen. PHP Grundlagen Grundbefehle betrachten.8. B. A.2.

Analog zu IF kann man auch hier mehrere Befehle pro Zweig (IF. so ist auch das m¨glich. u Kombinationen (z.2.8. PHP Grundlagen Grundbefehle Falls man mehr als einen Befehl hat. oder aber den ELSE-Zweig verwenden: if ( $a > $b ) print ”a i s t g r o e s s e r a l s b ”. . 8. um einheitlich zu programmieren. die abh¨ngig von einer Bedingung alternativ ausgef¨hrt a u werden sollen. so kann man entweder zwei IF-Abfragen mit gegens¨tzlichen Bedingungen a nehmen. Am Beispiel wird dies hoffentlich deutlich: if ( $a > $b ) print ”a } elseif ( $a print ”a } else { print ”a } { i s t g r o e s s e r a l s b ”. u o Man muß die Befehle nur in geschweifte Klammern einschließen: if ( $a > $b ) { print ”a i s t $b = $a . if ( $a <= $b ) print ”a i s t n i c h t g r o e s s e r a l s b ”. ist k l e i n e r a l s b ”. Christoph Reeg Seite 94 . == $b ) { i s t g l e i c h b ”. Man kann nat¨rlich auch nur einzelne Befehle in geschweifte Klammern einschließen u (und sei es nur. if ( $a > $b ) print ”a i s t g r o e s s e r a l s b ”. ELSE) angegeben. geschweifte Klammern bei IF. B. der ausgef¨hrt werden soll. oder Fehler beim Erweitern zu vermeiden). .12 ELSEIF ELSEIF ist eine Kombination aus ELSE und IF. else print ”a i s t n i c h t g r o e s s e r a l s b ”. aber keine bei ELSE) sind m¨glich.11 ELSE Wenn man zwei Anweisungen hat. . } g r o e s s e r a l s b ”. . in diesem Fall m¨ssen diese Anweisungen in geschweiften Klammern geschrieben werden. .2. o 8.

Allgemein: (Bedingung?R¨ckgabewert wenn true:R¨ckgabewert wenn false) u u An einem konkreten Beispiel: <? php echo ( $a < $b ? ”a i s t ?> k l e i n e r a l s b ”: ” ”). daß eine bestimmte Bedingung erf¨llt ist. bietet sich eine alternative Syntax an: <? php if ( $a < $b ): ?> < h1 > a ist kleiner als b </ h1 > <? php endif . u u wird die Anweisung uberhaupt nicht ausgef¨hrt. wird u die Anweisung ‘statement‘ ausgef¨hrt.15 WHILE WHILE-Schleifen sind die einfachsten Schleifen in PHP. Es gibt Stellen.2.2. Hier machen geschweifte Klamo mern nat¨rlich keinen Sinn. beide geben die Zahlen von 1 bis 10 aus. bei der Funktion printf. ENDIF. die zur selben WHILE-Schleife geh¨ren.. Die Grundform der WHILE-Schleife ist die folgende: WHILE (expr) statement Die Bedeutung der WHILE-Schleife ist einfach: Solange die Bedingung ‘expr‘ erf¨llt ist. in geschweifte Klammern eingeschlossen o werden.8.8. ?> Der HTML-Text wird nur dann ausgegeben.1 beschrieben wird). Christoph Reeg Seite 95 .14 Alternative Syntax f¨r IF: (?:) u Wenn man je nach Bedingung bestimmte Werte haben will. Man kann auch die alternative Syntax nehmen: WHILE (expr) : statement . Falls die Bedingung von Anfang an nicht erf¨llt ist. Analog zu IF m¨ssen mehrere Anweiu u ¨ sungen. PHP Grundlagen Grundbefehle 8. . . 8..2. kann man auch die Kurzsyntax verwenden. wenn die Bedingung A kleiner B“ erf¨llt ist. ENDWHILE. ganze HTML-Bl¨cke u o ausgeben will. u ” Es k¨nnen auch mehrere HTML-Zeilen benutzt werden. wie auch im folgenden Fall. Das Ergebnis der folgenden Beispiele ist identisch. B. u Falls man in dem Fall. u 8.13 Alternative Syntax f¨r IF: IF(): . die in Kapitel 8. wo sich diese Syntax sehr gut eignet (z. Zu h¨ufige Anwendung f¨hrt aber oft auch zu sehr a u schlecht lesbarem Code.

WHILE DO . Damit initialisiert u man in der Regel die Variable. while ( $ i <=10): print $ i .2.16 DO . do { print $ i . expr3) statement Der erste Ausdruck ‘expr1‘ wird genau einmal. Die Syntax ist identisch mit der in C: FOR (expr1. Der zweite Ausdruck ‘expr2‘ wird am Anfang jedes Schleifendurchlaufs uberpr¨ft. am Anfang.WHILE-Schleife ist vom Prinzip her identisch mit REPEAT UNTIL. wird die Schleife ausgef¨hrt. 15 Wer sich uber den Namen wundert: das englische for“ hat neben dem allgemein bekannten f¨r“ auch u ¨ ” ” noch eine andere. es werden allerdings erst die Ana weisungen ausgef¨hrt und dann wird die Bedingung uberpr¨ft. endwhile .. wenn nicht.WHILE-Schleifen sind den WHILE-Schleifen ¨hnlich. Am Ende jedes Schleifendurchlaufs wird der dritte Ausdruck ‘expr3‘ ausgef¨hrt. 8. $ i ++. Ein kleines Beispiel: u u ¨ $ i =0. Wenn u ¨ die Bedingung erf¨llt ist. PHP Grundlagen Grundbefehle /∗ B e i s p i e l 1 ∗/ $ i =1.. expr2. u Jeder Ausdruck kann auch leergelassen werden. wird abgebrochen. while ( $ i <=10) { print $ i ++. 8.. ausgef¨hrt.2.8.17 FOR FOR-Schleifen15 sind die kompliziertesten Schleifen in PHP. B. // $ i w i r d g e n a u e i n m a l a u s g e g e b e n F¨r Pascal/Delphi-Kenner: u Die DO .. mit f¨r die Dauer von“ ubersetzt! u ¨ ” Christoph Reeg Seite 96 . . zeitliche Bedeutung und wird dann z. } while ( $ i >0). // $ i w i r d e r s t a u s g e g e b e n und // dann i n k r e m e n t i e r t // I n k r e m e n t = N a c h f o l g e r // = um e i n s e r h o e h t ( b e i Z a h l e n ) } /∗ B e i s p i e l 2 ∗/ $ i =1. . Das u u ist die Laufbedingung.

8.) { if ( $ i >10) { break . while (expr2){ statement expr3. wie die Laufbedingung erf¨llt ist a u ($i muß kleiner/gleich 10 sein). die zur selben FOR-Schleife geh¨ren. } /∗ B e i s p i e l 3 ∗/ $ i =1. Im vierten Beispiel ist die FOR-Schleife u mit Hilfe von WHILE nachgebildet worden. for (. $ i <=10.. in u o geschweifte Klammern eingeschlossen werden. $ i ++. Die WHILE-Schleife l¨uft so lange. Allgemein ausgedr¨ckt (mit den oben verwendeten Bezeichnern) s¨he das dann so aus: u a expr1. } /∗ B e i s p i e l 2 ∗/ for ( $ i =1. while ( $ i <=10){ print $ i . Dann kommt die eigentliche Anweisung (Ausgabe der Christoph Reeg Seite 97 . $ i ++. } print $ i . } Das erste Beispiel ist nat¨rlich das geschickteste. $ i ++) { print $ i .. } Die folgenden Beispiele geben jeweils die Zahlen von 1 bis 10 aus: /∗ B e i s p i e l 1 ∗/ for ( $ i =1. } print $ i . } /∗ B e i s p i e l 4 ∗/ $ i =1. PHP Grundlagen Grundbefehle Analog zu IF m¨ssen mehrere Anweisungen. Die FOR-Schleife kann im Prinzip auch mit einer WHILE-Schleife nachgebildet werden. $ i ++) { if ( $ i > 10) { break . Wir sehen als erstes die Initialisierung ($i wird auf 1 gesetzt).

g l e i c h 1 ”.2. Anweisung f¨r Anweisung!) abu u gearbeitet. Bei der SWITCH-Anweisung wird Zeile f¨r Zeile (wirklich. um Fehler zu vermeiden.: u ¨ /∗ B e i s p i e l 3 ∗/ switch ( $ i ) { case 0: print ” i i s t case 1: print ” i i s t 16 g l e i c h 0 ”. Anweisungen uber den folgenden Fall auszuf¨hren.8. die Anweisungen bis an das Ende u a des SWITCH-Blockes auszuf¨hren oder bis es das erste Mal auf eine BREAK-Anweisung st¨ßt. 8. wie die SWITCH-Anweisung arbeitet.einmal mit einer Reihe von IFAnweisungen und einmal mit einer SWITCH-Anweisung gel¨st: o /∗ B e i s p i e l 1 ∗/ if ( $ i == 0) { print ” i i s t g l e i c h 0 ”. B. break . PHP Grundlagen Grundbefehle Variablenwerte) und als letztes wird $i inkrementiert16 . die Anweisungen auszuf¨hren. u o Wenn man keine BREAK-Anweisung an das Ende einer CASE-Anweisung schreibt. Z. } /∗ B e i s p i e l 2 ∗/ switch ( $ i ) { case 0: print ” i i s t g l e i c h 0 ”. case 1: print ” i i s t g l e i c h 1 ”. f¨ngt a PHP an. Die Anweisung ist ¨hnlich einer Serie von IF-Anweisungen mit denselben Ausa dr¨cken. Genau das erreicht eine SWITCH-Anweisung. Um eins erh¨ht o Christoph Reeg Seite 98 . wenn eine CASE-Anweisung u mit einem Wert gefunden wird. u Hier zwei Beispiele. die dasselbe Ergebnis ausgeben . der gleich dem Wert des SWITCH-Ausdruckes ist. Nur dann. break .18 SWITCH Die Funktion der SWITCH-Anweisung ist identisch mit der der CASE OF-Anweisung in Pascal/Delphi. Mit break wird die aktuelle Schleife verlassen. } Es ist wichtig zu wissen. } if ( $ i == 1) { print ” i i s t g l e i c h 1 ”. In vielen Situationen will man eine Variable oder einen Ausdruck mit vielen u Werten vergleichen und abh¨ngig von den Werten der Variablen unterschiedliche Befehle a ausf¨hren. f¨hrt PHP a fort. PHP f¨hrt fort. Am Anfang wird kein Code ausgef¨hrt.

break . break . Ein spezieller Fall ist der default-Fall. wie z. u a Dieses Verhalten kann aber auch bewußt genutzt werden. im folgenden: $ i = 0. u /∗ B e i s p i e l 4 ∗/ switch ( $ i ) { case 0: print ” i i s t break . w¨rden beide Anweisungen ausgegeben. als man es auf den ersten Blick erwartet. Dieser Fall trifft auf alles zu. } Gibt man hinter einem break eine Zahl (int) gr¨ßer Null an.8. diese Ano zahl an Ebenen hinauf (hinaus) zu springen. wird versucht. weil er sich anders a verh¨lt. g l e i c h 1 o d e r 2 ”. 1 ”. case 1: case 2: print ” i i s t } /∗ B e i s p i e l 5 ∗/ switch ( $ i ) { case 0: print ” i i s t case 1: case 2: print ” i i s t } g l e i c h 0 ”. Anwendung findet dies bei verschachtelten Schleifen. was in diesem Fall u nicht erw¨nscht w¨re. PHP Grundlagen Grundbefehle } Falls $i gleich 0 sein sollte. default : print ” i i s t u n g l e i c h 0 . a /∗ B e i s p i e l 6 ∗/ switch ( $ i ) { case 0: print ” i i s t g l e i c h 0 ”. Christoph Reeg Seite 99 . case 1: print ” i i s t g l e i c h 1 ”. Von daher sollte man das entweder a vermeiden oder ein paar Kommentare einf¨gen. was nicht von den anderen F¨llen abgedeckt wird. wie man in den folgenden F¨llen sieht. Solcher Code wird allerdings sehr schnell unleserlich. g l e i c h 0 o d e r 1 o d e r 2 ”. g l e i c h 0 ”. B.

Handelt es sich um ein assoziatives Array oder spielt der Index keine Rolle bei der Auswertung der Daten.8.2. hierbei kann es sich z.3. $ i < count ( $ t a g e ). ” S o n n t a g ”). B. a Besonders problematisch ist die erw¨hnte Kopiersemantik im Zusammenhang mit Oba jektreferenzen. 8. Wie man leicht sieht. Eine Gegen¨berstellung der beiden zeigt. while ( $ j < 10) { $ j += 2. Bei jedem Schleifendurchlauf enth¨lt diese lokale Variable eine Kopie a (!) der Daten des jeweiligen Array-Eintrags. Christoph Reeg Seite 100 . } } Das Beispiel stoppt mit den Werten 3 und 2 in $i und $j. B. nimmt man dazu meist eine fora Schleife. weil $j in der inneren Schleife immer mindestens den Wert 2 hat. auch wieder um ein Array handeln (wobei das eigentliche Array dann multidimensional w¨re). ” D o n n e r s t a g ”. Obiges Skript gibt nacheinander und ohne Leerzeichen oder Zeilenumbr¨che zweimal u alle Wochentage aus. wie viel einfacher letztere zu handhaben ist: u $ t a g e = array ( ”Montag ”. anwendbar): if (! isset ( $myArray )) $myArray = array (). $ i ++) echo $ t a g e [ $ i ]. foreach-Schleife. ”Samstag ”. $ j = 0. kann man die Variable im Zweifelsfall initialisieren (auch auf Funktionen mit ¨hnlicher a Problematik. ” D i e n s t a g ”. bietet sich eine alternative Schleife an. ” F r e i t a g ”. weist man bei foreach nacheinander die Eintr¨ge eines Arrays a (erste Variable) einer lokalen Variable zu. ”Mittwoch ”. Um sicherzustellen.1.19 foreach Wenn man alle Eintr¨ge eines Arrays durchgehen will. daß foreach ein Array als ersten Eingabe erwartet. die sog. siehe auch 20. daß die Eingabe immer ein Array ist. Zu beachten ist außerdem. wie z. if ( $ i > $ j ) break 2. sonst gibt es eine Fehlermeldung. // m i t f o r for ( $ i =0. die in der Syntax hinter dem Schl¨sselwort as u angegeben wird. in_array. PHP Grundlagen Grundbefehle while ( $ i < 10) { $ i ++.2. // m i t f o r e a c h foreach ( $ t a g e as $ t a g ) echo $ t a g .

Christoph Reeg Seite 101 . auch mysql_fetch_array(): 10. Wenn man es nur an dieser Stelle verwendet. while. if (!( $ i %2)) continue .1.: Schl¨ssel) des Arrays einer lokalen Variable zuzuweisen – das u geht n¨mlich mit einer for-Schleife nicht so ohne weiteres: a $ p r o d u k t e = array ( ”Auto ”=> ” 2 2 3 9 9 ”.8. um mehrdimensionale Arrays zu strukturieren (vgl. ” F a h r r a d ”=> ”349 ”. daß Arrays nicht nur statisch wie im Beispiel. switch. ¨ wenn Namen statt Indizes benutzt werden. die es erlaubt. for und foreach) gibt es analog zu u break die M¨glichkeit. Richtig interessant wird es aber erst mit der erweiterten Syntax.1. ’ )).00 EUR Fahrrad: 349. while ( $ i > 0) { $ i --. Im konkreten Fall liest sich die Ausgabe wie folgt: Auto: 22. foreach ( $ p r o d u k t e as $ t y p => $ p r e i s ) { printf ( ”%s : % s EUR\ n ”. Beispiel: $ i = 10.6 und mysql_fetch_row(): 10. 2. sondern auch als Resultat einer Datenbank-Abfrage oder durch sonstige Berechnungen (z. $ t y p . } } Die obige Funktion kauft“ selbst¨ndig so lange Produkte.00 EUR Skates: 229. sich also die Variable ersparen.399. PHP Grundlagen Grundbefehle foreach ( $myArray as $ k e y => $ v a l ) echo ” $ k e y : $ v a l \ n ”.7). Kopf) zu springen. B. also zum Anbfrageteil der Schleife (den o sog. bei komplexeren Arrays wird auch das Programmieren wesentlich ubersichtlicher. if ( $ p r e i s <= $ g u t h a b e n ) { $ g u t h a b e n -= $ p r e i s . ” S k a t e s ”=> ”229 ”).00 EUR Wenn man sich vorstellt. ’ . k¨nnte man $produkte auch direkt als Eingabe f¨r foreach o u hinschreiben. macht der Zugriff auf den Index gleich mehr u o Sinn.20 continue F¨r alle oben beschriebenen Schleifen (do. bis entweder die Liste durcha ” laufen ist – wie im Beispiel – oder das Guthaben nicht mehr reicht. engl. POST¨ /GET-Ubergabe) gef¨llt werden k¨nnen.2. $ g e k a u f t [ $ t y p ] = true . 8. die Schleife fortzusetzen. ’ . ’ . number_format ( $ p r e i s . $ g u t h a b e n = 1325. auch den Index (auch key.

Es wird aber von PHP3 etwas anders behandelt. Es gibt drei wesentliche Unterschiede zu include(): Zum einen wird require() immer ausgef¨hrt. siehe Kapitel 8. mit anderen PHP-Code-Markierungen. deshalb muß. WHILE) nur ein einziges Mal ausgef¨hrt u egal. Wie bei include() wird erst einmal aus dem PHP-Modus gesprungen. u wenn es eigentlich abh¨ngig von einer IF-Bedingung nicht ausgef¨hrt werden d¨rfte. ” Christoph Reeg Seite 102 . muß es immer in geschweiften Klammern geschrieben werden. } 8. Bei PHP3 wird der require()-Ausdruck beim ersten Aufruf durch die Datei ersetzt. Seit PHP4 gibt es keinen Unterschied mehr. /∗ So i s t e s f a l s c h ∗/ if ( $ B e d i n g u n g ) include ( ” D a t e i . i n c ”). wie oft die Schleife durchlaufen wird (trotzdem wird der Inhalt der eingef¨gten Datei u mehrmals abgearbeitet). Optional kann hinter continue ein Integerwert angegeben werden. /∗ So i s t e s r i c h t i g ∗/ if ( $ B e d i n g u n g ){ include ( ” D a t e i . in absteigender Reihenfolge. f¨gt an dieser Stelle den Inhalt der Datei ‘dateiname‘ ein. der in mehreren Dateien ben¨tigt wird. der analog zu break die Anzahl der hinauszugehenden“ Ebenen angibt.3 include Der Befehl include("dateiname"). PHP Grundlagen include echo $ i . ” 8.2). wenn u in der Datei nur PHP-Code steht. i n c ”).8. wird als HTML-Code interpretiert. zentral zu halten. Wenn include() in Verbindung mit Bedingungen oder Schleifen eingesetzt wird. } Die obige Schleife gibt genau die ungeraden Zahlen bis 10 aus. Dadurch ist es m¨glich. Die Datei. die eingef¨gt wird. Der dritte Unterschied liegt in der Reaktion auf nicht vorhandene Dateien: include() gibt nur ein Warning“ aus und PHP l¨uft weiter.4 require Ganz analog zu include() funktioniert require(). bei require() bricht a ” PHP mit einem Fatal error:“ ab. Quellcou o ¨ de. zum a u u anderen wird es innerhalb einer Schleife (FOR. so daß Anderungen einfacher o werden. diese Datei mit <?php anfangen und mit ?> aufh¨ren o (bzw. also auch dann.

wie zu erwarten. for ( $ i =1. require ( ” t e s t . PHP Grundlagen Beispiele zu include und require 8. t x t ”). Die Variable i hat den Wert 2.8. $ i ++){ require ( ” t e s t . $ i <=3. ?>.<br> Die Variable i hat den Wert 5.<br> Die Variable i hat den Wert 5. $ i ++){ include ( ” t e s t . txt test2. folgende: Erstmal ein einfaches include/require<br> Dies ist ein einfacher Text. for ( $ i =1.txt Datei test2 . Die Variable i hat den Wert 1. t x t ”). include ( ” t e s t . Die Ausgabe des Scripts ist. in dem das PHP-Script liegt. } Auch hier ist die Ausgabe. Dies ist ein einfacher Text. o echo ”\ n K l e i n e f o r− S c h l e i f e f u e r i n c l u d e<b r>\n ”. t x t ”).<br> Auch in Schleifen k¨nnen include() und require() verwendet werden. Dies ist ein einfacher Text.5 Beispiele zu include und require Es gibt im selbem Verzeichnis. Die Variable i hat den Wert 3.<br> Dies ist ein einfacher Text. t x t ”). } echo ”\ n K l e i n e f o r− S c h l e i f e f u e r r e q u i r e<b r>\n ”.txt Datei test1 .< br > test1. noch folgende Dateien: test. $ i = 5. wie zu erwarten: Kleine for-Schleife f¨r include u Dies ist ein einfacher Text.txt Dies ist ein einfacher Text . Christoph Reeg Seite 103 . $ i <=3. txt Aber jetzt zu den Beispielen: echo ” E r s t m a l e i n e i n f a c h e s i n c l u d e / r e q u i r e<b r>\n ”.< br > Die Variable i hat den Wert <? php echo $ i .

.txt <br> <b>Warning</b>: Failed opening ’test3. PHP Grundlagen Beispiele zu include und require Kleine for-Schleife f¨r require u Dies ist ein einfacher Text.. t x t ”). for ( $ i =1. $ i ++){ require ( ” t e s t $ i . Christoph Reeg Seite 104 . wo man einen Unterschied zwischen include() und require() sehen kann: echo ”\ n K l e i n e f o r− S c h l e i f e f u e r i n c l u d e<b r>\n ”. $ i <=3. Die Variable i hat den Wert 1. t x t ”).txt Datei test1. Kleine for-Schleife f¨r require<br> u Datei test1. Kleine for-Schleife f¨r require<br> u Datei test1.txt Datei test2. Dies ist ein einfacher Text... } echo ”\ n K l e i n e f o r− S c h l e i f e f u e r r e q u i r e<b r>\n ”. Als letztes ein Beispiel.txt Datei test2. } Hier gibt es einen Unterschied zwischen PHP3 und PHP4...8. Die Ausgabe bei PHP3 ist folgende: Kleine for-Schleife f¨r include<br> u Datei test1. Die Variable i hat den Wert 3.txt’ for inclusion (include_.txt’ (include_. for ( $ i =1. $ i <=3..txt Datei test2. Dies ist ein einfacher Text.txt’ for inclusion in <b>.txt Datei test1.txt <br> <b>Warning</b>: Failed opening ’test3..txt Die Ausgabe von PHP4: Kleine for-Schleife f¨r include<br> u Datei test1.txt <br> <b>Fatal error</b>: Failed opening required ’test3. $ i ++){ include ( ” t e s t $ i . Die Variable i hat den Wert 2..

txt“ einzuf¨gen.. . f¨gt man sie a o u immer am Anfang ein. Funktionen. weil jede nur einmal eingef¨gt werden darf. Prozeduren. Dadurch werden Programme einfacher lesbar.6 include once. Sobald aber mehrere zentrale Funktionsdateien existieren.. die die a zentralen Funktionen enth¨lt. Bei einigen Programmiersprachen findet eine Unterscheidung zwischen Funktionen statt. Z. sog.\n". u 8. require once Seit PHP4 gibt es neben den Funktionen include() und require() auch noch die Funktionen include_once() und require_once(). } Die Funktion bekommt die Argumente ‘Arg 1‘ bis ‘Arg n‘ ubergeben und gibt den Wert ¨ der Variablen ‘retval‘ zur¨ck.7 Funktionen Funktionen dienen dem Zusammenfassen mehrerer Befehle zu einem Aufruf. weil klar ist. u a wie h¨ufig man versucht. PHP Grundlagen include once. Bei PHP4 verh¨lt sich die require() wie die include() Anweisung. PHP3 verh¨lt sich. Bei den *_once() Funktionen wird die Datei nur einmal eingef¨gt. wozu ein Befehlsblock dient. Der Name zeigt schon. hat man dasselbe u Verhalten wie bei einer Prozedur in Pascal/Delphi. In beiden F¨llen wird versucht.txt“. // g i b t d a s Q u a d r a t von $num z u r u e c k // // // // g i b t 1 6 aus r u f t die Funktion auf . es p a s s i e r t aber n i c h t s ( der Rueckgabewert wird i g n o r i e r t ) Christoph Reeg Seite 105 . return $retval. a 8. require once Die include()-Anweisung wird bei PHP3 und PHP4 identisch behandelt. in Pascal/u u Delphi gibt es neben den sog. my_sqr (4). die keinen Wert zur¨ckgeben. die einen Wert zur¨ckgeben und solchen. } echo my_sqr (4). Da diese in den Webseiten ben¨tigt werden. u die keinen Wert zur¨ckgeben. die einen Wert zur¨ckgeben.. wo der Unterschied ist. wie ich es erwartet a habe. Bei require() sieht das ganze etwas anders aus. unabh¨ngig davon. $arg_2. Die Datei wird einmal eingef¨gt und dann wird der Inhalt der Datei mehrmals u aufgerufen. wird es schwierig. R¨ckgabewerte m¨ssen (im Gegensatz u u zu Pascal/Delphi) nicht abgefragt werden. PHP macht hier. test2. u Die Syntax lautet wie folgt: function foo($arg_1. Soweit kein Problem. keinen Unterschied. Wird kein ‘return‘ in der Funktion benutzt. sie einzuf¨gen. wobei a u ” ” ” letzteres mangels vorhandener Datei nicht funktioniert. die sich auch untereinander bedingen.8. $arg_n) { echo "Example function. a u Der Sinn ist einfach: Bei umfangreichen Webseiten gibt es h¨ufig eine Datei. die Dateien test1.txt“ und test3. genau wie C und C++. B. Ein kleines Beispiel: function my_sqr ($num) { return $num * $num.

PHP Grundlagen Formatierte Textausgabe 8. Das zeigt auch die Syntax: int printf (string format [.1 printf printf() ist eine ganz spezielle Funktion.]) Auf den ersten Blick mag das sehr verwirren und zur Frage f¨hren.8. // A u s g a b e : D i e s i s t e i n S t r i n g ( $ s t r ). } function foo2 (& $ s t ) { $ s t . mixed args. $str . // A u s g a b e : // D i e s i s t e i n S t r i n g und e t w a s mehr . // g l e i c h b e d e u t e n d m i t $ s t = $ s t . muß man mit Variablenparametern19 bzw. 8. Bevor ich das beantworten kann. ’ .7. Ein kleines Beispiel: function foo1 ( $ s t ) { $ s t . wenn der zweite Parameterteil entf¨llt. wenn mehr als nur ein String ubergeben wird: Dann ¨ spielt die Funktion ihre St¨rken aus. dem String.8. Will man jedoch die An¨ derungen der Parameter in der Funktion auch in der aufrufenden Funktion haben. denn die Anzahl ihrer Parameter ist variabel. muß ich aber erst einmal vollst¨ndig a erkl¨ren. Referenzparametern20 arbeiten21 . was man mit printf() machen kann. ’ . ’ und e t w a s mehr . was hinter dem String in 17 18 19 20 21 In der Funktion wird mit einer Kopie der Variablen gearbeitet wird auch als Call by value“bezeichnet ” Es wird mit den Originalvariablen gearbeitet.1 Variablenparameter ¨ Normalerweise werden in PHP Werteparameter17 ubergeben18 . $str .. // A u s g a b e : D i e s i s t e i n S t r i n g ( $ s t r ). die durch das ersetzt werden. $str . a Im einfachsten Fall. Im ersten Parameter.. } $str echo foo1 echo foo2 echo = ’ Dies i s t ein String ’ . Variablenparameter werden mit einem ‘&‘ im Funktionskopf gekennzeichnet.8 Formatierte Textausgabe 8. was daran denn u einfacher sein soll. Anders jedoch. ’ .= ’ und e t w a s mehr .= ’ und e t w a s mehr . k¨nnen n¨mlich a o a Platzhalter eingebaut werden. verh¨lt sich printf() gea a nauso wie print(). weil nur die Adresse ubergeben wird ¨ Zwei Namen f¨r dasselbe u wird auch als Call by reference“ genannt ” Jens Hatlak Seite 106 .

Im Normalfall22 gibt es also genau so viele zus¨tzliche Argumente. Die Ausrichtung. muß man es durch zwei Prozentzeichen ausdr¨cken23 . Standardm¨ßig wird hierbei a u a mit Leerzeichen aufgef¨llt. Hierbei u reichen die M¨glichkeiten von der Festlegung auf einen bestimmten Typ wie Zahlen zu o verschiedenen Basen bis hin zum Zurechtschneiden. wird bei letzterem der Wert als Integer interpretiert und als Dezimalzahl ausgegeben. um den eingef¨gten Wert auf der rechten Seite u u bis zur weiter unten angegebenen L¨nge aufzuf¨llen. die kein Integer sind. u 22 23 Ausnahmen best¨tigen die Regel. daß an einer bestimmten Stelle im auszugebenden String auch wirklich eine Zahl steht. in folgender Reihenfolge auftreten: 1. Vielmehr kann man mithilfe der Platzhalter genau vorgeben. wie der Wert. 2. aber dazu weiter unten mehr a Im Gegensatz zum sonst in PHP ublichen Escapen mithilfe des Backslashes ¨ Jens Hatlak Seite 107 . wie Platzhalter in den String eingebaut wurden – der ubrigens auch a ¨ vollst¨ndig in einer Variable enthalten sein kann. formatiert werden soll. ” Platzhalter %b %c %d %u %f %o %s %x %X Behandlung Integer Integer Integer Integer Double Integer String Integer Integer Darstellung Bin¨rzahl a Zeichen mit entsprechendem ASCII-Code Dezimalzahl. mit Vorzeichen Dezimalzahl ohne Vorzeichen Fließkommazahl Oktalzahl String Hexadezimalzahl mit Kleinbuchstaben Hexadezimalzahl mit Großbuchstaben Tabelle 8.8. wenn sie angegeben u werden. alles andere wird 1:1 ausgegeben – ausgenommen nat¨rlich Ausgabe-Formatierungsu zeichen wie \n. u Die beiden wichtigsten Platzhalter sind ubrigens %s und %d. k¨nnen noch weitere Angaben zur Formao tierung gemacht werden. stellt man den folu genden Angaben jedoch ein Minuszeichen (-) voran.7: printf: Platzhalter Zwischen dem einen Platzhalter einleitenden Prozentzeichen und dem Buchstaben. PHP Grundlagen Formatierte Textausgabe Form weiterer Argumente angegeben wird. wird linksb¨ndig formatiert. wobei letzteres dann mit einem einfachen Hochkomma (’) gekennzeichnet werden muß. Die Tabelle Platzhalter“ listet alle erlaubten Platzhalter auf. Das F¨llzeichen. es kann aber auch eine 0 (Null) oder ein beliebig anderes u Zeichen angegeben werden. Alle Werte. was u uns diese Funktion bietet. der an entsprechender Stelle eingef¨gt wird. a Die genannten Platzhalter werden grunds¨tzlich mit einem Prozentzeichen . Auf diese Weise kann man also sicher stellen. der die Typisierung des Platzhalters bestimmt. Reines Ersetzen allein ist jedoch noch lange nicht alles. Normalerweise wird rechtsb¨ndig ausgereichtet. werden kurzerhand in eine 0 verwandelt. ggf.%‘ eingeleia tet. Will man nun das Prozentzeichen selbst ausgeben. Diese sind allesamt optional und m¨ssen. Dieses wird benutzt. W¨hrend erstgenannter a ¨ einen beliebigen String als Wert akzeptiert. Ausrichten und Auff¨llen von Daten.

$betrag = $betrag1 + $betrag2 . $ i <10. PHP Grundlagen Formatierte Textausgabe 3. ob sie gerade oder u ungerade ist: for ( $ i =0. so daß man dann ja immer noch mal nachlesen kann und es sich nicht wirklich merken muß. z. 24 U. $monat = 5. $ f o r m a t = ”%02d . printf ( ”%01. sollte man diese in runden Klammern schreiben. Die L¨nge. $ b e t r a g ). Ist der gew¨hlte Typ f¨r die u a u Darstellung nicht double. Insgesamt ergibt sich somit folgende Syntax f¨r Platzhalter: u %[F¨llzeichen][Ausrichtung][L¨nge][Nachkommastellen]Typisierung u a Im Allgemeinen braucht man die optionalen Angaben aber recht selten.2.05.3) genutzt werden. ” $ b e t r a g 1 = 12. Die Zahl. bestimmt die Anzahl der Zeichen. Gibt 13.75.8. die die a formatierte Ausgabe des jeweiligen Wertes mindestens umfassen soll. B.2 f ”. erlauben Das folgende Beispiel gibt f¨r die Zahlen von 0 bis 9 jeweils aus. die in Kapitel 8. die man hier angibt. ” ”. $ b e t r a g 2 = 57. \ n ”. $ j a h r ). $ i ++) printf ( ”%d i s t % s g e r a d e .95. U. $ j a h r +2). daß man den Formatierungs-String nicht ver¨ndern m¨chte. $ j a h r = 2009. Hier gibt eine Zahl. Folgende Beispiele demonstrieren.8. printf ( $ f o r m a t . wie sich das eben gelernte nun tats¨chlich einsetzen a l¨ßt: a $ t a g = 13.7 70. daß es sich um eine solche handelt – und ggf. kann es ja sein. $monat . ” Ist nun eine der Variablen f¨r die Platzhalter im Formatierungs-String von anderen abu h¨ngig. Gibt 70. $i .%04 d \ n ”.2009“ und ein anderes wichtiges Datum aus.70“ aus. F¨r komplexere u Zahlenformatierungen sollte die Funktion number_format() (Kapitel 8. m¨ßte normalerweise eine if-Abfrage vor dem Funktionsaufruf get¨tigt werden. $ t a g . weil er schon a o in Form einer Variablen vorliegt Jens Hatlak Seite 108 . so hat diese Angabe keine Bedeutung.14 vorgestellt wurde. Um klar zu machen. um Erg¨nzungen mittels des Punkt-Operators zu a 24 —. printf ( $ f o r m a t . so kann man praktischerweise auch die alternative Kurzvariante benutzen. 4. a u a Ist diese Abfrage jedoch simpel. die Anzahl der Dezimalstellen f¨r Fließkommazahlen an. gefolgt von einem Dezimalpunkt.%02 d . echo $ b e t r a g . Die Nachkommastellen. auch. 2* $ t a g . $monat .

8.1. B. // A u s g a b e j e nach S p r a c h e : // de −> H e u t e i s t d e r 1 3 . $ j a h r = 2009. PHP Grundlagen Formatierte Textausgabe ( $ i %2==0 ? ” ” : ”un ”) ). ”. dabei jedoch ggf. Eine Referenz auf ein Argument definiert man nun mittels folgender Syntax: %[Argumentnummer\$][sonstige Formatierung]Typisierung Folgendes Beispiel einer Sprach-angepaßten Datumsausgabe verdeutlicht die Vorteile25 : // Angenommen . daß Variablen in ihnen ersetzt werden. 2 0 0 9 // en −> Today ’ s d a t e i s 2009−05−13 printf ( $ t e x t . eine einzelne Variable am Ende eines Strings vor. a a a u a a ¨hnlich wie bei regul¨ren Ausdr¨cken.8. Dann kann man n¨mlich von der Eigenschaft der doppelt a gequoteten Strings Gebrauch machen. 8. darauf hinzuweisen. die sp¨ter noch behandelt werden. ”. $ j a h r ). 5 . die selbst vom Typ String sind und deren Name aus a einem einzelnen Wort besteht. verschieden zu formatieren. } else { // u n b e k a n n t e S p r a c h e −> w i r g e b e n nur d i e Z a h l e n a u s $ t e x t = ”%3\ $04d−%2\$02d−%1\$02d ”. Dadurch ergibt sich nicht nur die M¨glichkeit.1 Argumente vertauschen/numerieren Seit PHP-Version 4. sondern auch bestimmte Argumente mehrfach zu plazieren. $monat = 5. a ¨ Ahnlich verh¨lt es sich bei Variablen. $monat .%3\ $04d . kann man sie einfach direkt mit dem Punktoperator anh¨ngen und muß nicht gleich zu printf greifen. das Verst¨ndnis 25 Man h¨tte hier auch an Stelle der ganzen if und elseif auch eine switch-Anweisung nehmen k¨nnen a o Jens Hatlak Seite 109 . $ t a g . daß die printfo Syntax nur dann als guter Stil“ bezeichnet werden kann. An dieser Stelle m¨chte ich die Gelegenheit nutzen. Kommt z. Aber nocheinmal der Hinweis: Gerade durch die M¨glichkeit des Numerierens kann die o Komplexit¨t des Codes schnell ansteigen (und das in wenigen Zeilen Code) und dadurch.06 kann man die Argumente (zur Erinnerung: das sind die zus¨tzlichen a Parameter. deren Werte anstelle der Platzhalter ausgegeben werden) durchnumerieren und entsprechend referenzieren. } elseif ( $ l a n g == ”en ”) { $ t e x t = ”Today ’ s d a t e i s %3\ $04d−%2\$02d−%1\$02d .%2\ $d . i n $ l a n g s t e h e d i e S p r a c h e if ( $ l a n g == ”de ”) { $ t e x t = ”Heute i s t d e r %1\ $d . } $ t a g = 13. Argumente in o der Reihenfolge ihres Auftretens bei der Ersetzung zu vertauschen. wenn man sie auch sinnvoll ” einsetzt.

alle SQL-Befehle und Vergleichsoperatoren.8. o 8. . u Eine sch¨ne Aufgabe zum Gesagten findet sich in Kapitel 10.) als Trennzeichen zwischen Tausenden und ohne Nachkommastellen ausgegeben. das den SQL-String zusammenbaut und zur¨ckgibt u (der Empf¨nger ist. 26 27 Das allerdings nur auf Servern. Zugunsten der Lesbarkeit sollte man also auf allzu verspielte ¨ Konstruktionen verzichten und dann. int decimals [. so wird diese ¨ mit einem Komma (. dem deutschen. die mit htmlentities() kombiniert gerade bei der u HTML-Ausgabe n¨tzlich ist.3. die u restlichen Parameter geben die Quellen (Variablen) f¨r die Werte an. wobei wahlweise ein. a Innerhalb dieses Konstruktes herrscht eine einfache Zweiteilung: der erste Parameter definiert das String-Grundger¨st.8. Ein Beispiel f¨r schlechten Stil w¨re es demnach. die in PHP-Variablen stecken. .3. o Insbesondere im Zusammenhang mit Internationalisierung l¨ßt sich diese Funktion nutzen. F¨r diese Variablen gilt ubrigens. F¨r die R¨ckwandlung bei der Ausgabe an anderer Stelle steht die Funku u tion stripslashes() zur Verf¨gung. anstatt ihn direkt auszugeben. Verwendung findet es im Gegensatz zu letzterem jedoch besonders gerne bei Zuweisungen oder als Parameter f¨r andere Funktionsaufrufe – sprintf liefert ja den erzeugten u String zur¨ck. eine Zahl zu formatieren. falls ihre Werte m¨glicherweise Hocho kommata enthalten k¨nnten – diese werden durch die erw¨hnte Funktion mittels Backso a lash escaped. also i. z. PHP Grundlagen Formatierte Textausgabe erheblich erschwert werden. anderen Formaten entsprechend umzuwandeln. string thousands_sep]]) Wird nur die zu formatierende Zahl als einziger Parameter ubergeben. string dec_point . die in PHP standardm¨ßig bekanntlich entsprechend der amerikaa nischen Normen27 formatiert werden. weil man damit den eigentlichen Abfrage-String a sauber von den Werten trennen kann. die die im Stringu Grundger¨st einzubauenden Platzhalter ersetzen. Das Prinzip ist immer das gleiche: Der eigentlichen Abfragefunktion mysql_query() ubergibt man als einzigen ¨ Parameter das sprintf()-Konstrukt.8. Die Syntax ist wie folgt. zumindest gut kommentieren. die Abfragefunktion). A. bei denen PHP dies nicht schon implizit macht! Komma als Tausender-Trennzeichen und Punkt als Dezimaltrenner Jens Hatlak Seite 110 . schon beim Vorkommen eines einzelnen u a doppelten Arguments mit der Kanone Referenzierung auf den Spatz String zu schießen. bedingt durch die Schachtelung. u sprintf() l¨ßt sich besonders gut im Zusammenhang mit SQL-Abfragen (siehe auch a n¨chstes Kapitel) besonders gut einsetzen. daß u u ¨ man sie mittels addslashes() behandeln sollte26 . wenn es doch einmal der Ubersichtlichkeit dienen sollte.2 sprintf Im Prinzip arbeitet sprintf genauso wie printf und folgt exakt derselben Parametrisierung.3 number format Mit der Funktion number_format() bietet PHP die M¨glichkeit. zwei oder vier Parameter angegeben werden k¨nnen (nicht drei!): o string number_format (float number [. B. 8. a um Fließkommazahlen.

3 9 2 .48365). indem man struka turiert. a Zeichen werden wild escaped und Parameter derart in Strings eingebettet. Auch hier trennt wieder ein Komma jede Tausenderstelle. 4 8 EUR 8. Selbst Kommentieren will gelernt sein – hier bietet sich PHPDOC (Kapitel 14) an. eine andere. number_format ( $ p r e i s . a a Dabei ist es im Prinzip gar nicht so schwer: Das Ziel l¨ßt sich erreichen. Vielleicht tragen ja diese Zeilen dazu bei. F¨r letzteres hat sich die objektorientierte Denku weise als hilfreich erwiesen und auch in PHP Einzug gehalten (siehe Kapitel 18). was das Zeug h¨lt. Wenn es jedoch zur Struktur kommt. daß o man selbst irgendwann mal – ein Jahr sp¨ter oder so – noch etwas ¨ndern will oder muß. welch uberaus hilfreiche und strukturierende Funktionen ¨ PHP von Hause aus bietet. wof¨r diese Funktion vornehmlich benutzt werden kann: u function Euro ( $ p r e i s ) { return sprintf ( ”%s EUR\ n ”. It was hard to write. } echo Euro (17392. einen Codeabschnitt im Kontext betrachtet) sowie auf Wiederverwendbarkeit achtet. ’ . W¨hrend printf() von print() a abgeleitet ist. Achtung: Es wird nur das erste Zeichen des Tausender-Trennzeichens f¨r die Ausgabe u benutzt! Das Beispiel verdeutlicht. die Ausgabe der Jens Hatlak Seite 111 .9 Guter Stil Real programmers don’t use comments because the code is obvious. PHP Grundlagen Guter Stil Bei zwei Parametern wird die Zahl mit decimals Stellen hinter dem Komma ausgegeben. die Nachkommastellen werden vom ganzzahligen Wert durch einen Punkt getrennt. it should be hard to understand. daß es passieren kann. bietet unsere Scriptsprache die Funktionen printf() und sprintf(). daß sich das ¨ndert a – ich hoffe es jedenfalls. So zu programmieren. 2.8. daß selbst der ¨ Autor des Scripts sich nicht mehr an eine Anderung heranwagen m¨chte. daß nicht nur man selbst. von der PHP bekanntlich stark beeinflußt ist. Da wird geschachtelt. also letztlich Text direkt ausgibt. ¨ Ahnlich wie in der Sprache C. Man darf auch nicht vergessen. ’ ) ). dient sprintf() dazu. daß sie die Zeichen f¨r den Dezimaltrenner und das Tausenderu Trennzeichen (in dieser Reihenfolge) verwendet. ’ . Die Ausgabe bei Angabe aller vier Parameter schließlich unterscheidet sich durch die bei nur zweien dadurch. fragt sich mancher angesichts ellenlanger Codekonstrukte schnell. Viele Autoren o scheinen einfach nicht zu wissen. ’ . kommentiert und abstrahiert (d. // A u s g a b e : 1 7 . h. Programmieren ist eine Sache. wie man dem beikommen soll. sondern auch andere den Code sp¨ter in m¨glichst kurzer Zeit verstehen und daraufhin auch era o weitern k¨nnen.

<? php error_reporting ( E_ALL ). wie viele Fehlermeldungen du bekommen willst. ich zeige hier nur ein paar Beispiele: // F e h l e r m e l d u n g e n g a n z a b s c h a l t e n error_reporting (0). PHP Grundlagen Guter Stil Funktion als Argument (Parameter) einer weiteren Funktion oder einfach als Wert einer Zuweisung zu benutzen28 . ein Syntax-Fehler schlimmer als der lesende Zugriff auf eine nicht initialisierte Variable29 . Beim echo habe ich mich verschrieben und die Variable varaible1 ist nicht initialisiert. ist nicht initialisiert Jens Hatlak Seite 112 .9.]/test. Meiner Meinung nach ist es kein Fehler. 28 29 Worauf schon das . ?> Frage: Was wird ausgegeben? Normalerweise nichts. Normalerweise beginnt hier die große Suche.s‘ hindeutet: Es steht f¨r silent“. // g a n z v i e l Code echo $ v a r a i b l e 1 . Beim Syntax-Fehler kann der PHP-Interpreter nicht weiter arbeiten (weil er nicht weiß. aber wenn man es nicht erlaubt. $ v a r i a b l e 1 = ” H a l l o Welt ! ”. der noch kein Wert zugewiesen wurde. zu deutsch: still.. Die genauen Stufen kannst du in der PHP-Dokumentation nachschlagen. B.1 Warn-/Fehlermeldungen anzeigen Bei Fehlermeldungen unterscheidet PHP verschiedene Stufen. Jetzt schalten wir (fast) alle Fehlermeldungen an.8. ?> Jetzt bekommen wir eine Warnung: Notice: Undefined variable: varaible1 in [. oder nicht. So ist z. ob es ein Fehler ist. <? php $ v a r i a b l e 1 = ” H a l l o Welt ! ”. u ” Eine Variable.. von einer nicht initialisierten Variable zu lesen. schließt man einige Fehlerquellen.php5 on line 8 Mit Hilfe von error_reporting kannst du PHP sagen. An dieser Stelle kann jetzt ein Glaubenskrieg anfangen. // g a n z v i e l Code echo $ v a r a i b l e 1 . 8. also leer. was er machen soll). bei der nicht initialisierte Variable hingegen nimmt er einfach den Standardwert (und gibt im Normalfall keine Meldung aus). wo die Fehler je nach Schwere eingeordnet sind.

// A l l e F e h l e r a u s s e r E NOTICE m e l d e n // D i e s i s t d i e S t a n d a r d e i n s t e l l u n g i n php . // S e i t PHP5 g i b t e s noch e i n e S t e i g e r u n g error_reporting ( E_ALL | E_STRICT ).8. i n i error_reporting ( E_ALL ^ E_NOTICE ). Als Parameter nimmt man einfach die gew¨nschten Fehler und verkn¨pft sie mit einem u u bitweisen ODER. Jens Hatlak Seite 113 . // A l l e PHP−F e h l e r m e l d e n // IMHO zum E n t w i c k e l n e m p f o h l e n error_reporting ( E_ALL ). PHP Grundlagen Guter Stil // E i n f a c h e L a u f z e i t f e h l e r m e l d e n error_reporting ( E_ERROR | E_WARNING | E_PARSE ).

. n!n=1 = n · (n − 1)!. . Die Fakult¨t einer nat¨rlichen Zahl a a u ist definiert als das Produkt aller Zahlen von 1 bis zu dieser Zahl. Rekursion ist ein beliebtes Mittel der Programmierpraxis. ggf. PHP Grundlagen Rekursion 8. das mit all den gemerkten“ Faktoren (der erste war n) multipliziert ” werden muß – man geht also den ganzen Weg“ wieder zur¨ck und sammelt“ dabei das u ” ” auf. 31 o 30 31 Da auch definiert wurde. In der Mathematik gibt es den Begriff der Fakult¨t. um Probleme zu l¨sen. mehr dazu sp¨ter. Irgendwann wird man dahin kommen. das aber in Wirklichkeit nichts u anderes ist als das urspr¨ngliche Problem. u d. kann man die Rekursion auch bis n = 0 laufen lassen. was man liegen gelassen“ hat.10. mit leicht ver¨nderten Voraussetzungen. Doch nun a a a zu dem Paradebeispiel f¨r Rekursion schlechthin: u 8. Jens Hatlak Seite 114 . Diese ist aber definiert als n − 1 mal die Fakult¨t von (n − 1) − 1 = n − 2 a usw. die Fakult¨t von n − x zu berechnen.10 Rekursion Um Rekursion verstehen zu k¨nnen. die an o mindestens einer Stelle zu einem weiteren Problem f¨hren. h. wobei a dieser Ausdruck den Wert 1 haben wird. das 0! = 1. Letztlich ist sie aber eh nur erfunden . u a Das klingt kompliziert. o muß man erst Rekursion verstanden haben. die Fakult¨t von 1 wird definiert als 1 und f¨r n = 1 ist die Fakult¨t von n gleich n mal a u a der Fakult¨t von n−1. Von der Vorgeschichte scheint es Dutzende von Abwandlungen zu geben. ist im Prinzip aber ganz einfach – wie das folgende beliebte Beispiel zeigt.1 Die T¨rme von Hanoi u Man stelle sich ein fern¨stliches Kloster vor. Die dortigen M¨nche wollen nun viele Kreiso o scheiben verschiedenen Durchmessers von einem Stapel auf einen anderen bef¨rdern. Mittels Rekursion kann man das wie folgt ausdr¨cken30 : 1! = 1. also z. Am Ende hat man auf diese Weise die eigentliche ” Fakult¨t berechnet. l¨ßt sich an diesem Beispiel noch nicht kl¨ren. Um das Ergebnis zu berechnen. Das folgende kleine Beispiel sollte das Prinzip verdeutlichen: a 1! = 1 2! = 2 · 1 3! = 3 · 2 · 1 4! = 4 · 3 · 2 · 1 5! = 5 · 4 · 3 · 2 · 1 6! = 6 · 5 · 4 · 3 · 2 · 1 = 2 · (1) = 3 · (2 · 1) = 4 · (3 · 2 · 1) = 5 · (4 · 3 · 2 · 1) = 6 · (5 · 4 · 3 · 2 · 1) = 2 · 1! = 3 · 2! = 4 · 3! = 5 · 4! = 6 · 5! Die Frage. muß man also erst die Fakult¨t von a a n − 1 berechnen. 5! = 1·2·3·4·5 = 120. B. Dann ist es mit der Rekursion vorbei und die erste Definition greift: Die Fakult¨t von 1 ist gleich 1.8. An dieser Stelle hat man also ein a erstes Teilergebnis. welchen Vorteil diese Methode gegen¨ber dem einfachen Z¨hlen und Multiu a plizieren hat.

Wer sich jetzt an eine gewisses a Schachbrett32 erinnert. die Aufgabe theoretisch f¨r jede o u beliebige Anzahl von Scheiben zu l¨sen. daß so eine Scheibe bei entsprechender H¨he des Stapels doch recht o schwer werden d¨rfte (nach unten hin wird’s ja immer gr¨ßer!) gibt es noch ein Problem u o ganz anderer Natur: Das Umschichten der Stapel kostet Zeit. Bewege die kleine Scheibe von Stapel 2 nach Stapel 1. 4. um n Scheiben vom Start32 Der Legende nach versprach der K¨nig dem Erfinder des Schachspiels ihm einen Wunsch zu erf¨llen.1): u 1. Der Legende o nach geht die Welt unter. auf das dritte Feld 4 K¨rner. Bild 8. Abgesehen davon. Man k¨nnte meinen. auf das zweite Feld 2 K¨rner.8. wenn die M¨nche ihr Werk vollendet haben . Das Problem wird aber schnell o a deutlich. Trotz aller Anstrengungen war es ihm aber unm¨glich. Bewege die mittlere Scheibe von Stapel 2 nach Stapel 3. Ziel. 6. Der K¨nig lachte und versprach dem Erfinder den Wunsch zu o o erf¨llen. Der zugeh¨rige Algorithmus (das Problem wurde o o von einem Mathematiker definiert . ) lautet nun in Pseudo-Syntax: Hanoi(n. wenn man die F¨lle vier. Bewege die kleine Scheibe von Stapel 3 nach Stapel 2. Start. auf das vierte o o Feld 8 K¨rner usw. daß das doch noch akzeptabel w¨re. Bewege die mittlere Scheibe von Stapel 1 nach Stapel 2. daß diese Aufgabe mit nur zwei Stapeln nicht l¨sbar ist: Ein dritter o Stapel muß her. Gehen wir einmal gemeinsam den Algorithmus durch f¨r drei Scheiben (vgl. Bewege die große Scheibe von Stapel 1 nach Stapel 3. Temp. 2. . Bewege die kleine Scheibe von Stapel 1 nach Stapel 3. . f¨nf oder sechs Scheiben durchspielt. Temp. Jens Hatlak Seite 115 . Der K¨nig h¨tte mehr als die 800fache u o o a Jahresproduktion an Reis von 1994 gebraucht. Temp) Bewege von Start nach Ziel Hanoi(n-1. legt dann die letzte Scheibe auf den Ziel-Stapel und schichten danach den Turm vom Temp-Stapel auch noch auf den Ziel-Stapel. Start. bis zum 64. Mit diesen Vorgaben ist es nun m¨glich. . PHP Grundlagen Rekursion Erschwert wird das Ganze dadurch. o Schnell wird klar. Und zwar auf u das erste Feld 1 Korn. Ziel) } Oder als normaler Text: Um einen Turm der H¨he n vom Start-Stapel auf den Zielo Stapel zu bewegen. Genauer gesagt sind 2n − 1 Schritte notwendig. Dabei ergibt a u sich n¨mlich ein Aufwand von 15. 7. Start. 3. dann Ende Hanoi(n-1. 5. der liegt richtig: Der Aufwand w¨chst exponentiell mit der Anzahl a der Scheiben. daß immer nur eine Scheibe gleichzeitig bewegt werden und außerdem nie eine gr¨ßere auf einer kleineren Scheibe liegen darf. o u Dieser dachte lange nach und w¨nschte sich dann: Er wollte Reis auf ein Schachbrett. Ziel) { Wenn n=0. 31 und 63 Schritten. . Feld. bewegt man erstmal einen Turm der H¨he n-1 (also alles bis auf die o letzte Scheibe) auf einen Temp-Stapel. Bewege die kleine Scheibe von Stapel 1 nach Stapel 3.

PHP Grundlagen Rekursion Abbildung 8.8.1: Umschichten der T¨rme von Hanoi u Jens Hatlak Seite 116 .

sehr hohes Wachstum auch schon f¨r niedrige Eingabewerte haben. Irgendwo muß sich der Computer schließlich auch merken. wie man sich denken kann. LIFO34 -Prinzip). T. aber immer auch einen hohen Speicherverbrauch. an welcher Stelle im Programm er weitermachen muß. daß eine Funktion sich selbst eine bestimmte. d. h. im Gegensatz zu diesen Speicherbereichen aber i. wenn er Rekursion benutzt: Durch die Anwendung der Rekursion muß sich die Situation derart ¨ndern. ¨ die ein Programmierer sicherstellen muß. in der Praxis nat¨rlich je fr¨her desto besser) der Algorithmus f¨r u u u jede Aufgabenstellung terminiert. Insbesondere auch die Daten jeder Rekursionsstufe ( lokale“ Variablen) kosten viel ” Speicherplatz: Das Einf¨hren einer zus¨tzlichen Variable geht dabei mit einer Vervielfau a chung des Speicherbedarfs f¨r die Rekursion einher. wo die jeweilige Funktion fortgesetzt wird. Sieht man sich nun einmal den Algorithmus n¨her an. PHP Grundlagen Rekursion auf den Zielstapel zu bewegen. weil sie sich doch unterscheiden. Eigentlich deshalb. selbstdefinierten Variablen und ggf. daß die Funka tion sich selbst aufruft. Last in first out Dies ist Teil der sog. vom Speicherende 33 34 35 Und mehr noch die Ackermann-Funktion. Das einzige. wie tief die Funku tion verschachtelt aufgerufen wird. daß die Funktion sich irgendwann nicht mehr aufruft. h. der dem letzten hinzugef¨gten Eintrag entspricht (das sog. zuvor meist nicht bekannte Anzahl mal selbst aufruft und nach etlichen Aufrufen irgendwann beendet. sinnvoll beendet wird – man kann auch sagen. Schon bei nur 20 Scheiben sind 220 − 1 = 1048575 Schritte notwendig! Die M¨nche w¨ren also f¨r hundert Scheiben ihr Leben lang und dar¨ber o a u u hinaus besch¨ftigt . ist die jeweilige Ausgangssituaa tion. daß rekursiv definierte Funktionen ein z. es liegen jedesmal weniger Scheiben auf dem Startstapel und mehr auf dem Zielstapel. daß in endlicher Zeit (d. und zwar nur in den Werten ihrer lokalen. wird das Prinzip dahinter klar: Rekursion bedeutet. a Doch was mag das nun mit Rekursion zu tun haben? Nun. daß es sich ¨ ” um einen wiederholten Aufruf derselben Funktion mit bestimmten Eingabedaten handelt. ahnlich wie bei Schleifen. . Stack verwaltet.8. was sich dabei ¨ndert. bei den beiden zentralen Dingen. auch Stapel genannt. Damit ist dann zwar diese Funktion beendet.2 Speicherverbrauch und Stack F¨r den Computer bedeutet eine große Zahl von Rekursionsstufen. a irgendwann einmal. s. Das mag auf den ersten Blick komisch aussehen. Von diesem kann man immer nur den obersten Eintrag sehen. sondern statt dessen beendet. . h. u 8. sieht man. Das Besondere ist nun. machen die M¨nche im Prinzip immer wieder dasselbe: Sie bewegen Scheiben von einem o Stapel zum anderen. aber diese wurde ja von einer anderen Funktion aufgerufen. d. die Abbruchbedingung muß irgendwann erf¨llt werden. um zu verdeutlichen. Das Beispiel der T¨rme von Hanoi33 u u zeigt eindrucksvoll. Anstatt jeweilige Funktion“ sagt man ubrigens Rekursionsstufe. daß beide Funktionen eigentlich gleich sind. u. d. h. u Die genannten Informationen werden intern auf dem sog. Die Gr¨ße des Stacks ist auu o ßerdem beschr¨nkt. da er sich ja den Hauptspeicher mit dem Programm selbst sowie seinen a Daten teilen muß35 . wenn die von ihr aufgerufene Funktion sich beendet. von Neumann-Architektur Jens Hatlak Seite 117 .10. Damit sind wir auch schon. aber wenn man sicherstellt. die nun an der Stelle nach dem Funktionsaufruf fortgesetzt wird. in der jeweiligen Stelle. wenn eine Rekursionsstufe durchlaufen wurde und damit verlassen wird. A.

3 Vorteile der Rekursion Rekursion hat aber nicht nur Nachteile. ack(4. 1) = ack(1. ack(4. a 8. Beispiel: ack(4. ack(4. . so kann man viele mittels Rekursion implementierte Funktionen auch iterativ programmieren. a Nur der Vollst¨ndigkeit halber gebe ich hier doch nochmal die genannte Ackermanna Funktion an:  . falls n = 0  m+1 ack(n . 0) = ack(3. PHP Grundlagen Rekursion her w¨chst. 3). Keller.4 Rekursion und Iteration im Vergleich Man k¨nnte meinen. In jedem anderen Fall. 1) = ack(2. m . die man nur mit Rekursion l¨sen o a o kann.1. s.1.10. 1) 7. ack(4. ohne daß das Auswirkungen o a auf die anderen. m) =  ack(n . außer dem R¨ckgabewert u ” k¨nnen alle Variablen nach Lust und Laune ver¨ndert werden. ack(2. . 2)) 2. nicht aber mit Iteration. 2) = ack(3. ack(4. hinzu. 0)) 36 Davon ausgenommen sind nat¨rlich Klassenvariablen und Referenzen auf Objekte in der OOP u Jens Hatlak Seite 118 . d. 1)) 3. die ja innerhalb der u a Rekursion meist selbst aus den Werten von lokalen Variablen und Parametern des vorigen Aufrufs berechnet werden. ack(4. 1) = ack(3. noch abzuarbeitenden Rekursionsstufen h¨tte36 . ack(3. einen Stack (Stapel. h. 8. so kann diese in jeder Rekursionsstufe einen anderen Wert haben und nat¨rlich von den Parametern des Funktionsaufrufs abh¨ngen. ack(3.1)) sonst Die Formel liest sich dabei wie folgt: Der Ackermann-Wert zweier nat¨rlicher Zahlen n u und m ist m + 1. ack(3. o so berechnet sich das Ergebnis rekursiv mit n = n − 1 und m = 1. 0) = ack(2. ack(n. 1) 5.8. ack(4. Lediglich mehrfach rekursive Funktionen wie die Ackermann-Funktion bilden hier die Ausnahme – im Alltag trifft man diese aber wohl nicht allzu h¨ufig an. Ein großer Vorteil dieser Methode ist. muß zuerst die Rekursion mit n = n und o m = m − 1 berechnet werden und das Ergebnis als m f¨r die Rekursion mit n = n − 1 u eingesetzt werden. 3) = ack(3. falls n Null ist. also letztlich nur wenn n und m gr¨ßer Null sind. o. n > 0. Ist dagegen n gr¨ßer Null und gleichzeitig m gleich Null.10. es g¨be viele Problemstellungen. Verwendet man beispielsa weise eine Variable n. daß man in jeder Rekursionsstufe wieder neue lokale“ Variablen hat. ack(2. m = 0 ack(n. 0)) 4. 1. 0)) 6. In Wahrheit sind beide Formen der Programmierung aber ann¨hernd gleich m¨chtig: Nimmt man zur klassischen Iteration n¨mlich noch die M¨ga a a o lichkeit. 1) .) zu benutzen.

B. m¨glich. Grunds¨tzlich enth¨lt eine moderne“ Mail oft mehrere u u a a ” 37 -Parts genannt. kann man das Erkennen von Attachments (Mail-Anh¨ngen) oder a anderen speziellen Teilen. . hast du es o a vielleicht schon gemerkt: Sowohl das Anlegen wie auch das Auslesen bzw. Da eine E-Mail in Wirklichkeit nichts anderes als ein speziell geu gliederter ASCII-Text ist. Die rekursive Funktion geht nun durch den kompletten Parts-Baum und stellt u 37 Multi Purpose Internet Mail Extensions. wenn es darum geht. der einen Part identifiziert. ack(1. ack(1. ack(1. ack(0. o eine E-Mail mit Attachments weiterzuleiten.8. Der eigentlichen. daß die f¨r das Extrahieren bestimmter Parts n¨tige Funktion imap_fetchbody() u o einen String als Parameter erwartet. PHP Grundlagen Rekursion 8. 1) 11. einen solchen o Praxisbezug aufzuweisen. ack(1. 2) = 2 + 1 = 3 = ack(1.10. ack(1. Interpretieren eines solchen Baumes l¨ßt sich am besten rekursiv l¨sen. ack(1. a E-Mails zu entschl¨sseln. rekursiv definierten. . um die Struktur f¨r die jeweilige E-Mail zu beu kommen (in diesem Fall in Form eines verschachtelten Objekts).5 Ein Beispiel aus der Praxis: MIME parsen Bei solch an sich so theoretischen Dingen wie Rekursion fragt sich vielleicht mancher. Diese Parts sind in einem Baum (siehe auch Kapitel 7. aber an einer zentrau len Stelle muß man doch selbst etwas konstruieren: Dann n¨mlich. das imap_fetchstructure() als Unterobjekt der Hauptstruktur zur¨ckliefert. dem HTML-Anteil einer Mail. ack(2. 2)) 14. Mehrzweck-Internet-E-Mailerweiterungen Jens Hatlak Seite 119 . die Funktion imap_fetchstructure() zu benutzen. Durch diesen Aufbau ist es z. Die PHP-IMAP-Funktionen o bieten schon recht viel dessen. An dieser Stelle m¨chte ich deshalb die Gelegenheit nutzen. o Benutzt man nun tats¨chlich die PHP-IMAP-Funktionen. dann wird man schnell festa stellen. 0) 13. Wenn du diesen Satz in seiner ganzen Komplexit¨t genau gelesen hast. 3) = ack(0. neu zu schreibenden Funktion ubergibt man nun ¨ das Parts-Objekt. 1)) 15. wie z. 1) = 1 + 1 = 2 = ack(1. der sich beliebig verzweigen kann. Angenommen. was man f¨r das Backend braucht. 1) = ack(0. 0)) 10. Dieser String setzt sich aus durch Punkte getrennten Zahlen zusammen und muß leider – wie oben schon angedeutet – selbst zusammengezimmert werden. was man damit in der Praxis – hier meine ich damit das Programmieren in PHP – anfangen kann. ack(1. 0) = ack(1. Ein iterativer Ansatz ist bestimmt a o auch m¨glich. B. du m¨chtest ein Webmail-System bauen. 1) 9. ack(0. auf das Erkennen von bestimmten Strings zur¨ckf¨hren. 2) = ack(0. 0) = ack(0. MIME organisiert. Hierzu bietet es sich an. dabei neue Attachments anzuh¨ngen und a trotzdem die Ursprungsmail mit ihren Attachments theoretisch problemlos extrahieren zu k¨nnen.4) Teile. als einfach Rekursion zu benutzen. 0) 12. 8. 1) = ack(2. . aber sicher sehr viel weniger intuitiv.

dann entstehen. ¨ Der folgend dargestellte Aufbau einer komplexen Mail sollte das verdeutlichen (¨beru setzte Version von http:// www.2 4.2. der sp¨ter a a als Nachrichtentext ausgegeben wird. die bereits o Attachments enth¨lt. h.2. Jens Hatlak Seite 120 . da sie a neben dem HTML-Teil meist auch einen reinen ASCII-Textteil enthalten. Bei der R¨ckkehr aus jeder Rekursionsstufe ist der ID-String im Array $data unveru andert. Innerhalb einer Rekursionsstufe setzt sich der lokale ID-String aus dem ID-String im Array $data sowie der Nummer des aktuellen Parts zusammen.1 4.TEXT 3. PHP Grundlagen Rekursion f¨r jedes Blatt den Part-Typ fest. Außerdem werden auch HTML-Mails intern mit MIME-Parts realisiert. d. Diesen String erh¨lt man a wie folgt: 1.org/ rfc/ rfc2060. Die gesuchte Part-Nummer ist dabei immer um eins gr¨ßer als der Array-Z¨hler.HEADER 4.2. ubergeben.2. Im Falle eines Attachments wird einfach dessen Struktur u analysiert und die relevanten Daten wie Name und Kodierung vermerkt.txt): HEADER TEXT 1 2 3 3. wird dieser an den String angeh¨ngt. Beim erstmaligen Aufruf der Funktion ist der ID-String im Array $data noch nicht gesetzt.2. Vor dem Starten einer neuen Rekursionsstufe wird der lokale ID-String statt des ID-Strings. Handelt es sich jedoch um einen anzuzeigenden Text-Part.2. o a 3.2. komplett eingebettet weiterleitet und dann noch eigene Attachments a anh¨ngt. 2.MIME 4.TEXT 4. außer.1 4. wenn man eine Nachricht. der ID-String im Array ist leer (erste Rekursionsstufe). Zur Extraktion des Textes aus einem solchen Part muß wie gesagt der spezielle Identifizierungsstring bekannt sein. getrennt durch einen Punkt.2 4 4. leer.1 3.2. der sich im Array $data befindet.1. ¨ 4.ietf. B.8.2 4.2 ([RFC-822] Header der Nachricht) MULTIPART/MIXED TEXT/PLAIN APPLICATION/OCTET-STREAM MESSAGE/RFC822 ([RFC-822] Header der Nachricht) ([RFC-822] Textk¨rper der Nachricht) o TEXT/PLAIN APPLICATION/OCTET-STREAM MULTIPART/MIXED IMAGE/GIF ([MIME-IMB] Header des IMAGE/GIF) MESSAGE/RFC822 ([RFC-822] Header der Nachricht) ([RFC-822] Textk¨rper der Nachricht) o TEXT/PLAIN MULTIPART/ALTERNATIVE TEXT/PLAIN TEXT/RICHTEXT Solch komplexe Mails k¨nnen z.HEADER 3.1 4.

8. if ( is_array ( $ p a r t s [ $ i ]-> parts )) { // R e k u r s i o n .. Die Funktion imap_fetchbody extrahiert hierbei den Nachrichtenk¨rper. daß eine solche Anweisung im Verlauf der Rekursion immer in endlicher Zeit erreicht werden muß. Sie erwartet als Parameter einen ge¨ffneo o ten Mailbox-Stream. daß es eine Anweisung zur Beendigung von Rekursionsstufen gibt. // Daten−A u s w e r t u n g In diesem Beispiel ist die Abbruchbedingung in Form der return-Anweisung noch recht einfach erkennbar. $ d a t a ). PHP Grundlagen Rekursion Das folgende Code-Beispiel zeigt den Rahmen einer entsprechenden Implementierung innerhalb einer geeigneten Klasse (siehe Kapitel 20). $ t h i s -> msgid . Die Funktion imap_fetchstructure schließlich liefert ein Objekt zur¨ck. $ i ++) { // ID−S t r i n g : < ID−S t r i n g >. a. . Wichtig ist dabei weniger. um Leerzeichen vorne und hinten sowie Escapezeichen zu entfernen sowie Sonderzeichen (Umlaute. $ i +1). Auf ihren R¨ckgabewert werden dann noch einu mal einige Funktionen angewendet. ( $ d a t a [ ” i d s t r ”]!= ’ ’ ? ’ .<Partnummer> $ i d s t r = sprintf ( ”%s%s%d ”. $ d a t a = $ t h i s -> parseParts ( $ p a r t s [ $ i ]-> parts .. $ d a t a ) { // S c h l e i f e u b e r a l l e P a r t s d e r a k t u e l l e n Ebene ¨ for ( $ i =0. } $ s t r u c t u r e = im ap_fetchstructure ( $ t h i s -> mbox . ) zu konvertieren. Da bei einer Jens Hatlak Seite 121 . $ d a t a ). $ d a t a [ ” i d s t r ”]. . $ d a t a [ ” i d s t r ”] = $tmp ... also den eigentlichen Text. $ i < count ( $ p a r t s ). eine Message-ID. Andernfalls gibt es schnell eine sich unendlich weiterverschachtelnde Rekursion: das Pendant zur Endlosschleife. eine Part-ID sowie (optional) ein Flag zum Benutzen von eindeutigen Message-IDs. f a l l s a k t u e l l e r P a r t U n t e r p a r t s e n t h ¨ l t a $tmp = $ d a t a [ ” i d s t r ”]. . FT_UID )))).. die bereits einen Mailbox-Stream und die Message-ID bereitstellt. } . .. ’ : ’ ’ ). $ d a t a = $ t h i s -> parseParts ( $ s t r u c t u r e -> parts . . $ i d s t r . a function parseParts ( $ p a r t s . // w e i t e r e B e h a n d l u n g } } return $ d a t a . das Aufschluß uber die Struku ¨ tur der E-Mail gibt und u. $ d a t a [ ” i d s t r ”] = $ i d s t r . sondern vielmehr. // Code f u r A t t a c h m e n t−Erkennung ¨ if (! $ i s a t t a c h m e n t ) { // k e i n A t t a c h m e n t −> Body $msgbody = htmlspecialchars ( stripslashes ( trim ( imap_fetchbody ( $ t h i s -> mbox . $ t h i s -> msgid . FT_UID ). alle MIME-Parts in verschachtelten Arrays enth¨lt.

o.8. Vermeiden sollte man sowas aber trotzdem auf jeden Fall! Christoph Reeg Seite 122 . PHP Grundlagen Rekursion Rekursion rechnerintern die R¨cksprungadressen immer auf dem Stack gespeichert werden u (s. gibt es dann u ¨ mehr oder weniger schnell den gef¨rchteten stack overflow.) und dieser irgendwann den normalen Speicher uberschreiben w¨rde. wird aber schlimmstenfalls nur das Script unsanft beendet. der Rechner riegelt ab. d. u bevor schlimmeres passiert. h. Da PHP nur eine Scriptsprache ist.

Christoph Reeg Seite 123 . Danach ist es standardm¨ßig ausgeschaltet (und das ist auch a a gut so).1 Formulare Mit PHP k¨nnen Formulardaten relativ einfach eingelesen werden.php‘ ubermittelt. kann man ab u ¨ PHP 4. ” In ¨lteren PHP-Versionen heißen diese Arrays $HTTP_GET_VARS bzw. implizit u wieder ubergeben werden – wenn das Formular also mit GET arbeitet.html‘ eingetragen wurden.X der Fall ist. ¨ Gilt allgemein f¨r alle POST/GET-Ubergaben! u Das Gesagte gilt nur.).html‘: <!DOCTYPE HTML PUBLIC ”−//W3C//DTD HTML 3 . Zu beachten ist dabei. was standardm¨ßig bis Version 4. je nach Ubergabeart.1.1 die superglobalen“ Arrays $_GET und $_POST. verwenden. hat man nach dem ¨ Absenden sowohl die urspr¨nglichen als auch die neuen GET-Parameter! u Die Felder eines verschickten Formulares2 werden beim Laden der Empf¨ngerseite (ana gegeben im . $HTTP_POST_VARS a und m¨ssen außerhalb des Script-Hauptteils explizit als global deklariert werden (global u $var. wenn in der PHP-Konfiguration register_globals aktiviert wurde. daß in diesem Fall alle GET-Parameter des Scriptaufrufs. Bei ‘get‘ kann man sonst die Werte der Eingabe in a 1. URL-encoded Format. n¨mlich dann.action‘ des Formulars) automatisch in Variablen gleichen Namens verwandelt.9 PHP & HTML 9. Durch u ¨ diese werden sie dann ausgegeben. werden durch Dr¨cken von OK an die Datei ‘ausgabe. auf die man im Verlauf des Script-Hauptteils direkt zugreifen kann. die auf der Seite ‘eingabe. u. Man muß im Formular o als action den Dateinamen der das Formular auswertenden PHP-Datei angeben und als method empfiehlt sich h¨ufig ‘post‘. 2 / / EN”> < html > < head > < t i t l e > Eingabe </ t i t l e > </ head > < body > < d i v a l i g n = ” c e n t e r ”> < form a c t i o n = ” a u s g a b e . der URL wiederfinden In bestimmten F¨llen macht es auch Sinn. kein action anzugeben. Nun ein kleines Beispiel. der zum Anzeigen des Formulars f¨hrte. wenn a a das Zielscript dasselbe wie das aktuelle ist. s. Die Eingaben.3 Will man auf solche Variablen auch in Funktionen zugreifen. Quelltext der Datei ‘eingabe. php ” method = ” p o s t ”> Feld1 : < i n p u t name= ” f e l d 1 ” s i z e = ”60 ” m a x l e n g t h = ”60 ”> < b r > Feld2 : < i n p u t name= ” f e l d 2 ” s i z e = ”60 ” m a x l e n g t h = ”60 ”> < b r > < i n p u t t y p e = ” s u b m i t ” v a l u e = ”OK”> 1 2 3 Im sog. ohne sie global definieren zu m¨ssen.

?> </ body > </ html > Nat¨rlich kann die Seite zum Senden und die zum Auswerten auch genau dieselbe sein. PHP & HTML Werte ubergeben ¨ < i n p u t t y p e = ” r e s e t ” v a l u e = ”Abbrechen ”> </ form > </ d i v > </ body > </ html > Quelltext der Datei ‘ausgabe. wie Umlaute. Siehe auch Kapitel 9.4. beim Verschicken von Formularen wird quasi f¨r jeu des Feld urlencode aufgerufen und beim Bereitstellen der POST/GET-Daten in Dateien Christoph Reeg Seite 124 . php ? v a r 1=Wert1&v a r 2 =2 ”> Linktext </ a > Allgemeiner formuliert: An das Verweisziel (in unserem Fall ‘datei. a weitere Werte mit einem ‘&‘ statt ‘?‘. a 9. sieht der Link folgendermaßen aus: ¨ < a h r e f = ” d a t e i . Diese Variante (Formular und Auswertung in einer Seite) hat sich in vielen Situationen als praktisch erwiesen und wird deshalb auch h¨ufig empfohlen. Leerzeichen. Dies ist nat¨rlich auch m¨glich. m¨ssen nach einem bestimmten Schema kodiert werden. Ein normaler HTML-Link sieht u o folgendermaßen aus: < a h r e f = ” d a t e i . u PHP bietet mit den Funktionen urlencode und urldecode die M¨glichkeit. php ”> Linktext </ a > Wenn man jetzt der Datei die Werte ‘Wert1‘ und ‘2‘ in den Variablen ‘VAR1‘ und ‘VAR2‘ ubergeben will. ohne ein o ¨ Formular zu verwenden.9. Es d¨rfen keine Leerzeichen dabei entstehen.oder Fragezeichen.php‘) wird mit einem ‘?‘ beginnend der Variablenname und mit einem Gleichheitszeichen der Wert angeh¨ngt.2 Werte ubergeben ¨ Es gibt auch Situationen. das Kaufmannsund. 2 / / EN”> < html > < head > < title > Ausgabe </ title > </ head >< body > <? php printf ( ” F e l d 1 : % s<b r>F e l d 2 : % s ”. das URL-encoded genannt wird. $ POST[ ” f e l d 2 ”]). da m¨chte man dem PHP-Script Werte ubergeben. Strings von o und in dieses Format zu wandeln. $ POST[ ” f e l d 1 ”].php‘: <! DOCTYPE HTML PUBLIC ”−//W3C//DTD HTML 3 . Sonu derzeichen in Werten. u in diesem Fall muß sie logischerweise eine PHP-Endung haben.

Der Name wird beim Verschicken des Formulars zum Namen der Variable bzw. Zeichen / : . der das Formular abschickt. Im Wesentlichen sind folgende Elemente zu unterscheiden: 1. u ¨ 9. .3 Dynamische Formulare ¨ Formulare zur Ubermittlung von Daten (per POST oder GET) an sich sind schon ganz brauchbar. aber f¨r wirklich interaktive.9. Grunds¨tzlich hat a a jedes solcher Elemente einen Namen (name) und einen Wert (value). Wird ein Name angegeben. so hat dieser der HTML-Syntax entsprechend den Wert des Buttontitels. A. Tabelle . 4 ¨ Uber einfaches Kopieren und Ver¨ndern der URL a Jens Hatlak Seite 125 . INPUT-Felder gliedern sich in folgende Typen (type): a) TEXT: Normales Texteingabefeld b) PASSWORD: Paßworteingabefeld (Anzeige von Sternchen statt Zeichen) — ¨ Achtung: Die Ubermittlung erfolgt i.urlencoded‘ listet die wichtigsten Sonderzeichen und ihre Kodierung auf. insbesondere den Formularelementen.1: urlencoded umgekehrt urldecode. dynamische Formulare braucht es noch etwas u mehr Verst¨ndnis von HTML. PHP & HTML Dynamische Formulare Zeichen Leerzeichen ! ” # $ % & ’ ( ) * + . daß jeder4 die ¨ Werte beim Aufruf ver¨ndern kann. Code + %21 %22 %23 %24 %25 %26 %27 %28 %29 * %2B %2C . ungesichert! c) SUBMIT: Button. Wenn man die ubergebenen Werte verwendet. Deshalb sollten die Variablen vor der Weiterverarbeia tung auf korrekte Werte hin uberpr¨ft werden. darf man nicht vergessen. < = > ? @ [ \ ] ˆ ‘ Code %2F %3A %3B %3C %3D %3E %3F @ %5B %5C %5D %5E %60 — Zeichen { | } ˜ a ¨ o ¨ u ¨ ¨ A ¨ O ¨ U ß — — — Code %7B %7C %7D %7E %E4 %F6 %FC %C4 %D6 %DC %DF Tabelle 9. des Indexes im Array. die den Wert des entsprechenden Formularelements annimmt.

wie die genannten Formularelemente eingesetzt werden k¨no nen und wie ihre Vorbelegung implementiert wird. nat¨rlich auch Arrays. verwendet werden. kein) Knopf“ gleichzeitig gedr¨ckt sein kann. $ i < count ( $ b e r u f e ). 5 6 7 Hindert nat¨rlich keinen. so dienen die Eintr¨ge a selbst als Werte. o ¨ f) HIDDEN: verstecktes Feld. a 2. ob auch auf Typgleichheit gepr¨ft u werden soll. Interessant ist dabei u. wird dies mit dem a Attribut checked (bei HTML ohne Wert) angegeben. PHP & HTML Dynamische Formulare d) RADIO: Radiobutton. B. Auf diese Weise lassen sich besonders gut logisch zusammengeh¨rende Mehrfachauswahlen realisieren. functions. booleschen Parameter kann man optional noch angeben. die weder ver¨nderbar noch sichtbar sein sollen 5 . auch is_numeric() f¨r Zahlen u Als dritten. in Verbindung mit einer Datenbank-Anbindung. ” O e d i e ”. $ i ++) { printf ( ”<o p t i o n v a l u e =\ ”% d \ ”%s>%s </ o p t i o n >\n ”. Ist das value-Attribut bei den option-Tags nicht vorhanden. u und mit in_array() kann man feststellen.inc: <? php /∗ ∗ ∗ B e r u f−O p t i o n e n a u s g e b e n ∗ ∗ @param $ b e r u f B i s h e r i g e r Wert ∗/ function pri nt_beru f_options ( $ b e r u f =0) { $ b e r u f e = array ( ” A n g e s t e l l t e r ”. ” S t u d e n t / S c h u e l e r ”). Soll sie standardm¨ßig gesetzt sein. Dient der Ubermittlung von Informationen. Haben mehrere Checkboxen den gleichen Namen und endet dieser mit den Zeichen []. aus der nur ein (oder am Anfang ggf. deren zugeh¨rige Checkboxen a o beim Verschicken gesetzt waren. das genau die Eintr¨ge a (mit den jeweils entsprechenden Werten) enth¨lt. ob ein Wert (Parameter 1) in einem Array (Parameter 2) enthalten ist. for ( $ i =0. Mehrere Radiobuttons mit demselben Namen aber unterschiedlichem Wert werden zu einer Gruppe zusammengefaßt. die aus o u einer SQL-Abfrage resultieren. ob eine Variable ein Array ist6 .7 Anstelle der statischen Arrays in den beiden Funktionen f¨r die Ausgabe der Optionen u k¨nnen. Solche Arrays erstellt man i. die Verwendung zweier neuer PHP-Funktionen: is_array() pr¨ft. Jens Hatlak Seite 126 . e) CHECKBOX: Checkbox. A.9. Der stanu ” dardm¨ßig gew¨hlte Knopf wird mit dem Attribut checked (bei HTML ohne a a Wert) definiert. so werden sie bei der Umwandlung durch PHP in ein Array umgewandelt. sie trotzdem zu ver¨ndern u a Es gibt z. mittels einer while-Schleife. SELECT-Boxen erlauben die Auswahl eines Eintrags aus einer Dropdown-Liste. Das folgende Beispiel zeigt.a.

nliche Daten </ title > </ head > < body > <? php // l o k a l e V a r i a b l e n s e t z e n $ v a r s = array ( ” s e n d e r ”. htmlentities ( $ s e n d e r )). 2 / / EN”> < html > < head > < title > Pers & ouml . i n c ”). ” R a d f a h r e n ”. ”vorname ”.9. $ h o b b i e s = array ( ” L e s e n ”. ” g e s c h l ”. for ( $ i =0. ” v a l u e =\ ”% s \ ”%s > % s \ n ”. } } ?> daten. ( in_array ( $ h o b b i e s [ $ i ]. foreach ( $ v a r s as $ v a r ) $ $ v a r = $ POST[ $ v a r ]. $ i < count ( $ h o b b i e s ). ( $ b e r u f ==( $ i +1) ? ” s e l e c t e d ” : ” ”). } } /∗ ∗ ∗ Hobby−O p t i o n e n a u s g e b e n ∗ ∗ @param $hobby Array b i s h e r i g e r Werte ∗/ function pri nt_hobb y_options ( $hobby ) { if (! is_array ( $hobby )) $hobby = array ().php: <? php include ( ” . $hobby ) ? ” c h e c k e d ” : ” ”). ”. ”hobby ”). Jens Hatlak Seite 127 . / f u n c t i o n s . if (! isset ( $ g e s c h l )) $ g e s c h l = ’m’ . $hobbies [ $i ] ). ”name ”. ” b e r u f ”. ”Schwimmen ”). ?> <! DOCTYPE HTML PUBLIC ”−//W3C//DTD HTML 3 . PHP & HTML Dynamische Formulare ( $ i +1). $ i ++) { printf ( ”<i n p u t t y p e =\ ”checkbox \ ” name=\ ”hobby []\ ” ”. if ( $ s e n d e r ) printf ( ” D i e Daten wurden von % s a u s v e r s c h i c k t . htmlentities ( $ h o b b i e s [ $ i ]). htmlentities ( $ b e r u f e [ $ i ]) ).

< input type = ” r a d i o ” name = ” g e s c h l ” value = ”w”<? php printf ( ”%s ”. das Anlegen oder Aktualisieren von Datens¨tzen einer entsprechenden Daa tenbank.9. php ” method = ” p o s t ”> < input type = ” h i d d e n ” name = ” s e n d e r ” value = ” d a t e n . ?>< br > < input type = ” s u b m i t ” value = ” W e i t e r ”> < input type = ” r e s e t ” value = ”Zur&uuml . c k s e t z e n ”> </ form > </ body > </ html > Der Effekt dieser ganzen Abfragen und Zusatzangaben ist letztlich nicht nur. B. m¨ßte dieses Feld datenbanko u technisch wohl relational definiert werden. nicht weiterverarbeitet. h t m l e n t i t i e s ( $name ) ) . In diesem Beispiel werden die verschickten Daten. h t m l e n t i t i e s ( $vorname ) ) . daß die Daten verschickt werden. ?>> m & auml . ?> ”>< br > Geschlecht : < input type = ” r a d i o ” name = ” g e s c h l ” value = ”m”<? php printf ( ”%s ”. php ”> Vorname : < input name = ”vorname ” size = ”25 ” maxlength = ”60 ” value = ”<?php p r i n t f ( ”% s ” . die eine ¨ Auswahl erm¨glichen. sondern daß auch das Formular nach dem Verschicken wieder genau so aussieht.Bitte w & auml . also uber eine Zusatztabelle. Da im obigen Beispiel die Hobbies uber Checkboxen realisiert wurden. hlen ---</ option > <? php prin t_beruf _options ( $ b e r u f ). Anbieten w¨rde sich f¨r pers¨nliche u u u o Daten z. bis auf das Ausf¨llen des Formulars. nnlich & nbsp . PHP & HTML Dynamische Formulare ?> < form action = ” d a t e n . die die Beziehung ¨ zwischen pers¨nlichen Daten und einer Hobbytabelle herstellt: o Jens Hatlak Seite 128 . ?> ”>< br > Name : < input name = ”name ” size = ”25 ” maxlength = ”60 ” value = ”<?php p r i n t f ( ”% s ” . wie zuvor. die aus mehreren Werten besteht. ( $ g e s c h l == ’ w ’ ? ” c h e c k e d ” : ” ”)). ?> </ select >< br > Hobbies : <? php prin t_hobby _options ( $hobby ). ?>> weiblich < br > Beruf : < select name = ” b e r u f ”> < option value = ”0 ”<? php echo (! isset ( $ b e r u f ) ? ” s e l e c t e d ” : ” ”). ?>>--. ( $ g e s c h l == ’m’ ? ” c h e c k e d ” : ” ”)).

darf jedoch keine direkte Ausgabe. erfolgen. nach gleichen Eintr¨gen suchen. den Wert. A. durch Abfragen des Submit-Buttons erreichen. ob Daten verschickt wurden oder nicht. vor der ersten direkten Ausgabe stehen o m¨ssen. korrigierte Werte gesetzt werden m¨ssen (nebst Erstellung einer u Fehlermeldung. a ob die Variable. o dessen Beschriftung bekanntlich gleich seinem Wert ist. denn in PHP ist jeder String außer dem leeren und 0“ gleich dem booleschen Wert TRUE. die gesamte Datenverarbeitung an den Beginn eines PHP-Scriptes zu stellen und darauf zu achten.2: Datenbank-Realisierung der Hobbies-Mehrfachauswahl 9. dann ist jedoch unbedingt darauf zu achten. wenn das Formular nach erfolgtem Eintragen und Verschicken von korrekten Daten nicht mehr gebraucht wird8 . bevor nicht alle Header ausgegeben worden sind. falls das (hier nicht angegebene) Formular abgeschickt wurde. daß man HTTP-Header. Eine Weiterleitung uber HTTP-Header macht v. auf neue. das sich einfach daraus ergibt. assoziativen Array9 . a Die Erkennung. u Es bietet sich also an. In PHP spielt es dabei meist ¨ eine untergeordnete Rolle. die zusammen mit allen anderen an zentraler Stelle ausgegeben werden kann). je nach Ubermittlungsart Jens Hatlak Seite 129 . das die Daten verschickt.4 Normalform von Formularen Die Verarbeitung von Daten. wenn er einen Namen hat. ” Im folgenden Schema sei $submitted true. die den gleichen Namen hat wie der Submit-Button des Formulars. ob man f¨r die Uberpr¨fung die Funktion isset(var) benutzt. daß ein Reload“ ” der Seite keinen Effekt hat. a. HID → hobbies ID Tabelle 9. print(f) oder bloßer Text außerhalb der PHP-Marken. Dies wiederum bedeutet. B. daß kein einziges anderes Zeichen vor der ersten PHPMarke (am Dateianfang) steht.oder Methou ¨ denaufrufe (bei OOP. Das k¨nnte man z. daß die Daten nicht nur verifiziert und damit ggf. ob eine dopu ¨ pelte Eintragung durch falsche bzw. folgt allgemein ei¨ nem bestimmten Schema. $_GET. Wie wir aus Kapitel u 11. Der gesamte Datenverarbeitungsblock kann nat¨rlich auch uber Funktions. kann eine Fehlermeldung generiert und das Formular ggf. daß alle Codeabschnitte. PHP & HTML Normalform von Formularen pers daten ID pd hob ← PID.1 wissen. In diesem Fall hat dies auch den Vorteil. mittels echo. u u die auf Existenz einer Variable testet.9. sondern im Verlauf der Datenverarbeitung auch der Fall auftreten kann. Auch sonst sollte man aber immer uberpr¨fen. mit den korrigierten Daten erneut angezeigt werden. B. gesetzt ist oder nicht. dann ¨ Sinn. schicken will. mißbr¨uchliche Browserbenutzung m¨glich ist und a o entsprechende Vorkehrungen bei der Konstruktion der Datenverarbeitung treffen (z. davon abh¨ngig. die uber ein Formular verschickt werden. anstatt weiterzuleiten ¨ $_POST bzw. macht man i. hierbei bieten sich besonders u 8 9 Sind die Daten nicht korrekt. eine saubere Parameter¨bergabe zu verwenden. der als value-Attribut angegeben wurde a – welcher in diesem Fall gleichbedeutend ist mit Button-Titel. also z. bevor ein INSERT versucht wird). siehe Kapitel 20) erledigt werden. die unter irgendwelchen Bedingungen HTTP-Header ausgeben k¨nnten. Zur Erinnerung: Ein solcher Submit-Button tr¨gt dann. genau gesagt an der Indexposition mit Namen des name-Attributs des Submit-Buttons. oder einfach direkt die Variable abfragt. B. wie f¨r eine Weiterleitung notwendig. Wie alle anderen Formularwerte findet sich auch der des Submit-Buttons im passenden superglobalen.

HTML−F o o t e r−I n c l u d e ?> Mit den Includes sind m¨gliche Einbindungen von Funktions. so daß danach die Variablen. muß nat¨rlich das Formular ausgef¨llt werden. h¨ngt ganz vom a ¨ jeweiligen Fall ab. g g f .1 Wieso ist das Null?! In obiger Formular-Normalform wird an der Stelle if (<Daten OK>) uberpr¨ft. z. Was genau an dieser Stelle zu tun ist. die u die Formularfelder vorbelegen. <? php // g g f . sinnvolle Werte haben. Falls Daten ge¨ndert werden sollen (im Beispiel angedeutet durch Abfragen der booleschen a Variable $fillform). Ein sch¨nes Beispiel f¨r die Anwendung des hier gelesenen findet sich ubrigens in Kapitel o u ¨ 16. daten[vorname] Jens Hatlak Seite 130 .4. HTML-Ausgaben. 10 Namensvergabe im Formular: einheitlicher Name.9. h. mit dem ¨ Integerwert 0 verglichen werden und dabei angenommen wird. F e h l e r m e l d u n g e n e r z e u g e n ¨ if (< Daten OK >) { // e i g e n t l i c h e V e r a r b e i t u n g : // − neuen D a t e n s a t z a n l e g e n // − b e s t e h e n d e n D a t e n s a t z a k t u a l i s i e r e n // − b e s t e h e n d e n D a t e n s a t z l ¨ s c h e n o // und g g f . w e i t e r l e i t e n } else { // F e h l e r m e l d u n g e r z e u g e n // ( i n V a r i a b l e s c h r e i b e n ) } } elseif ( $ f i l l f o r m ) { // a l t e Daten l e s e n und i n V a r i a b l e n s p e i c h e r n } // F r u h e s t m ¨ g l i c h e A u s g a b e : g g f . HTML−Header−I n c l u d e . B.und Klassendefinitionso dateien gemeint bzw. daß Werte. o ¨ // F e h l e r a u s g e b e n ?> Hier das Formular ( mit Werten ) anzeigen <? php // g g f . d. die weitgehend unabh¨ngig von der Datenverara beitung sind (HTML-Header und -Footer). daß dies nur wahr wird. Ein h¨ufiger Denkfehler (im Englischen nennt man das ubrigens coma ¨ ” mon pitfall“) dabei ist. entsprechende u u DB-Abfragen m¨ssen gestartet und ausgewertet werden. direkt gefolgt von dem eigentlichen Variablenname in eckigen Klammern. PHP & HTML Normalform von Formularen assoziative Arrays an10 . F u n k t i o n s−I n c l u d e if ( $ s u b m i t t e d ) { // Daten p r u f e n . 9. die per GET oder POST ubermittelt werden. ob die u ¨ ubergebenen Werte korrekt sind.

9.2. weiß. if ($ POST[ ’ s t u e c k m e n g e ’ ]==0) { // F o r m u l a r f u r B e s t e l l u n g a u s g e b e n ¨ } else { // B e s t e l l u n g aufnehmen } Da hier nicht mittels === auf Typgleichheit uberpr¨ft wurde.9. PHP & HTML Normalform von Formularen wenn die fragliche Variable auch tats¨chlich den Wert Null (nicht null) hat. wird das Formular immer u ¨ ausgegeben werden (d.und GET-Werte sind immer Strings. h. Falsch gea dacht! Wer das aktuelle DSP bis zu dieser Stelle aufmerksam gelesen hat. die Abfrage ist in dieser Form nutzlos) – POST. . . warum: In Kapitel 8. Christoph Reeg Seite 131 . daß jeder String bei normalem Vergleich gleich dem Integerwert Null ist.1 wurde gesagt.

wird ein Standardwert genommen. In den Klammern stehen dann die Parameter.1 Syntax 10. ¨ Dieser hat große Ahnlichkeit mit dem anderer Programmiersprachen. Was muß in der Syntax erkl¨rt werden? Als erstes interessiert nat¨rlich der Funktionsa u name. folgendermaßen ausu sehen: $link = mysql_connect(’localhost’. Diese Informationen sind in der Syntax versteckt. auf den wir schon die ganze Zeit hingearbeitet haben: Die Verbindung von PHP und MySQL. In diesem Kapitel werden die Befehle beschrieben. wenn sie optional sind. wobei das string den erwarteten Typ angibt.10 PHP & MySQL Jetzt kommen wir zu dem Punkt. Da Funktionen immer was zur¨ckgeben. Eckige Klammern definieren jeweils einen optionalen Teil. string password ]]]) Christoph Reeg Seite 132 . string username [. h.1.2 mysql connect Syntax: resource mysql_connect ( [string server [. Mit allen Parametern w¨rde der Aufruf des Befehls z.1 allgemein Zum Beschreiben der Syntax von PHP-Befehlen hat sich ein gewisser Standard entwickelt. Die Typangabe und die eckigen Klammern werden sp¨ter selbstverst¨ndlich nicht mit a a eingegeben. Zwischen diesen beiden Sprachen ist streng zu trennen! 10. Weiter unten werden noch Befehlsfolgen f¨r gewisse Aufgaben aufgelistet. Nehmen wir als u Beispiel die Funktion mysql_connect().’MeinName’. u Hier werden jetzt Befehle von PHP und MySQL verwendet. Das Wort resource gibt den R¨ckgabetyp u der Funkion mysql_connect an. alle drei Parameter m¨ssen in diesem Fall vom u Typ string sein. interessiert auch der R¨ckgabetyp und last u u but not least muß man auch wissen.’MeinPasswort’). der nur bei Bedarf angegeben werden muß. Laut Anleitung ist die Syntax wie folgt (wegen Platzproblemen in zwei Zeilen geschrieben. Die genaue Beschreibung der Parameter und welche Standardwerte diese haben. B. eigentlich geh¨rt alles hintereinander): o resource mysql_connect ( [string server [.1. string password ]]]) Schauen wir uns die Syntax mal von vorne an. Wenn der jeweilige Parameter nicht angegeben wird. string username [. 10. steht in der anschließenden Beschreibung. d. welche Parameter die Funktion erwartet (und welchen Typ sie haben m¨ssen).

Die Verbindung wird automatisch bei Beenden des Scripts geschlossen. F¨r ‘username‘ und u ‘password‘ sind die von uns bzw. Mit dem Zeiger an sich kann man aber nicht viel anfangen. o Wenn der zur¨ckgegebene Wert nicht . o Es wird ein sogenannter Zeiger auf das Ergebnis (result pointer) zur¨ckgegeben. um die folgenden o Funktionen nutzen zu k¨nnen. um bei u o mehreren Verbindungen eine eindeutig bestimmen zu k¨nnen.FALSE‘ ist. Wird kein ‘link identifier‘ angegeben. o ¨ Christoph Reeg Seite 133 . u Bei einem zweiten Aufruf mit denselben Parametern wird keine neue Verbindung erstellt. sie kann aber auch mit mysql close() explizit geschlossen werden.3 mysql close Syntax: bool mysql_close ( [resource link_identifier]) mysql close schließt eine bestehende Verbindung zum Server. wird die zuletzt ge¨ffnete Verbindung zum o Server benutzt. Es wird entweder ‘TRUE‘ bei Erfolg oder ‘FALSE‘ bei einem Fehler zur¨ckgegeben. welche Verbindung geschlossen werden soll. Wenn nichts angegeben wurde. Es wird entweder ‘TRUE‘ bei Erfolg oder ‘FALSE‘ bei einem Fehler zur¨ckgegeben. resource link_identifier]) mysql query sendet die SQL-Befehlsfolge ‘query‘ an den Server mit der DB. PHP & MySQL Syntax Mit mysql connect() wird eine Verbindung zum Server ge¨ffnet. Dort wird er als Parameter result ubergeben. aber es wird der ‘link identifier‘ zur¨ckgegeben. wird die zuletzt ge¨ffnete Verbindung geschlossen. o Als ‘hostname‘ ist in unserem Fall immer localhost zu nehmen.10.1. u Wenn kein ‘link identifier‘ angegeben wurde. vielmehr ben¨tigt man ihn. wird die zuletzt ge¨ffnete Verbindung genutzt. resource link_identifier]) a Mit mysql select db wird die Datenbank ausgew¨hlt. die durch den ‘link identifier‘ festgelegt ist. verlief die Verbindung erfolgreich. Wenn u dieser (Result-)Zeiger den Wert .1.5 mysql query Syntax: resource mysql_query ( string query [.FALSE‘ hat. Der ‘link identifier‘ wird ben¨tigt. 10. von dir selbst zugewiesenen Werte zu nehmen. o 10. gibt es einen Fehler. u Mit ‘link identifier‘ kann explizit angegeben werden. 10.4 mysql select db Syntax: bool mysql_select_db ( string database_name [.1. auf die sich die Anfragen beziehen soll.

Wenn beim Join zweier Tabellen zwei Spalten denselben Namen haben. $ r e s u l t = mysql_query ( ”SELECT u s e r i d . Christoph Reeg Seite 134 . u d. $ p a s s w o r d ). echo $row [ ” f u l l n a m e ”]. gibt diese als Array zur¨ck und setzt den Result-Zeiger u auf die n¨chste Zeile. Dasselbe Beispiel wie bei mysql_fetch_array: <? php mysql_connect ( $ h o s t . PHP & MySQL Syntax 10.6 mysql fetch array Syntax: array mysql_fetch_array(resource result [. $ r e s u l t = mysql_query ( ”SELECT u s e r i d . mysql_select_db ( ” d a t a b a s e ”). u obwohl es deutlich angenehmer zu programmieren ist. MYSQL_NUM und MYSQL_BOTH. Bei MYSQL_NUM bekommt das zur¨ck gegebene Array einen durchnumerierten Index. f u l l n a m e FROM u s e r s ”). h. while ( $row = mysql_fetch_array ( $ r e s u l t )) { echo $row [ ” u s e r i d ”]. $ p a s s w o r d ).s1 AS foo. f u l l n a m e FROM u s e r s ”). mysql_select_db ( ” d a t a b a s e ”). <? php mysql_connect ( $ h o s t . Die Indizes des Arrays werden nicht von 0 ausgehend durchgez¨hlt. t2. Das optionale zweite Argument result_type in mysql_fetch_array ist eine Konstante und kann die folgenden Werte annehmen: MYSQL_ASSOC. sondern nach den Spaltennamen a benannt. m¨ssen ihnen u mit Hilfe der SELECT-Anweisung andere Namen gegeben werden. t2 Die Spalte s1 der Tabelle t1 hat nun den Namen foo und s1 aus t2 hat den Namen bar. F¨r ‘result‘ muß der R¨ckgabewert (=Zeiger) der ‘mysql query‘a u u Funktion genommen werden.1. Die Funktion ist in der Ausf¨hrung nur unwesentlich langsamer als mysql_fetch_row.s1 AS bar FROM t1. } ?> 10.10. Beispiel: SELECT t1. $ u s e r . $ u s e r .7 mysql fetch row Syntax: array mysql_fetch_row(resource result) Holt eine Zeile aus der DB-Abfrage. Bei MYSQL_ASSOC a werden die Spaltennamen als Index des Arrays genutzt und bei MYSQL_BOTH (was auch der Standard ist) gibt es beide Indizes. int resulttype]) a Dies ist eine erweiterte Version von ‘mysql fetch row‘ (siehe n¨chste Funktion). mysql_fetch_array verh¨lt sich genauso wie mysql_fetch_row.1.

1.8 mysql error Syntax: string mysql_error([resource link_identifier]) Gibt die Fehlermeldung des letzten SQL-Befehls zur¨ck. wird u 0 zur¨ckgegeben.1. an denen man es sich einfach machen kann. PHP & MySQL Tips und Tricks while ( $row = mysql_fetch_row ( $ r e s u l t )) { echo $row [0].1.1. wird u nichts zur¨ck gegeben. Gibt die Anzahl der Zeilen im Ergebnis zur¨ck. Im Folgenden sei bereits jeweils eine Datenbankverbindung hergestellt. u 10. } ?> 10. die beim letzten INSERT dem Feld mit AUTO_INCREMENT zugeu wiesen wurde. Wenn es keinen Fehler gab.2 Tips und Tricks Gerade beim Zusammenspiel von PHP und MySQL gibt es einige Stellen.11 mysql num rows Syntax: int mysql_num_rows(resource result). wird die zuletzt ge¨ffnete u o Verbindung genutzt. 10. 10. Wird kein ‘link identifier‘ angegeben. Wird kein ‘link identifier‘ angegeben. 10. wird die zuletzt ge¨ffnete Verbinu o dung genutzt.9 mysql errno Syntax: int mysql_errno([resource link_identifier]) Gibt die Fehlernummer des letzten SQL-Befehls zur¨ck.10. Wenn es keinen Fehler gab. wenn man weiß.10 mysql insert id Syntax: int mysql_insert_id([resource link_identifier]) Gibt die Nummer zur¨ck. Jens Hatlak Seite 135 . wie. echo $row [1].

die man beim MySQL-Prompt bekommt. von o ¨ einem Formular mit Checkboxen wie in 9. nennen wir es einmal delIDs. deren IDs im ubera o a ¨ gebenen Array vorkommen.3 beschrieben stammen: Auf einer Ubersichtseite. auf die hier nicht n¨her eingegangen wird. Wenn die Werte keine Integers sondern Strings sind. ” ) ”).3. wobei die VALUE-Attribute der Checkboxen genau den IDs der Datens¨tze entspr¨chen.00 sec) mysql> Christoph Reeg Seite 136 . kommt man aber wohl kaum um einen kompletten Durchlauf des Arrays herum: foreach ( $ i d s as $ k e y => $ i d ) $ i d s [ $ k e y ] = ” ’ $ i d ’ ”. Dieses Array. Die Ausgabe soll im Prinzip die Tabelle. +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 2 | 1 | 1 | junetz. in HTML umsetzen (inkl.1 Ergebnis-Tabelle ausgeben I ¨ Als Vertiefung und Ubung zu dem bisher gesagten eine kleine Aufgabe: Es soll eine Funktion geschrieben werden. a a mysql_query ( ”DELETE FROM t a b e l l e WHERE ID IN ( ”. k¨nnte z. B. PHP & MySQL ¨ Ubung 10.10. kommt folgende Ausgabe zustande: mysql> select * from Mitarbeiter. ’ .de | 1998-03-05 | 069/764758 | | 3 | 1 | 1 | Uli | NULL | NULL | | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | +-----+------+-------+----------------+------------+--------------+ 6 rows in set (0.2. ¨ 10. Mithilfe der PHP-Funktion implode spart man sich das h¨ndische Zusammenbauen des entsprechenden a Strings. Denkbar w¨re etwa folgende Abfrage zum L¨schen aller Datens¨tze. Wenn man zum Beispiel am MySQL-Prompt alle Mitarbeiter abfragen will. die im IN-Teil einer Abfrage auftauchen sollen. $ d e l I D s ). k¨nnten alle oder bestimmte Datens¨tze in a o a Tabellenform nebst je einer Checkbox angezeigt werden. die das Ergebnis einer SQL-Abfrage tabellarisch darstellt.1 Abfragen mit IN Gegeben sei ein Array von IDs. Spaltennamen). implode ( ’ .3 Ubung 10.

ist folgender (vereinfachter) HTML-Code notwendig: < html > < body > < table > < tr > < th > MNr </ th > < th > VNr </ th > < th > AbtNr </ th > < th > Name </ th > < th > GebDat </ th > < th > Telefon </ th > </ tr > < tr > < td > 1 </ td > < td > </ td > < td > 3 </ td > < td > Christoph Reeg </ td > < td > 1979-05-13 </ td > < td > </ td > </ tr > < tr > < td > 2 </ td > < td > 1 </ td > < td > 1 </ td > < td > junetz . de </ td > < td > 1998-03-05 </ td > < td > 069/764758 </ td > </ tr > < tr > < td > 3 </ td > < td > 1 </ td > < td > 1 </ td > < td > Uli </ td > < td > </ td > < td > </ td > </ tr > < tr > < td > 4 </ td > < td > 3 </ td > < td > 1 </ td > < td > JCP </ td > < td > </ td > < td > 069/764758 </ td > </ tr > Christoph Reeg Seite 137 .10. PHP & MySQL ¨ Ubung Um das in einer HTML-Tabelle darzustellen.

10. PHP & MySQL

¨ Ubung

< tr > < td > 5 </ td > < td > 1 </ td > < td > 2 </ td > < td > Maier </ td > < td > </ td > < td > 06196/671797 </ td > </ tr > < tr > < td > 6 </ td > < td > 5 </ td > < td > 2 </ td > < td > Meier </ td > < td > </ td > < td > 069/97640232 </ td > </ tr > </ t a b l e > </ body > </ html > Als kleine Hilfe hier das Rahmenprogramm f¨r die Funktion: u <? php $db host $db user $db pass $datab = = = = ” l o c a l h o s t ”; ” c r ”; ”123 ”; ” c r ”;

function print_result_table ( $ r e s u l t ){ // h i e r d a s r i c h t i g e s c h r e i b e n } // Hauptprogramm /∗ V e r b i n d u n g z u r D a t e n b a n k a u f b a u e n ∗/ $db = @mysql_connect ( $ d b h o s t , $ d b u s e r , $ d b p a s s ) or die ( mysql_error ()); @mysql_select_db ( $ d a t a b , $db ) or die ( mysql_error ()); /∗ HTML−S t a r t c o d e a u s g e b e n ∗/ echo ”<html>\n<body>\n ”; /∗ SQL−A b f r a g e ∗/ $ r e s u l t = @mysql_query ( ”SELECT ∗ FROM M i t a r b e i t e r ”); print_result_table ( $ r e s u l t );

Christoph Reeg

Seite 138

10. PHP & MySQL

¨ Ubung

/∗ HTML−Endcode a u s g e b e n ∗/ echo ”</body>\n</html>\n ”; ?>

Tips zur L¨sung o Die Aufgabe in mehreren Schritten l¨sen: o 1. Nur in der 1. Zeile die 1. Spalte ausgeben. 2. Mit einer Schleife f¨r alle Zeilen die 1. Spalte ausgeben. u 3. Mit einer 2. Schleife alle Spalten ausgeben (vorher in der Dokumentation nachsehen, mit welcher Funktion man die Spaltenanzahl abfragen kann). 4. Als letztes noch die Spaltennamen ausgeben. Eine L¨sung befindet sich in Anhang B.2. o

10.3.2 Ergebnis-Tabelle ausgeben II
Das Hauptprogramm aus der vorigen Aufgabe soll etwas erweitert werden. Bei meiner Vorgabe ist bis jetzt noch keine Fehlerpr¨fung enthalten. Was f¨r Fehler k¨nnen auftreten? u u o • Die SQL-Anweisung enth¨lt Fehler. a • Die Abfrage enth¨lt keine Datens¨tze. a a Bei dem ersten Fehler soll die Fehlermeldung von MySQL ausgegeben werden, beim zweiten “Keine Datens¨tze gefunden“. Das Hauptprogramm soll entsprechend erweitert werden. a Eine L¨sung befindet sich in Anhang B.3. o

10.3.3 Abfrage mit sprintf()
Auch in diesem Beispiel wird obige Tabelle benutzt. Die Zeile /* SQL-Abfrage */“ und ” die folgende werden jedoch nun wie folgt ver¨ndert1 . a ... $was = ”Name ”; $monat = 5; $ j a h r = 1979; /∗ SQL−A b f r a g e ∗/ $ r e s u l t = @mysql_query ( sprintf ( ”SELECT %0\ $ s FROM M i t a r b e i t e r
1

Fehlerbehandlung wurde hier absichtlich außen vor gelassen, um die vorhergehenden Aufgaben nicht zu beeintr¨chtigen a

Christoph Reeg

Seite 139

10. PHP & MySQL

¨ Ubung

WHERE GebDat LIKE ’%2\ $02d −%3\02d−%’ ”, $was , $monat , $ j a h r ) ); ... In diesem Programmabschnitt sind sechs Fehler versteckt. Wer findet sie? Aufl¨sung in o Anhang B.4.

10.3.4 Einf¨gen mit automatischer ID u
Nun etwas neues: Es soll in zwei Tabellen eingef¨gt werden, wobei die ID der ersten u Einf¨geoperation f¨r die zweite ben¨tigt wird. Konkret soll der Mitarbeiter Jens“ einu u o ” gef¨gt werden, der direkt Christoph Reeg unterstellt ist, in der Verwaltung arbeitet und u am 26.5.1981 Geburtstag hat. Diesem Mitarbeiter unterstellen wir wiederum einen Helfer namens Kile, der in der EDV arbeitet. Zu beachten ist, daß beim Einf¨gen keine u Mitarbeiter-Nummer vergeben werden sollen; das soll MySQL selbst machen (die MNr ist ein AUTO INCREMENT-Feld). Alle hier nicht angegebenen Werte sollen NULL sein. Eine m¨gliche L¨sung findet sich in Anhang B.5. Die Verbindungsdaten f¨r MySQL o o u seien dieselben wie bei 10.3.1. Die vorgegebenen Tabellen finden sich unter A.2.

Christoph Reeg

Seite 140

11 PHP & HTTP
11.1 Header
Neben der eigentlichen Seite schickt der Server an den Client (Browser) noch einige Zusatzinformationen. Diese werden vor der eigentlichen Seite im sog. Header gesendet. Mit diesen Informationen sagt der Server z. B., ob die angezeigte Seite wirklich die gew¨nschte u Seite ist (Status ‘200 Found‘), oder ob die Seite nicht gefunden werden konnte und deshalb eine Fehlerseite angezeigt wird (Status ‘404 Not Found‘). Auch kann der Server dem Client mitteilen, daß die Seite sich unter einer anderen Adresse befindet (Status ‘301 Moved Permanently‘ oder ‘302 Found‘). Es kann auch die Aufforderung geschickt werden, sich zu authentifizieren (Status ‘401 Unauthorized‘). Zus¨tzlich zum Status einer Seite kann auch ubermittelt werden, wann die Seite zum a ¨ letzten Mal ver¨ndert wurde (Last-Modified), ob sie gecached werden darf (Cache-Control) a und wenn ja wie lange (Expires) oder welchen Typ ihr Inhalt hat (Content-Type). Normalerweise sendet der Webserver (in der Regel Apache) automatisch den richtigen Header. Mit PHP kann man den gesendeten Header allerdings beeinflussen. Zu beachten ist, daß kein einziges Zeichen vor der header-Anweisung ausgegeben werden darf ! Ausgeben heißt in diesem Fall: Die Seite muß unbedingt mit PHP-Code (<?php) anfangen und darf vor dieser Codemarke nichts (nicht einmal ein Leerzeichen oder einen Zeilenumbruch) enthalten. Auch innerhalb der Codemarken d¨rfen Ausgaben mittels echo, u print etc. erst nach dem Senden der Headerangaben gemacht werden. Wenn PHP als CGI installiert ist, gibt es außerdem einige Einschr¨nkungen, z. B. kann a keine Authentifizierung gemacht werden (mehr dazu siehe weiter unten). Wie der Header aussehen muß, ist in dem RFC1 2616 festgelegt. Er spezifiziert das HTTP/1.1 Protokoll. Im Folgenden zeige ich ein paar M¨glichkeiten der Anwendung der o header-Anweisung.

11.1.1 Weiterleiten
Wie bereits oben erw¨hnt, kann man, neben JavaScript und HTML2 , auch mit PHP den a Client auf eine andere Seite weiterleiten. Dies geschieht mit folgender Anweisung: header(’Location: absolute_URL’); exit; absolute_URL muß nat¨rlich durch die gew¨nschte URL ersetzt werden. Es muß nach RFC u u die absolute URL angegeben werden, auch wenn fast alle Browser eine relative verstehen! Das exit ist nicht unbedingt notwendig, allerdings w¨rde es nichts bringen, nach dem u header noch etwas auszugeben, da es sowieso nicht angezeigt wird.
1 2

Request for Comments hier allerdings nicht konditional, also bedingungsabh¨ngig, sondern nur nach einer festen Anzahl a Sekunden

Christoph Reeg

Seite 141

11. PHP & HTTP

Header

Bei dieser Anweisung sendet Apache automatisch den Statuscode 302.

11.1.2 Nicht gefunden
Wenn du Apache so konfiguriert hast, daß er als Fehlerseite eine PHP-Seite anzeigt, wird als Statuscode 200 (OK) gesendet. Da dies aber unpraktisch ist, weil so z. B. Suchmaschinen deine Fehlerseite in ihren Index aufnehmen, solltest du den Statuscode 404 (Not Found) senden, wodurch diese Seite als Fehlerseite erkannt wird. Die Anweisung dazu lautet wie folgt: header(’HTTP/1.0 404 Not Found’);

11.1.3 Authentifizierung
Mit PHP besteht die M¨glichkeit, den Browser ein Fenster ¨ffnen zu lassen, in dem Name o o und Paßwort eingetragen werden m¨ssen. Wenn PHP nicht als Modul, sondern als CGI u l¨uft, funktioniert das allerdings nicht3 . a Es ist eigentlich ganz einfach, eine solche Datei muß vom Prinzip her so aussehen: <? php if ($PHP AUTH USER!= ” C h r i s t o p h ” OR $PHP AUTH PW!= ”Reeg ”) { Header ( ’ HTTP / 1 . 1 4 0 1 U n a u t h o r i z e d ’ ); Header ( ’W W u t h e n t i c a t e : B a s i c r e a l m =”Top S e c r e t ” ’ ); W −A echo ”Mit Abbrechen kommst Du h i e r n i c h t r e i n . ; − ) \ n ”; exit ; } ?> <! DOCTYPE HTML PUBLIC ”−//W3C//DTD HTML 3 . 2 / / EN”> < html > < head > < title > Authentification </ title > </ head > < body > < h1 > Hier ist der Top - Secret Bereich </ h1 > < h2 ><? php echo ”Username : ”.$PHP AUTH USER. ” Paßwort : ”.$PHP AUTH PW; ?></ h2 > </ body > </ html > Das Funktionsprinzip ist ganz einfach: Beim ersten Aufruf sind im Array SERVER“ die ” beiden Stellen ‘ PHP AUTH USER‘ und ‘PHP AUTH PW‘ nicht gesetzt. Dadurch wird ” der Bereich in der IF-Abfrage bearbeitet. Hier werden die beiden Header zur¨ckgegeben, u die den Browser veranlassen, nach Usernamen und Paßwort zu fragen. Diese beiden Zei3

¨ Ubrigens: PHP gibt es auch als Modul f¨r Windows, siehe auch PHP-FAQ[8] “Wo finde ich PHP als u Modul f¨r Windows?“ u

Christoph Reeg

Seite 142

wird der Bereich in der IF-Abfrage nicht bearbeitet und der Rest der Datei wird abgearbei¨ tet. . − ) \ n ”. 2 / / EN”> < html > < head > < title > Authentification </ title > </ head > < body > < h1 > Hier ist der Top . was u ¨ ge¨ndert werden darf. Der folgende Quelltext zeigt. dann springt der Webserver nach dem ‘echo‘ aus der Datei und der Rest wird nicht mehr ausgegeben. Wenn jedoch jemand das richtige Paßwort mit dem richtigen Usernamen eingegeben hat. a wenn jemand bei der Paßwortabfrage auf . sondern sie w¨rde auch die Paßwortabfrage zuveru o u 4 Beachtet man z. W −A echo ”Mit Abbrechen kommst Du h i e r n i c h t r e i n . mißlungen sind). Header ( ’W W u t h e n t i c a t e : B a s i c r e a l m =”Top S e c r e t ” ’ ). Die u Fehlermeldung w¨rde nicht nur st¨ren. drei Versuche. $ SERVER[ ”PHP AUTH PW”])) { Header ( ’ HTTP / 1 . indem man den Browser komplett beendet. Es sorgt daf¨r. die a man nach der Paßworteingabe abruft. $ SERVER[ ”PHP AUTH USER”]. ?></ h2 > </ body > </ html > Das ‘@‘-Zeichen vor dem mysql_connect hat nichts mit der if-Abfrage zu tun. exit . Auf fast dieselbe Weise kann man sich nat¨rlich auch direkt f¨r den Zugriff auf eine u u Datenbank authentifizieren.Secret Bereich </ h1 > < h2 ><? php echo ”Username : ”. so daß die Autoren derjenigen Seiten. ” Es gibt noch ein kleines Sicherheitsproblem bei der ganzen Sache . 0 4 0 1 U n a u t h o r i z e d ’ ).Abbrechen‘ klickt (oder. wohl aber weiterhin mit dem Netscape Navigator funktioniert! Christoph Reeg Seite 143 . PHP & HTTP Header len m¨ssen fast genau so ubernommen werden. Der Text danach wird nur dann ausgegeben. } ?> <! DOCTYPE HTML PUBLIC ”−//W3C//DTD HTML 3 . In unserem Fall wird die Uberschrift Hier ist der Top-Secret Bereich“ und die Zeile ” Username: Christoph Paßwort: Reeg“ im HTML-Format ausgegeben. wie man dies erreicht: <? php if ($ SERVER[ ”PHP AUTH USER”] == ” ” OR ! @mysql_connect ( ” l o c a l h o s t ”. Dies o kann man jedoch ganz einfach verhindern.der Browser beh¨lt a sich n¨mlich den Usernamen und das Paßwort.$ SERVER[ ”PHP AUTH PW”]. daß keine Fehlermeldung beim Aufruf von mysql_connect ausgegeben wird. die Groß-/Kleinschreibung nicht. kann das dazu f¨hren. ist das ‘Top Secret‘. daß die Authentifizierung u nicht mehr mit dem Internet Explorer. sich zu authentifizieren.11.$ SERVER[ ”PHP AUTH USER”]. damit es funktioniert!4 Das einzige. im Falle des Internet Explorers. theoretisch das Paßwort abfragen k¨nnten. echo ” Paßwort : ”. B.

aber nicht in welches Verzeichnis die Datei gespeichert werden sollte. Altere a u Versionen dagegen scheinen den Fehler nicht aufzuweisen. ¨ Uber die Variable _SERVER["HTTP_USER_AGENT"] k¨nnen wir PHP auch entscheiden o lassen. Im Falle des o.ext“ gesetzt.x verh¨lt. welche Variante wahrscheinlich die richtige ist. Christoph Reeg Seite 144 . h. Das geschieht mit folgender u a Anweisung (siehe auch weiter unten): header("Content-Type: application/octetstream"). Dieser sollte dann die Daten z. muß die Angabe uber den a ¨ ¨ ¨ Typ des Dateiinhalts f¨r die Ubertragung ge¨ndert werden. Eveno tuelle Pfadangaben sollen explizit ignoriert werden. Um sich Probleme zu ersparen. denn diese ist bestens erprobt! :-) ¨ Noch eine Anmerkung zum Schluß: Anstatt der Zeichenkette “HTTP/1.ext"). daß bestimmte u Browser wie der IE sonst die Quoting-Zeichen als Teil des Dateinamens ansehen.0 401 Unauthorized“ kann auch “Status: 401 Unauthorized“ benutzt werden.56 nur folgenden Header versteht: header("Content-Disposition: filename=datei_name. . a Normalerweise wird die Ausgabe eines PHP-Scripts als HTML interpretiert. in Form einer Datei abspeichern oder auf sonstige o Weise verarbeiten (an spezielle Applikationen ubergeben). denn trotz allem werden die beiden ben¨tigten Authentifizierungs-Variablen nicht mit den Werten gef¨llt. welches der Browser anzeigen soll. In jedem anderen Fall wird. bei Anh¨ngen (Attachments) in einem Webmail-System. wie im ersten Beispiel. a Der Bereich in der obigen IF-Abfrage wird genau dann nicht bearbeitet. B. . header("Content-Disposition: attachment. benutzt der Browser den Dateinamen des Scripts aus der URL als Dateinamen zum Abspeichern. PHPCGI-Problems scheint es dann so. ¨ Solche Situationen gibt es z. u 11. wenn ein PHP-Script die von ihm erzeugten Daten a a o nicht einfach in Form einer HTML-Seite ausgeben. Microsoft liest die RFCs scheinbar anders als alle anderen (oder gar nicht?). filename=datei_name.4 Download In bestimmten F¨llen w¨re es sch¨n. wenn mittels Benutzername und Paßwort eine Verbindung zur Datenbank aufgebaut werden konnte. Nat¨rlich u kann anstelle des hier beispielhaft eingetragenen jeder m¨gliche Dateiname stehen. dies ist jedoch ein Trugschluß. g. B. so daß der IE 5. Man beachte das ” Fehlen von Quoting-Zeichen wie etwa Hochkommata5 . abgebrochen und (in diesem Fall) der Text Mit Abbrechen. Vor dem header-Aufruf darf nichts ausgegeben werden. wenn die endg¨ltige Version erschienen ist. Damit der Browser die Datei aber direkt auf die Platte speichert (bzw. wissen wir erst. 5 6 Nach RFC muß der Dateiname gequotet werden ¨ Wie es sich mit IE 6. D. es ist m¨glich den Dateinamen o festzulegen. als ob die Authentifizierung funktionieren w¨rde (es u tritt kein Fehler 500 mehr auf).ext"). die der o u Browser nach der Eingabe durch den Benutzer im entsprechenden Dialog zur¨ckliefert. sondern diese an den Client senden k¨nnte.11.“ ausgegeben. sollte man obige ” Bedingung der IF-Anweisung einfach 1:1 ubernehmen. dem Benutzer uberl¨ßt. PHP & HTTP Header l¨ssig verhindern. was er damit machen will). Mit diesem Header wird der Dateiname auf datei name.1. Grund hierf¨r ist. Wenn nichts anderes angegeben wird.

¨ ” header("Content-Length: {Dateigr¨ße}"). Dies ist wiederum nur uber Funktionen des u ¨ Webservers m¨glich. Diese Headerkombination sollte zuverl¨ssig funktionieren. Bei der Vielzahl von Browsern. ( strpos ($ SERVER[ ”HTTP USER AGENT”]. den Dateinamen uber Header festzulegen. konnte noch kein Header gesendet ¨ ” werden. wie groß die Datei ist. h a t s i c h a b e r w o h l b e w a e h r t header ( ” C o n t e n t−T r a n s f e r−E n c o d i n g : b i n a r y ”). hat einen kleinen Nachteil: Wenn ¨ der Nutzer sp¨ter im Browser nicht auf den Link klickt. a sondern direkt uber Save Link as“ speichern will. 5 ”)? ” a t t a c h m e n t . // D a t e i g r ¨ ß e f u r D o w n l o a d z e i t−B e r e c h n u n g o ¨ header ( ” C o n t e n t−L e n g t h : { D a t e i g r o e s s e } ”). die besser funktioniert. ”: ” ”). wenn vor dem Senden o. gesandt wurden. header("Content-Transfer-Encoding: binary"). g. ”). indem man daf¨r sorgt. so daß der Browser den Dateinamen nicht kennt und wieder den Dateinamen des Scripts vorschl¨gt. (! strpos ($HTTP USER AGENT. a die sich nicht immer an die RFCs halten. freue ich mich nat¨rlich uber eine R¨ckmeldung.11. // Z w i s c h e n s p e i c h e r n a u f P r o x i e s v e r h i n d e r n // ( s i e h e w e i t e r u n t e n ) header ( ”Cache−C o n t r o l : p o s t−c h e c k = 0 . wenn die Ausgabe eines o Scripts heruntergeladen werden soll: // D a t e i t y p . um dann die Datei zu speichern. Die Gr¨ße o der Datei in Bytes wird uber den Content-Length“ Header angegeben. // Dateiname // m i t S o n d e r b e h a n d l u n g d e s IE 5 .1. ” f i l e n a m e=d a t e i n a m e . Dies a ” funktioniert allerdings nur dann. o Zusammenfassend k¨nnen wir nun folgenden Header benutzen. Beim Apache sind das die Funktionen Rewrite und Redirect. PHP & HTTP Header header ( ” C o n t e n t−D i s p o s i t i o n : ”. wenn der Browser weiß. Header schon bestimmte andere Header. daß das ganze angepaßt werden muß. e x t ”). o Die Erfahrung hat gezeigt. auch wenn er laut RFC 2616 nicht benutzt wird.6). 5 ”)? ” ” : ” a t t a c h m e n t . Das kann nur umgangen werden. Man sollte also immer u Christoph Reeg Seite 145 . ”MSIE 5 . ist jedoch nicht ausgeschlossen. Die großen“ Browser zeigen beim Download h¨ufig einen Fortschrittsbalken an. Die Variante. wie die f¨r das Nicht-Cachen (11. // e i g e n t l i c h u e b e r f l u e s s i g . e x t ”). ” f i l e n a m e=d a t e i name . Sollte jemand eine Kombination haben. daß der a u gew¨nschte Dateiname in der URL steht. 5 header ( ” C o n t e n t−D i s p o s i t i o n : ”. d e r immer a b g e s p e i c h e r t w i r d header ( ” C o n t e n t−Type : a p p l i c a t i o n / o c t e t s t r e a m ”). daß ein Content-Transfer-Encoding“ Header die ganze Sache ” sicherer macht. u u ¨ Ein letztes Wort noch zur Header-Kombination: Wie sich zeigte. ”MSIE 5 . p r e−c h e c k =0 ”). funktioniert diese Download-Methode nicht mehr.

muß der Typ explizit angegeben werden.11. anhand der Endung selbst besser entscheiden zu k¨nnen. um was f¨r eine Datei es sich handelt. Wenn aber ” ” z. Normalerweise beachtet der Client den Typ. PHP & HTTP Header auf die Reihenfolge der Header achten und sicherstellen. mit den PHP image functions ein Bild dynamisch erzeugt wird. was auch als Bild im Browser angezeigt wird. Die Tabelle 11. welchen Typ er sendet. So lange u nur“ normale“ Webseiten ausgegeben werden. o <? php ?> < html > < body > < h1 > Hallo Welt !</ h1 > </ body > </ html > Die Datei ist im Endeffekt eine ganz normale Webseite.1 zeigt die wichtigsten Typen. o 11. daß vor den Headern f¨r den u Download keine oder nur definitiv nicht st¨rende Header verschickt werden.1. ?> < html > < body > < h1 > Hallo Welt !</ h1 > </ body > </ html > Christoph Reeg Seite 146 .1: Content-Type Typen Die Bedeutung des Type k¨nnen wir uns an den folgenden Dateien ansehen. enth¨lt zwar einen Bereich f¨r PHP a u Anweisungen. B.5 Content-Type Neben dem oben schon verwendeten Content-Type gibt es nat¨rlich noch andere. HTML wird interpretiert wird als reiner Text angesehen. Sie wird auch dem entsprechend im Browser angezeigt. o u Bezeichnung application/octetstream image/gif image/jpeg image/png text/html text/plain Bedeutung wird als Datei (Bin¨rdaten) angesehen (wird gespeichert) a GIF-Bild JPEG-Bild PNG-Bild wird als Webseite angesehen. HTML wird nicht beachtet Tabelle 11. der ist jedoch leer. interessiert uns der Typ nicht. <? php header ( ” C o n t e n t−Type : t e x t / p l a i n ”). Es gibt jedoch IE Versionen. die der Meinung sind. Bei statischen Dateien entscheidet der Webserver in der Regel anhand der Endung. den der Server sendet.

header ( ” L a s t−M o d i f i e d : ” . ?> < html > < body > < h1 > Hallo Welt !</ h1 > </ body > </ html > Mit dem richtigen Typ ist die Welt aber wieder in Ordnung. ” GMT”). d. p r e−c h e c k =0 ”). <? php header ( ” C o n t e n t−Type : t e x t / html ”). a header ( ” E x p i r e s : − 1 ”). werden die HTMLa Anweisung komplett mißachtet und der Text so wie er ist ausgegeben. a 11.11. ?> < html > < body > < h1 > Hallo Welt !</ h1 > </ body > </ html > Als Bild taugt der HTML-Code nun wirklich nicht und Netscape zeigt das Symbol f¨r ein u defektes Bild an. So verhindert folgende Kombination zuverl¨ssig das Zwischenspeichern. ?> < html > < body > < h1 > Hallo Welt !</ h1 > </ body > </ html > Und den Octetstream will Netscape ordnungsgem¨ß als Datei abspeichern. header ( ”Cache−C o n t r o l : p o s t−c h e c k = 0 . d M Y H : i : s ”) . Zus¨tzlich braucht der IE ab Version 5 offenbar noch folgenden HTML-Code am Ende a der Datei. PHP & HTTP Header Nachdem das Script nun von sich behauptet.6 Cache ¨ Uber die richtigen Headerangaben kann auch das Verhalten der Proxies beeinflußt werden. h. zwischen </body> und </html> Christoph Reeg Seite 147 . <? php header ( ” C o n t e n t−Type : image / png ”). <? php header ( ” C o n t e n t−Type : a p p l i c a t i o n / o c t e t s t r e a m ”).1. gmdate ( ”D . header ( ”Pragma : no−c a c h e ”). es w¨re ein normaler Text.

d.2 zeigt die entsprechenden Header. Section 14. Section 14. sie muß bei jedem Aufruf neu ubertragen werden. die Seite sich bei jedem Aufruf ¨ndert. einen gescheiten Last-Modified und Expires Header senden. Die Tabelle 11. h. daß sie sich st¨ndig ¨ndert? Von daher sollte die Seite. Wenn dies nicht der Fall ist. Davon abgesehen ignorieren viele Suchmaschinen Seiten.11. Was tun bei einer Seite. die im HTML stehen und den HTTP-Headern. kann er die gespeicherte Seite senden. ¨ Christoph Reeg Seite 148 . die o nicht gecached werden d¨rfen. Bezeichnung Cache-Control Expires Last-Modified Bedeutung Anweisungen f¨r Proxies und Browser u Zeitpunkt.2: Cache Header Cache-Control Das RFC 2616 sagt zum Thema Syntax des Cache-Control (hier nur ein Ausschnitt): Cache-Control = "Cache-Control" ":" 1#cache-directive cache-directive = cache-request-directive | cache-response-directive cache-request-directive = "no-cache" | "no-store" .2 Bei einem Cache-Control: no-cache Header muß der Proxy bei jeder Anfrage uberpr¨u ¨ fen.9. PHP & HTTP Header < head > < meta http . Es ist sonst n¨mlich zum einen f¨r den Besucher a a u nervig. letztere auch von Proxies.normalerweise kommt sie ja nach dem ersten Aufruf f¨r eine gewisse Zeit aus dem Cache. denn warum soll eine Seite aufgenommen werden.9.1 | "no-store" .9. Section 14. wenn sie a a in Suchmaschinen auftauchen soll. ab dem der Inhalt wahrscheinlich veraltet sein wird ¨ letzte Anderung des Inhalts Tabelle 11. da die Seite bei jedem Aufruf neu geladen werden muß . Erstere werden nur vom Browser gelesen. ob eine aktuellere Version vorliegt. das heißt. wenn es wirklich notwendig ist. Es muß unterschieden werden zwischen den META-Tags. Zum anderen belastet das u Neuladen den Server unn¨tig. die sich jede Minute ¨ndert? Ganz einfach: Die entsprechenden a Header richtig setzen.equiv = ”pragma ” content = ”no−c a c h e ”> </ head > Das Nicht-Cachen sollte aber nur benutzt werden. Section 14.1 .9. wenn die u Seite von sich behauptet. Bei Cache-Control: no-store darf der Proxy die Seite nicht speichern.2 cache-response-directive = | "no-cache" [ "=" <"> 1#field-name <"> ].

net/index. Beispiel: a http://php. Wozu auch .und das ist es.html?IRGENDETWAS. URL h¨ngen und landet automatisch auf der richtigen Seite des PHP-Manuals. Bei statischen ¨ Seiten wird daf¨r h¨ufig das Anderungsdatum der Datei genommen. Diese kann man abfangen und statt der Standard-Fehlerseite eine eigene angeben . Browser) schickt.net/ gen¨gt. Im Folgenden werde ich also erst einmal zeigen. Wie man sich denken kann. Kleines Beispiel: Expires: Thu. eine Seite nicht findet. Danach muß sie wieder a auf Aktualit¨t uberpr¨ft werden.2. Dezember 1994 0 Uhr aktuell gewesen. a ¨ u Last-Modified ¨ Bei Last-Modified sollte die Zeit der letzten Anderung angegeben werden. ein kurzer Blick auf http:// php. Dann n¨mlich schickt er den Status-Code 404 a (siehe 11.2) in Verbindung mit einer Fehlerseite. kennt alle Befehle und deren Syntax auswendig.html die Adresse a http://reeg. 11. bis man den Befehl gefunden hat. h. PHP & HTTP URLs parsen Expires Beim Expire-Header muß die Uhrzeit richtig formatiert sein und in Greenwich Mean Time7 .2 URLs parsen 11. damit u man sich nicht immer durch zig Unterseiten hangeln muß. was wir hier ausnutzen m¨chten.es gibt schließlich das PHP-Manual.11.net/index. Bei dynamischen u a Seiten gestaltet sich die Sache etwas schwieriger. Die Betreiber dieser Site haben sich etwas besonders schlaues einfallen lassen. Doch nun los: Zuerst einmal muß man verstehen. daß er beim Status-Code 404 zu einer anderen als der Standard-Fehlerseite umleiten soll. erstellt man eine Datei namens . den man sucht: Man kann einfach den Namen des gesuchten Befehls hinter die o. wenn der Webserver. Alternative: GET-Parameter Eine Alternative zum Header ist. Zum Beispiel wird dann aus der URL http://reeg. daß IRu a GENDETWAS immer etwas anderes ist. was passiert. wurde diese Annehmlichkeit mit einem PHP-Script realisiert.net/echo zeigt die Beschreibung des Befehls echo an. der die HTML-Seiten (auch die durch PHP-Scripte dynamisch erzeugten!) an den Client (d. der PHP programmiert. die dann im Browser angezeigt wird. 01 Dec 1994 16:00:00 GMT Diese Seite w¨re bis zum 1.1 Beispiel: PHP-Manual Niemand. o Um einem Apache-Webserver mitzuteilen. wie dieser Trick funktioniert und im zweiten Schritt dann noch ein anderes Beispiel geben.1. g. einen zuf¨lligen GET-Parameter an die URL zu a h¨ngen. Es muß nat¨rlich gew¨hrleistet sein.htaccess mit folgendem Inhalt: 7 kurz GMT oder auch UTC (Universal Time) Jens Hatlak Seite 149 .

11.1. Letztere kann man nach Belieben im weiteren Scriptverlauf auswerten (und nat¨rlich auch ganz u anders nennen!). auf den gesuchten letzten Teil der URL wie folgt zugreifen: <? php if ($ SERVER[ ”REDIRECT STATUS”]==404) { $keyword = substr ($ SERVER[ ”REDIRECT URL”]. wof¨r dann eine Datenbank o u u benutzen?! Das geht viel eleganter: Erstelle eine Datei namens . PHP & HTTP URLs parsen ErrorDocument 404 /pfad/zur/alternativseite. du hast eine recht bekannte Homepage. da die meisten Dateinamen der Seiten des Manuals die Form function. was hinter dem letzten Slash / kommt. ”/ ”)+1). Akronyme o o schnell und einfach nachzuschlagen.2.FUNKTIONSNAME. was recht leicht zu bewerkstelligen ist.php4 Auf diese Weise wird an Stelle der normalen Fehlerseite die Alternativseite aufgerufen. indem man einfach o http://akronyme. das Akronym ROTFL nachzuschlagen.lediglich Underscores (_) werden durch das Minuszeichen ersetzt.2 Anderes Beispiel: Akronyme Angenommen. In dieser Seite kann man dann in dem Fall. daß mit Status-Code 404 umgeleitet wurde. Nun m¨chtest du vielleicht den Besuchern dieser Seite die M¨glichkeit geben. u 11.de/rotfl eintippt.junetz.html haben .php4 der absolute Pfad (relativ zur Server-HTTPWurzel) zu unserem Akronyme-Skript ist. mit MySQL) aufsetzt. die M¨glichkeit. Mit der neuen URL wird dann eine einfache Header-Weiterleitung (siehe 11. indem sie ein gesuchtes Akronym einfach ans Ende der ihnen schon bekannten URL h¨ngen.htaccess mit folgendem Inhalt: ErrorDocument 404 /akronyme/index. Doch wie soll das funktionieren? Soll ich etwa f¨r jede m¨gliche Eingabe eine eigene u o ” Seite bauen?“ h¨re ich euch schon rufen. Nat¨rlich nicht. Die weitere Behandlung der REDIRECT_URL wurde bereits im vorigen Beispiel beschrieben.de/ als Basis-URL era gibt sich so z. Jens Hatlak Seite 150 . B. und es in die Variable $keyword schreibt. daß es einfach alles abschneidet.junetz. Mit http://akronyme.php4 Wobei hier /akronyme/index. B. } ?> Mit etwas Erfahrung sieht man dem Script direkt an. wobei der Benutzer davon nichts mitbekommt. die auf einer serverseitigen Datenbank (z. Im Falle des PHP-Manuals wird aus dieser Information eine neue URL zusammengestellt. strrpos ($ SERVER[ ”REDIRECT URL”].1) durchgef¨hrt. Hier soll einmal eine Akronym-DB als Beispiel dienen.

Irgendwann geht es. str_replace() oder strpos(). Wenn hingegen die normalen String-Funktionen. dieses Kapitel erstmal zu uberspringen. wenn normale Suchmuster nicht mehr ausreichen. die ereg*a u und die preg*-Funktionen. ¨ 12. sollten diese auch benutzt werden. verst¨ndlich. und mit der Zeit perfektioniert man a sein K¨nnen. wie z. wenn es am Anfang nicht funktioniert oder o man Minuten braucht. weil sie schneller abgearbeitet werden. a Mit regul¨ren Ausdr¨cken ist es wie mit Programmen (und Dokus .: regular expressions verbreitete Scriptsprache unter Unix Perl Compatible Regular Expressions Christoph Reeg Seite 151 . was man mit a ¨ regul¨ren Ausdr¨cken realisieren kann. die finden regul¨re Ausa u a ¨ dr¨cke fast so genial wie die Erfindung des geschnittenen Brotes: Im Prinzip sind regul¨re u a Ausdr¨cke Suchmuster. halten sich an die POSIXDefinition. B. ist dann aber nat¨rlich etwas l¨nger. Mit regul¨ren Ausdr¨cken ist es einfach u a a u eleganter.-)): Es ist eine Kunst. sind aber langsamer und nicht so leistungsf¨hig wie die letzteren. Von daher sollten. In Unix-Programmen. die preg*-Funktionen verwendet werden. diese werden auch h¨ufig als PCRE3 -Funktionen bezeichnet. H¨ufig werden der Schr¨gstrich (Slash) / oder das Gleichheitszeia a chen = verwendet. Was sie o aber so sinnvoll macht ist ihre F¨higkeit. Auch wenn einfache Suchmuster noch relativ einfach zu erstellen sind.12 Regul¨re Ausdrucke a ¨ Was sind denn uberhaupt regul¨re Ausdr¨cke1 ? Es gibt Leute. kann das beliebig kompliziert werden.mehr dazu im a u folgenden. bei denen die normalen Funktionen nicht mehr ausreichen. u a Wann sollen denn nun die regul¨ren Ausdr¨cke eingesetzt werden? Die Antwort ist a u ganz einfach: Wenn man nach Mustern suchen will. solange es nachher nicht 1 2 3 Engl. Auf den u ersten Blick sehen sie etwas kryptisch aus. kann auch mit normalen Befehlen programmiert a u werden. probieren und ¨ nochmals uben. Erstere sind von Anfang an dabei. a u gut. fehlerfrei und effizient zu schreiben.1 einfache Suchmuster Das Suchmuster muß bei den preg*-Funktionen von Begrenzungszeichen (sog. Alles. die sich an Perl a orientieren. die sich auf Strings (Zeichenketten) anwenden lassen. die sich nur mit diesem Thema besch¨ftigen.uben. In o Konsequenz werde auch ich hier die Perl-kompatiblen Funktionen verwenden. ausreichen. Von daher: Nicht verzweifeln. bis dieser 20 Zeichen lange Ausdruck steht . PHP kennt zwei verschiedene Funktionsgruppen von regul¨ren Ausdr¨cken. wenn m¨glich. Nicht umsonst gibt es dicke B¨cher. Im Prinzip kann jedes Zeichen benutzt werden. werden die regul¨ren Ausdr¨cke sehr gerne a u benutzt. vor allem in Perl2 . Delimiter) eingeschlossen werden. was sie durchaus auch sein k¨nnen. Anf¨ngern empfehle ich. komplexe Suchen durchzuf¨hren .

5 und 6 als erstes Zeichen wird die Auswahl negiert alle Zeichen bis auf die Zahlen 1-6 Dezimalziffer alle Zeichen bis auf die Dezimalziffern Whitespace (Leerzeichen.3. Bereiche die Zahlen 1. wird die Auswahl negiert. ein paar Beispiele zu erfinden. Das ist zwar schon besser. Ziffern. Man br¨uchte genau die Menge der Zahlen a 1.. B.... Wenn man a das Dach ^ als erstes Zeichen angibt. bzw. aber auch noch nicht perfekt.) alle Zeichen außer Whitespace alle “Wort“-Zeichen (Buchstaben. Der Ausdruck /^Hallo/ paßt auf alle Strings.Hallo‘ am Anfang steht.2. sucht das Muster /<title>/ nach dem HTML-Tag <title>. nicht jedoch in der Mitte.. kann mit Hilfe der eckigen Klammern [] eine Menge von Zeichen definiert werden.. bei denen das Wort . /<h\d>/ trifft nur noch die HTML-Tags <h0>.6. 2. Das. Hier braucht man einen Platzhalter.<h1>. immer mit einem Backslash \ escaped wird. Tabulator etc. 3.<h2>. bei denen auf das h ein beliebiges Zeichen folgt. was auf der Kommandozeile der Stern * und in SQL bei LIKE das Prozentzeichen % ist. Z. Unterstrich) alle “Nicht-Wort“-Zeichen Tabelle 12. das mit einem Dollar $ markiert wird. die mit dem Wort Welt!“ enden. Christoph Reeg Seite 152 .4.5. ist hier der Punkt .. Diese ¨ befinden sich bei den Ubungen am Ende des Kapitels.>/ w¨rde auf u alle HTML-Tags zutreffen. Das Muster /<h. Neben dem Anfang ist nat¨rlich auch das Ende interesu sant. ” ¨ Zur Vertiefung und Ubung habe ich versucht. Wenn man jetzt aber Header-Tags (<h1>. [^1-6] \d \D \s \S \w \W ein beliebiges Zeichen (bis auf Newline \n) die angegebenen Zeichen bzw. Dies ist selbstverst¨ndlich auch m¨glich: Der Ausdruck /<h[123456]>/ bewirkt a o das Gew¨nschte. B.<h2>.. Mit \d steht ein Platzhalter f¨r eine beliebige Zahl zur Verf¨u u gung. Wir wollten aber nur die Zahlen 1-6.<h9>. Das l¨ßt sich nat¨rlich auch kombinieren: a u ” Mit /^Hallo Welt!$/ findet man genau die Strings Hallo Welt!“ . indem man entweder alle aufz¨hlt oder den Bereich angibt.<h6>) finden will. Regul¨re Ausdr¨cke a u einfache Suchmuster im Suchmuster verwendet wird. u a o Wie wir gesehen haben. funktioniert das so nicht mehr.12. 4. [1-6] [^] z.. [] z. . B.2: Sonderzeichen bei den PCRE Das Dach ^ hat auch im Muster eine besondere Bedeutung: es markiert den Stringanfang. er l¨ßt sich aber noch versch¨nern zu /<h[1-6]>/.1: Zeichenmengen \n \r \\ \t Zeilenumbruch (LF) Wagenr¨cklauf (CR) u Ein \ Tabulator Tabelle 12. Das Suchmuster /Welt!$/ paßt demnach auf alle Strings.

muß der Quantifizierer immer hinter dem Zeichen bzw. der Zeichenmenge stehen. Z.3 Gruppierungen Die runden Klammern ( ) haben auch eine besondere Bedeutung: Der Hauptzweck ist. B. gibt es noch das Fragezeichen ?. den eingeklammerten Bereich zur sp¨teren Verwendung zu markieren. Allquantor genannt. ? + * {n} {min. aber h¨chstens max -mal o Tabelle 12. Wie man an dem Beispiel sieht.3: Quantifizierer Wenn man aber genau f¨nf Zahlen oder zwischen drei und sieben kleine Buchstaben u haben will. Deshalb gibt es noch die geschweiften Klammern {}. das f¨r keinmal oder einmal steht und Existenzquantor genannt u wird. 12. in die man die gew¨nschten Zahlen eintragen kann. die mit einem Doppelpunkt anfangen.max} kein-/einmal mind. Regul¨re Ausdr¨cke a u Quantifizierer 12. ohne Klammern so aussehen /:\d{2}:\d{2}:\d{2}/ . a u ” ” Das Suchmuster /^\d*$/ w¨rde z. min-mal keinmal bis h¨chsten max -mal o mind. reichen die bisherigen Quantifizierer dann doch noch nicht. wenn zweimal dasselbe Wort nur durch ein Leerzeichen getrennt vorkommt. ¨ Die markierten Teilbereiche eines Ausdruckes werden auch Backreferences genannt. das f¨r die drei bis u u u sieben kleinen Buchstaben so: /[a-z]{3. u Das Suchmuster f¨r genau f¨nf Zahlen sieht z. ¨ Auch hier gibt es zur Vertiefung Ubungen am Ende des Kapitels. Der Ausdruck /(\w)\s\1/ paßt immer dann. B. Sie werden von links nach rechts durchnumeriert. sowie das Pluszeichen + (mind. aber irgendwie o u ¨ fehlt noch etwas. einmal keinmal oder beliebig oft genau n-mal mind. der auf drei zweistellige Zahlen. der f¨r keinmal“ oder beliebig oft“ steht. alle Strings. Selbstverst¨ndlich ist auch das m¨glich: hier hilft a o der Quantifizierer (auch Quantor genannt). der von der ersten Klammer eingeschlossen wird. Die Klammern kommen a auch beim wiederholten Vorkommen eines Teilaudrucks hintereinander zum Einsatz. Christoph Reeg Seite 153 . Wie die letzte Ubung gezeigt hat. ¨ Zur allgemeinen Verwirrung gibt es auch hier am Ende des Kapitels Ubungen. Innerhalb eines Ausdruckes kann man sich mit \1 auf den Text. u paßt. beziehen. finden. so aus: /\d{5}/.} {.2 Quantifizierer Mit dem bisher Gesagten kann man zwar schon sch¨ne Ausdr¨cke schreiben. min. Mit Klammer wird das ganze ubersichtlicher: /(:\d{2}){3}/ .12. ist es doch relativ umst¨ndlich. mehrere a aufeinander folgende Zeichen anzugeben. einmal). die aus keiner oder beliebig vielen Ziffern u bestehen. B. Neben dem Stern *.7}/. w¨rde ein Ausdruck.max} {min. Man unterscheidet die folgenden Typen: Da w¨re als erstes der altbekannte Stern *. mit \2 auf den zweiten usw.

u o Die Optionen werden hinter dem letzten Delimiter angegeben. daß nicht auf Groß-/Kleinschreibung geachtet wird. HALLO“ oder jede andere Kombination von Groß-/Kleinbuchstaben. wie auch auf den String-Anfang. auf alle Zeichen. $ u verwendet wird. Normalerweise sind die Quantifizierer greedy (gierig).4 Optionen Die ganzen Ausdr¨cke k¨nnen sich je nach angegebener Option auch noch anders verhalten. wird der Ausdruck auf den Anfang des Strings angewandt. Bei Setzen dieser Option.1 /hallo/ 12.1. das heißt das Dach ^ paßt nur auf den Anfang des Strings und das Dollar $ auf das Ende des Strings.12.2 /[^0-9A-Z]$/ Christoph Reeg Seite 154 . sie versuchen immer den gr¨ßtm¨glichen Text zu treffen.1 einfache Suchmuster Passen die folgenden Suchmuster auf die beiden Texte oder nicht? Text1= Hallo Welt!“. Dieses Verhalten kann auch durch entsprechende Konstrukte im Ausdruck erreicht werden. So bewirkt z. außer den Zeilenumbruch \n. es wird immer der k¨rzestm¨gliche Text genommen. u o Tabelle 12. inklusive Zeilenumbruch. B. hallo“. u Wenn es keine Zeilenumbr¨che in dem Text gibt oder im Ausdruck kein ^ bzw. In negierten Mengen. [^a]. ” ” ¨ ” Eine Ubersicht zu den Optionen gibt die Tabelle 12. unabh¨ngig von der Option.5. Beim $ gilt das Ganze analog f¨r das Ende. Ohne diese Option paßt der Punkt . Die L¨sung befindet o ” sich in Anhang B.5. i m Es wird nicht auf Groß-/Kleinschreibung bei Buchstaben geachtet. den String als eine Zeile. Normalerweise betrachtet PHP bei den PCRE. 12. paßt das ^ auf jeden Zeilenanfang.5. hat diese Option logischerweise keine Funktion. B.5 Ubungen 12. ” Text2= PHP ist einfach genial und die Regex sind noch genialer“.1. Mit Hilfe dieser Option wird auf ungreedy o o umgeschaltet. Wenn diese Option gesetzt ist.4: Optionen f¨r regul¨re Ausdr¨cke u a u s e A U ¨ 12.1. Der Ausdruck /hallo/i paßt auf Hallo“. Regul¨re Ausdr¨cke a u Optionen 12. das heißt. a Mit dieser Option wird der zu ersetzende Text bei preg_replace() als PHP-Code aufgefaßt und entsprechend ausgewertet.6. ein i. wie auch Perl. ist der Zeilenumbruch immer enthalten. wie z. das heißt.4. Mit gesetzter Option paßt der Punkt auf alle Zeichen.

5. Eine Zeile kann z.2 Quantifizierer Hier gilt dieselbe Aufgabenstellung wie in der vorigen Aufgabe 12.5.5.12. der Rechnername.1. kann aber trotzdem interessant sein: Als erstes steht die IP-Adresse bzw.5.2.5 /\w{4} \w+$/ 12.4 /\w{4} \w+/ 12. B.2 /^\w* \w*!$/ 12.4 /\w\w\w\w\w/ 12.1.5.6 Diesmal darfst du selbst nachdenken: Schreibe einen Ausdruck.1. wie viel Daten bei diesem Aufruf ubertragen wurden.1. von dem die Anfrage kam.1 /^\w* \w*$/ 12.[01/Apr/2001:08:33:48 +0200] "GET /test.2. der uberpr¨ft. ob u ¨ eine Log-Zeile dem Standard-Log Format des Apache-Servers entspricht.2.1 sein). In den Anf¨hrungszeichen steht die angeforderte u Datei mit der Methode (kann auch POST sein) und dem Protokoll (kann auch HTTP/1.168.2.. Regul¨re Ausdr¨cke a u ¨ Ubungen 12.0" 200 3286 Die Bedeutung der Felder ist hier nicht wichtig.2.1 .5.5. Als vorletztes wird der Status angegeben (200 ist OK) und das letzte Feld sagt. In den eckigen Klammern steht das u genaue Datum mit Zeit und Zeitzone.3 /^[HP][Ha][lP]/ 12.php4 HTTP/1.5. so aussehen: 192. beide Felder m¨ssen aber nicht existieren.3 /^\w* [\w!]*$/ 12. Die n¨chsten beiden Felder sind der Username (vom identd bzw.5 /\w\w\w\w\w\w/ 12. a von auth).5. ¨ Christoph Reeg Seite 155 .5.2.

Christoph Reeg Seite 156 .12.1 Schreibe einen Ausdruck.5.5. der uberpr¨ft.3 Gruppierungen 12. Regul¨re Ausdr¨cke a u ¨ Ubungen 12. Die Preisangabe sieht vom Format her so aus: 99. ob bei einer Preisangabe der DM-Betrag gleich u ¨ dem Pfennig-Betrag ist.99DM.3.

13 Fehlersuche
Fehlschl¨ge sind die W¨rze, die dem a u Erfolg sein Aroma geben.

Auch wenn man sehr gut programmieren kann und sowohl PHP als auch SQL im ” Schlaf“ beherrscht, kommt es vor, daß es nicht so tut“ wie man will. In solchen F¨llen ist a ” es praktisch, wenn man weiß, wie man auf Fehlersuche gehen kann. Als erstes sollte man sich nat¨rlich uberlegen, in welcher Reihenfolge das Programm u ¨ was wie tun sollte und dann uberpr¨fen, bis zu welchem Punkt es funktioniert. Um das u ¨ festzustellen, gibt es verschiedene Methoden; am sinnvollsten ist es i. d. R., zu uberpr¨fen, u ¨ ob die Variablen die Werte haben, die sie haben sollten. Dazu kann man sie z. B. einfach mit echo ausgeben. Bei Arrays kann die Funktion var_dump($var) sehr praktisch sein. var_dump gibt n¨mlich das gesamte Array mit Index und Werten aus. Da es aber in HTML a vorkommen kann, daß Text lediglich im Quelltext der Seite sichtbar wird (innerhalb von Tabellenkonstrukten zum Beispiel), ist es sinnvoll, einfach noch einen festen String mit auszugeben; auf diese Weise weiß man nachher auch noch, welche Variable es genau war. Als Beispiel haben wir die Variablen ‘VAR1‘ und ‘VAR2‘: echo $VAR1. ’AAA’ ; echo $VAR2. ’ BBB ’ ; F¨r reine Testzwecke hat es sich auch als hilfreich erwiesen, um die Testausgabe der u Variablen herum einen HTML-PRE-Block zu setzen. Das bewirkt dann mit Sicherheit eine Darstellung der Ausgabe auch auf dem Bildschirm: echo ”<p r e>”; echo $VAR1. ” ”.$VAR2; echo ”</ p r e>”; Die dritte M¨glichkeit schließlich findet dann Anwendung, wenn man mehrere Variablen, o z. B. von POST/GET-Daten oder Servervariablen, im Zusammenhang sehen will und vielleicht die Namen einiger dieser Variablen gar nicht kennt. In diesem Fall kann man auf die PHP-interne Funktion phpinfo() zur¨ckgreifen, die eine komplette HTML-Seite voll mit u daten¨berf¨llten Tabellen ausgibt. Hier¨ber lassen sich dem System auch intime Details“ u u u ” uber die Serverkonfiguration, den User-Agent (Browser) uvm. entlocken. ¨ Bei IF-Abfragen z. B. kann es auch passieren, daß Anweisungen gar nicht erst ausgef¨hrt u werden. Um das zu uberpr¨fen, setzt man einfach ein ‘echo‘ in die Abfrage hinein. Zum u ¨ Beispiel: $ i =1; echo $ i . ’ CCC ’ ; if ( i ==1){

Christoph Reeg

Seite 157

13. Fehlersuche

echo ’DDD’ ; .... } Bei dieser Abfrage w¨rde man auf den ersten Blick davon ausgehen, daß ‘1CCCDDD‘ u ausgegeben wird, da $i, durch das erste ‘echo‘ bewiesen, den Wert 1 hat. Da man nun aber weiß, daß etwas mit der IF-Abfrage nicht stimmt, kann man auch einen zweiten Blick riskieren und sieht dann, daß beim i das $ fehlt. Ein anderes Problem tritt h¨ufig auch im Zusammenhang mit Strings auf - warum wird a wohl bei folgendem String nicht das gew¨nschte ausgegeben: u $text = ’ Alternativtext ’ ; echo ”<img s r c =\ ”bild . gif \ ” w i d t h =\ ”10\ ” h e i g h t =\ ”10\ ” ”; echo ” a l t =\ ”. $ t e x t .\ ”>”; Oder warum bekommen wir hier eine Fehlermeldung: $text = ’ Alternativtext ’ ; echo ”<img s r c =\ ”bild . gif \ ” w i d t h =\ ”10\ ” h e i g h t=”10 ” ”; echo ” a l t =\ ” ” . $ t e x t . ”\ ”>”; Ganz einfach: Das Escapen stimmt nicht. Im oberen Beispiel sind hinter ‘alt=‘ zwar die doppelten Anf¨hrungsstriche escaped, aber da direkt im Anschluß daran mit Hilfe des u Stringoperators Strings verbunden werden, m¨ßten an dieser Stelle noch einmal doppelte u Anf¨hrungsstriche stehen, genauso wie bei der zweiten Stringverbindung. Im unteren Beiu spiel wurden zwar die Strings korrekt beendet und wieder angefangen, daf¨r wurden die u Anf¨hrungszeichen um die ‘10‘ nicht escaped. Komplett richtig muß es so aussehen: u $text = ’ Alternativtext ’ ; echo ”<img s r c =\ ”bild . gif \ ” w i d t h =\ ”10\ ” h e i g h t =\ ”10\ ” ”; echo ” a l t =\ ” ” . $ t e x t . ”\ ”>”; Solcherlei Vergeßlichkeiten sind nicht selten Grund genug f¨r eine langwierige Fehlersuche. u Man kann dies aber von vorne herein vermeiden, indem man gleich gut nachdenkt und dabei alle doppelten Anf¨hrungszeichen, die wirklich ausgegeben werden sollen, escaped. u :-) H¨ufig funktioniert zwar der komplette PHP-Teil, die SQL-Anweisungen jedoch nicht. a In diesen F¨llen gebe ich selbst einfach den Abfrage-String mit ‘echo‘ aus.1 Dann sieht a man n¨mlich schon h¨ufig den Fehler – ein h¨ufiger ist ubrigens, daß ein Feld einen String a a a ¨ erwartet (z. B. die SQL-Typen TEXT und VARCHAR), in der Abfrage jedoch die f¨r Strings u charakteristischen Hochkommata vergessen wurden. Wenn man ihn jedoch nicht findet, benutzt man einfach den String und gibt ihn direkt am SQL-Prompt2 ein. Wenn es dann immer noch nicht funktioniert, k¨rzt man die Abfrage solange, bis sie funktioniert. Die u andere Richtung funktioniert nat¨rlich auch, d. h. man konstruiert sich die Abfrage St¨ck u u f¨r St¨ck zusammen und probiert, wie lange sie noch funktioniert und hat dann hoffentlich u u den Fehler.
1

2

Hat man die Tips f¨r guten Stil aus Kapitel 8.8.2 angewandt und sprintf() benutzt, kann man hier u einfach testweise das ,s‘ entfernen. :-) Oder z. B. in PHPMyAdmin, siehe Kapitel 7.3

Christoph Reeg

Seite 158

13. Fehlersuche

¨ Ubungen

Damit w¨ren wir auch schon beim n¨chsten Punkt der Fehlersuche angelangt: Wenn a a etwas nicht laufen will, ersetzt man die Variablen durch Konstanten und probiert. Auf diese Weise ist n¨mlich eine Fehlerquelle (falsche Werte bei den Variablen) ausgeschlossen. a Bei großen PHP-Dateien ist es teilweise sinnvoll, den nicht funktionierenden Teil in eine Datei zu kopieren, denn nicht selten werden Anweisungen durch andere beeinflußt, die eigentlich gar nichts miteinander zu tun haben (sollten). Wenn es immer noch nicht funktioniert, hilft es vielleicht, wenn ein Freund, der auch etwas programmieren kann (das muß nicht einmal PHP sein) das Ganze mal begutachtet - denn vier Augen sehen mehr als zwei. Jeder hat nat¨rlich seine eigene Art, eine Fehlersuche anzugehen. Ich selbst habe hier u nur kurz zeigen wollen, wie ich es mache (und damit bisher immer zum Ziel gekommen bin!). Wahrscheinlich habe ich wieder die H¨lfte vergessen, aber du kannst mich nat¨rlich a u auch auf bessere Methoden aufmerksam machen (gilt ubrigens f¨r die gesamte Anleitung)! u ¨

¨ 13.1 Ubungen
Man lernt die Fehlersuche nirgendwo so gut wie beim Selbermachen. Ich habe hier mal ¨ versucht, ein paar “typische“ Fehler zu sammeln. F¨r alle Ubungen gelten folgende Fragen: u • Was soll das Programm eigentlich tun? Was soll es ausgeben? • Was macht das Programm? • Gibt es eine Fehlermeldung, und wenn ja, welche? • Wo liegt der Fehler? • Kann man durch die Programmierweise diesen Fehler vermeiden? Die L¨sungen befinden sich im Anhang B.7. o

13.1.1 Ein komisches IF
Teil 1 <? php $ i = 0; if ( $ i = 1){ echo ” D i e V a r i a b l e $ i h a t den Wert 1 ”; } else { echo ” D i e V a r i a b l e h a t n i c h t den Wert 1 ”; }

Christoph Reeg

Seite 159

13. Fehlersuche

¨ Ubungen

Teil 2 $ i = 0; if ( $ i = 0){ echo ” D i e V a r i a b l e $ i h a t den Wert 0 ”; } else { echo ” D i e V a r i a b l e h a t n i c h t den Wert 0 ”; } ?>

13.1.2 Fehler in einer leeren Zeile?
¨ Die Zeilennummern sind hier nur der Ubersichtlichkeit halber eingef¨gt worden. Sie stehen u nat¨rlich nicht in der PHP-Datei. u 1 2 3 4 5 6 <? php for ( $ i =1; $ i <=5; $ i ++){ echo ” $ i<b r>\n ”; echo ”Das waren d i e Z a h l e n 1−5 ”; ?>

13.1.3 Wieso fehlt ein ‘;‘ wo eins ist?
¨ Wie im vorigen Beispiel sind die Zeilennummern wieder nur der Ubersichtlichkeit halber eingef¨gt worden. u 1 2 3 4 5 6 <? php for ( $ i =1; $ i <=5; $ i ++){ echo ” $ i<b r>\n ; } e c h o ”Das waren die Zahlen 1-5 ” ; ?>

Jens Hatlak

Seite 160

14 PHPDOC
Beim Programmieren, unabh¨ngig von der verwendeten Sprache, ist nicht nur die Funktioa nalit¨t und Effizienz (Qualit¨t) des Codes wichtig, sondern meist auch die Verst¨ndlichkeit a a a und Wiederverwendbarkeit. Das liegt darin begr¨ndet, daß teilweise mehrere Programmieu rer an einem Projekt arbeiten, zu dem der jeweilige Quelltext geh¨rt; auch wird oft der o Code stetig erweitert und verbessert oder es m¨ssen Fehler gefunden und behoben werden. u In jedem Fall ist es also notwendig, daß der Code ubersichtlich ist. Dar¨ber hinaus ist u ¨ es jedoch unerl¨ßlich, den Quelltext ausf¨hrlich zu kommentieren. I. A. ist es hier dem a u jeweiligen Programmierer uberlassen, wie er dies anstellt. Es hat sich allerdings gezeigt, ¨ daß eine standardisierte Vorgehensweise beim Kommentieren von Vorteil sein kann: Jeder Programmierer braucht die Syntax dieses Standards nur einmal erlernen und kann ihn dann sowohl selbst anwenden als auch schnell wiedererkennen, wenn es gilt, Quelltexte anderer zu verstehen. Mit der Programmiersprache Java wurde ein solcher Standard eingef¨hrt und JavaDoc u 1 liegt ein gleichnamiges Programm bei, das beliebige Klassen – Java ist getauft. Dem JDK eine durch und durch objektorientierte Sprache – durchparst und die enthaltenen standar¨ disierten Kommentare so aufbereitet, daß eine HTML-Ubersicht2 entsteht, die ebenfalls eine einheitliche Form aufweist: Die offizielle Java-Dokumentation wird ebenfalls mit JavaDoc erstellt. Einige PHP-Programmierer haben diese Idee aufgegriffen und f¨r die Scriptsprache u angepaßt. Dabei herausgekommen ist PHPDOC – eine standardisierte Methode, PHPFunktionen und Klassen3 zu kommentieren. Mit dem PHPDOC-Programm lassen sich ¨ daf¨r, ganz ¨hnlich wie mit JavaDoc, HTML-Ubersichten erzeugen. Doch auch ohne das u a PHPDOC-Programm einzusetzen, wird der Code bei sachgem¨ßer Anwendung von PHPa DOC sehr viel ubersichtlicher. Es finden sich im Internet verschiedene PHPDOC-Pakete, ¨ wobei folgende Varianten zu unterscheiden sind: • Der phpDocumentor von http:// www.phpdoc.org/ ist PHP-basiert und recht aktuell. Er scheint der einzige zu sein, der noch weitergepflegt wird. • Unter http:// www.phpdoc.de/ , http:// sourceforge.net/ projects/ phpdoc/ und http: // wwpakis.free.fr/ php3/ phpdoc/ index en.html gibt es noch eine weitere Varianten, diese werden aber offensichtlich schon lange nicht mehr weiterentwickelt. • Es gibt von Christian Calloway eine Java-basierte L¨sung, die den Vorteil hat, daß sie o auf das Original-JavaDoc zur¨ckgreift und somit dessen umfangreiche Ausgabem¨gu o lichkeiten bietet. Allerdings gibt es die Webseite nicht mehr und Google findet keine neue.
1 2 3

Java Development Kit ¨ Es ist auch m¨glich, die Ubersicht in anderen Formaten wie PS oder PDF auszugeben . . . o PHP erlaubt ja, in beschr¨nktem Umfang, ebenfalls OOP [20]! a

Jens Hatlak

Seite 161

u 14. auch einzelne Sterne * wie am Anfang jeder Folgezeile. o Auf die Unterschiede gehe ich weiter unten noch n¨her ein.x) keine Zugriffsrechte kennt. doch ein Stern an passender Stelle stehen .php im aktuellen u 4 Es sollte nat¨rlich.org/ ) u PHP. PHPDOC phpDocumentor • In den neueren Versionen unterst¨tzt auch Doxygen (http:// www. Hierzu werden Schl¨sselworte benutzt.doxygen.14. wie oben beschrieben.php -d html – das w¨rde die Datei script. etwas komplexere Beispiel zeigt einen typischen PHPDOC-Kommentar f¨r die ebenfalls exemplarische Funktion foo. ¨ ∗ ∗ @author Jens Hatlak ∗ @version 1. kann dazwischen alles andere stehen. Diese kann sich uber mehrere Zeilen hinziehen und sollte die Funktionalit¨t a ¨ des zu kommentierenden Folgecodes im Kern dokumentieren. u Christoph Reeg Seite 162 . Jede dieser L¨sungen ist leider etwas anders und funktioniert auch unterschiedlich gut. In JavaDoc gibt es ubrigens noch die Schl¨sselworte @deprecated. Ublicherweise beginnt der Kommentar dann auch in der zweiten Zeile mit der Beschreibung der Funktion/Klasse/Methode. . die grunds¨tzlich mit einem @ eingeleiu a tet werden und ansonsten aus der Tabelle 14.0 ∗ @param $bar Ein b e l i e b i g e r Wert ∗ @return Der n e g a t i v e E i n g a b e w e r t ∗/ function foo ( $ b a r ) { return . wobei ich nur den phpDocua mentor im folgenden betrachten werde. . Da PHP (zumindest in der o aktuellen Version 4. u /∗ ∗ ∗ foo : l i e f e r t − $bar zuruck . Grunds¨tzlich stehen alle PHPDOC-Kommentare in Ca Kommentarzeichen (/* C-Kommentar */). Doch nun zur Vorgehensweise. B. mit phpdoc -f script.1 zu ersehen sind. erfolgt a z. Der erste ¨ Satz wird auch in der Ubersicht genutzt und der Rest erscheint dann bei der eigentlichen Beschreibung. } Da erst */ den mit /** begonnen Kommentar wieder beendet. macht auch die Verwendung des @accessSchl¨sselwortes entsprechend wenig Sinn. an das einleitende Zeichen wird jedoch in leichter Abwandlung ein zus¨tzlicher Stern angeh¨ngt: /** PHPDOC-Kommentar */ a a Das folgende. sie dienen der besse¨ ren Abgrenzung des Kommentars vom Code. die allerdings in PHPDOC in Ermangelung entsprechender Konstrukte in PHP nicht ben¨tigt werden. der derzeit nur unter Linux/Unix lauff¨hig ist. Nach einer zus¨tzlichen Leerzeile4“ folgen dann die einzelnen Angaben zur Codebea ” schreibung. @exception und u ¨ @throws sowie @package und @subpackage.1 phpDocumentor Ein Aufruf des phpDocumentors.$ b a r .

ebenfalls dokumentierbares Element eine weiterf¨hrende URL u Parameter (Wert und Typ. auch Angabe von op” tional“) der Funktion bzw. Name und Datum zu verlinkendes.bzw. B. Ubergabe Typ des R¨ckgabewerts der Funktion bzw. ggf. PHPDOC phpDocumentor Schlusselwort ¨ @author @version @since @access @copyright @see @link @param @return Tabelle 14. Methode in der Reihenfolge ¨ der An. neu zu erstellenden) Unterverzeichnis html erzeugen. Christoph Reeg Seite 163 .14.1: PHPDOC-Schl¨sselworte u Bedeutung Autor des Codeabschnitts Version des Codeabschnitts eine Version oder ein Datum Zugriffsrechte: private oder public z. Methode u ¨ Verzeichnis parsen und die HTML-Ubersicht im (ggf.

Teil IV Beispiele

Christoph Reeg

Seite 164

15 Einfaches G¨stebuch a
Dieses Beispiel-G¨stebuch soll wirklich ganz einfach gehalten sein, es soll nur zeigen, wie ein a einfaches Script aufgebaut ist. Es werden keinen Funktionen oder gar Objektorientierung benutzt. Das w¨re hier Overkill. Entsprechende Beispiele kommen sp¨ter noch. a a Was muß so ein G¨stebuch eigentlich k¨nnen? Im Prinzip nur vorhandene Eintr¨ge a o a anzeigen und neue Eintr¨ge entgegen nehmen. Das Speichern der Eintr¨ge machen wir a a hier der Einfachheit halber einmal in einer Datenbank. Es stellt sich also zuerst die Frage, wie die Tabelle aussehen muß. Was f¨r Informationen u m¨ssen denn gespeichert werden? Bei einem einfachen G¨stebuch sollen mal der Name des u a Eintragenden und der eigentliche Text, sowie das Eintragedatum reichen. Daraus l¨ßt sich a eigentlich schon unser create table bestimmen. CREATE TABLE meldung ( id int not null primary key auto_increment , datum datetime , name varchar (200), eintrag text ); Ich habe hier noch eine eindeutige ID eingef¨gt, damit man einen Eintrag auch sp¨ter u a noch eindeutig identifizieren kann. Nun stellt sich die Frage: Was programmiert man zuerst? Erst die Eingabe oder die Ausgabe? Ohne Daten kann man die Ausgabe nicht testen, aber ohne Ausgabe auch nicht vollst¨ndig die Eingabe. Wenn man die Eingabe (Formular und Eintragen in die Datena bank) programmiert, muß man irgendwie uberpr¨fen, ob das Script die Daten auch richtig u ¨ in die Datenbank schreibt. Das kann man z. B. per geeignetem select am MySQL-Prompt erledigen. Um die Ausgabe zu testen, braucht man nat¨rlich irgendwelche Daten. Auch u diese k¨nnte man zum Testen von Hand per passendem insert in die Datenbank schreio ben. Dies ist in der Regel jedoch aufwendiger, so daß es sich empfiehlt, erst die Eingabe und dann die Ausgabe zu programmieren. Wer gut ist, kann nat¨rlich auch beides gleichzeitig programmieren und damit beide u Scripte auf einmal testen. Problematisch wird es allerdings im Fehlerfall. Bei unserem G¨stebuch zum Beispiel: Nehmen wir an, die Ein-/Ausgabe ist soweit programmiert, aber a bei der Ausgabe bleibt das Feld mit dem Kommentar leer. Wo liegt dann der Fehler? Einerseits kann er bei der Eingabe liegen (dann steht nichts in der Datenbank) oder bei der Ausgabe (dann wird der korrekt in der DB stehende Text nicht ausgegeben). Nun aber zu unserem Script. Als erstes nun die Eingabe. Im Prinzip sollte es durch die Kommentare selbst erkl¨rend sein. Eine nette Spielerei ist die Weiterleitung nach erfolgtem a Eintrag. Wie wir jedoch seit Kapitel 11.1.1 wissen, muß die angegebene Adresse absolut sein. Hier werden die von PHP zur Verf¨gung gestellten Umgebungsvariablen genutzt, um u automatisch die aktuelle Adresse zu ermitteln und dorthin weiterzuleiten. Die Alternative

Christoph Reeg

Seite 165

15. Einfaches G¨stebuch a

w¨re gewesen, die Adresse hart“ reinzuschreiben und dann h¨tte man Probleme, wenn a a ” sich die Adresse des Scripts ¨ndert. a <? php $DBHost $DBName $DBUser $DBPasswd = = = = ” l o c a l h o s t ”; ” r e e g ”; ” r e e g ”; ” s u p e r g e h e i m ”;

// V e r b i n d u g z u DB−S e r v e r h e r s t e l l e n mysql_connect ( $DBHost , $DBUser , $DBPasswd) OR die ( ”Konnte DB−S e r v e r n i c h t e r r e i c h e n ”); mysql_select_db ($DBName); if ( isset ($ GET[ ” s u b m i t ”])){ // Der S u b m i t − B u t t o n wurde g e d r u c k t ¨ // −> d i e Werte m¨ ssen u b e r p r u f t u ¨ ¨ // und b e i G u l t i g k e i t i n d i e DB e i n g e f u g t werden ¨ ¨ // w i r g e h e n von d e r G u l t i g k e i t d e r Daten a u s ¨ $DatenOK = 1; // e s g a b noch k e i n e F e h l e r m e l d u n g $ e r r o r = ” ”; if (! isset ($ GET[ ”name ”])){ // e s wurde k e i n Name e i n g e g e b e n $DatenOK = 0; $ e r r o r .= ”Es muß e i n Name e i n g e g e b e n werden<b r>\n ”; $ d a t e n [ ”name ”] = ” ”; } else { $ d a t e n [ ”name ”] = $ GET[ ”name ”]; } if (! isset ($ GET[ ” e i n t r a g ”])){ // e s wurde k e i n Komementar e i n g e g e b e n $DatenOK = 0; $ e r r o r .= ”Ein E i n t r a g ohne Komemntar mach n i c h t v i e l ”; $ e r r o r .= ” S i n n , o d e r ?< b r>\n ”; $ d a t e n [ ” e i n t r a g ”] = ” ”; } else { $ d a t e n [ ” e i n t r a g ”] = $ GET[ ” e i n t r a g ”]; }

Christoph Reeg

Seite 166

15. Einfaches G¨stebuch a

if ( $DatenOK ){ // Daten waren OK −> a l s o i n DB e i n t r a g e n mysql_query ( sprintf ( ’ i n s e r t i n t o meldung ( datum , name , e i n t r a g ) VALUES ( now ( ) , ”% s ”, ”% s ”) ’ , addslashes ( $ d a t e n [ ”name ”]), addslashes ( $ d a t e n [ ” e i n t r a g ”]))); echo mysql_error (); ¨ // A l l e s e i n g e t r a g e n −> z u r u c k z u r U b e r s i c h t ¨ header ( ’ L o c a t i o n : h t t p : / / ’ .$ SERVER[ ”HTTP HOST”]. substr ($ SERVER[ ”PHP SELF ”],0, strrpos ($ SERVER[ ”PHP SELF ”], ’ / ’ )) . ’ / ’ ); // und f e r t i g . . . die (); } } else { $ d a t e n [ ”name ”] = ” ”; $ d a t e n [ ” e i n t r a g ”] = ” ”; } ?> < html > < head > < title > Neuer Eintrag in unser GB </ title > </ head > < body > <? php if ( $ s u b m i t && ! $DatenOK ){ // Das F o r m u l a r wurde s c h o n a b g e s c h i c k t a b e r d i e Daten // waren n i c h t OK // −> F e h l e r m e l d u n g a u s g e b e n echo ”<h2>F e h l e r :</ h2>\n ”; echo $ e r r o r ; } // F o r m u l a r a n z e i g e n ?> < form action = ”<?php e c h o $ SERVER [ ”PHP_SELF ” ] ; ? > ” method = ”GET”> Name : < input type = ” t e x t ” name = ”name ” size = ”30 ” maxlength = ”200 ” value = ”<?php e c h o $ d a t e n [ ”name ” ] ; ? > ”>

Christoph Reeg

Seite 167

15. Einfaches G¨stebuch a

< br > Text :< br > < textarea rows = ”10 ” cols = ”50 ” wrap = ” v i r t u a l ” name = ” e i n t r a g ”> <? php echo $ d a t e n [ ” e i n t r a g ”]; ?> </ textarea > < br > < input type = ” s u b m i t ” name = ” s u b m i t ” value = ”Absenden ”> </ body > </ html > Die Ausgabe ist eigentlich noch einfacher als die Eingabe. F¨r den ,realen‘ Einsatz sollte u man allerdings z. B. das Datum sch¨ner formatieren und die Tabelle ist auch nicht so toll. o <? php $DBHost $DBName $DBUser $DBPasswd = = = = ” l o c a l h o s t ”; ” r e e g ”; ” r e e g r o ”; ” s t r e n g g e h e i m ”;

// V e r b i n d u g z u DB−S e r v e r h e r s t e l l e n mysql_connect ( $DBHost , $DBUser , $DBPasswd) OR die ( ”Konnte DB−S e r v e r n i c h t e r r e i c h e n ”); mysql_select_db ($DBName); ?> < html > < head > < title > Die Eintr & auml ; ge in unserem GB </ title > </ head > < body > <? php $ r e s = mysql_query ( ’ s e l e c t datum , name , e i n t r a g from meldung o r d e r by datum d e s c ’ ); echo mysql_error (); while ( $row = mysql_fetch_array ( $ r e s )){ echo ”<t a b l e b o r d e r =\ ”1\ ” w i d t h =\ ”600\ ”>\n ”; printf ( ”<t r><t d>Name:</ t d><t d>%s </t d></ t r >\n ”, htmlentities ( $row [ ”name ”])); printf ( ”<t r><t d>Datum :</ t d><t d>%s </t d></ t r >\n ”, $row [ ”datum ”]);

Christoph Reeg

Seite 168

printf ( ”<t r><t d c o l s p a n =\ ”2\ ”>%s </t d></ t r >\n ”. php4 ”> neuen Eintrag hinzuf¨ gen </ a > u </ body > </ html > ¨ Das Script in Aktion gibt es auf meiner Homepage http:// reeg. } ?> < hr > < a href = ” e i n t r a g . nl2br ( htmlentities ( $row [ ” e i n t r a g ”]))). Die einzigen Anderungen wurden am Layout vorgenommen. Christoph Reeg Seite 169 .net/ . echo ”</ t a b l e >\n ”.15. Einfaches G¨stebuch a printf ( ”<t r><t d>E i n t r a g :</ t d></ t r >\n ”).

wie immer. Ab MySQL Version 3. sollte man meinen. Viel interessanter ist die zweite Anweisung. Als erstes stellt sich. h. o CRON unter Unix. VARCHAR (d. das den gew¨hlten Spruch irgendwo o a speichert. Es gibt auch noch u die Bastell¨sung. Ersteres k¨nnte man theoretisch dadurch a o l¨sen. wie z. Dies sollte hier kein großes Problem sein. daß ein Spruch u a ¨ angezeigt wird. Im Endeffekt will ich nur erreichen. uber die man sp¨ter verhindern kann. daß ein Spruch nicht zweimal eingetragen werden kann. So etwas mit PHP zu realisieren wird schwierig. CREATE TABLE spruch ( SID int not null primary key auto_increment . Kommen wir nun aber zum Programmieren.anzeigen‘ eingef¨hrt. daß man um Mitternacht ein Script aufruft.16 Spruch des Abrufs Was soll das Script eigentlich tun? Nun. mit einem Hilfsprogramm.23 ist es aber m¨glich. n¨mlich. hat man zwei Teilprobleme: Erstens muß man f¨r diesen Tag einen u Spruch ausw¨hlen und diesen zweitens anzeigen. Die einzige M¨glichkeit ist. Spruch text . wird bei jedem Aufruf ein Spruch ausgew¨hlt. PHP bietet allerdings von sich aus keine M¨glichkeit. in welcher Reihenfolge sie programmiert a werden sollten. wird ein neuer Spruch ausgew¨hlt. ob es der erste Aufruf o u an diesem Tag ist und wenn ja. er erlaubt keinen). die Frage nach der Tabelle. Hier stellt sich wieder die Frage. Nachdem nun die Tabellenerstellung gekl¨rt ist. kommen wir zu den eigentlichen PHPa Scripten. Neben dem eigentlichen Text und einem eindeutigen Schl¨ssel habe ich noch eine kleiu ne Spalte . B. B. wobei dann nur ¨ die ersten n Buchstaben genutzt werden (hier sind es 200). CREATE unique INDEX spruch_idx_Spruch ON spruch ( Spruch (200)). Wenn man einen Spruch des Tages realisieren will. o uber diese zweite Anweisung einen Index auf eine TEXT-Spalte zu legen. Dem ist aber leider nicht u ” so. zu gewissen Zeiten irgendetwas o automatisch zu machen. von wo er dann den ganzen Tag lang ausgegeben werden kann. Im Prinzip kein Problem. da Spruch“ vom Typ TEXT ist und dieser in Sachen Index etwas anders funktioniert ” als z. a Um das Ganze etwas einfacher zu halten. bei der bei der Ausgabe immer abgepr¨ft wird. anzeigen bool ) TYPE = MYISAM . ein UNIQUE im CREATE TABLE auf Spruch“ sorgt schon daf¨r. es gibt h¨ufiger den Spruch des Tages oder a a ¨hnliches. a der dann ausgegeben wird. zum gew¨nschten Zeitpunkt das Ganze anzustoßen. Ich habe mich f¨r die folgende entschieden: u • neuen Spruch einf¨gen u • zuf¨lligen Spruch ausgeben a Christoph Reeg Seite 170 .

Der zuf¨llige Spruch ist ja das eigentliche Ziel des Ganzen. Es erfolgt keinerlei Authentifizierung. $DB USER = ” c r ”. Wie man eine entsprechende Paßwort¨berpr¨fung einbauen k¨nnte. jeder kann beliebige Daten in die Datenbank einf¨gen.3. <? php // V e r b i n d u n g s d a t e n MySQL DB $DB HOST = ” l o c a l h o s t ”. $ d a t e n [ ” S p r u c h ”] = ” ”.1. $DatenOK = true . wie in 9. if ( isset ($ GET[ ” s u b m i t ”])){ // F o r m u l a r wurde a b g e s c h i c k t −> Daten p r u e f e n if ($ GET[ ” S p r u c h ”] == ” ”){ $DatenOK = false . gibt es als Letztes auch noch ein ¨ Andern. deshalb die Gesamtausgabe o a ¨ vor dem L¨schen. Um o einen Spruch zu l¨schen. $ F e h l e r = ” ”. $ F e h l e r . $DB NAME = ” c r ”. im Checkbox-Inputfeld wird nicht der Wert ubergeben. In der Variable $anzeigen bzw. wie man es realisiert.16. d. Es ist also eigentlich egal.= ” B i t t e noch e i n e n Text e i n g e b e n !< b r>\n ”. Spruch des Abrufs Neuen Spruch einf¨gen u • alle Spr¨che ausgeben u • Spruch l¨schen o • Spruch ¨ndern a Kurze Begr¨ndung: u Das Einf¨gen in die Datenbank kann uber ein einfaches SELECT von Hand uberpr¨ft weru u ¨ ¨ den.4 schon beschrieben. zumindest kann man jetzt das Ganze in Betrieb nehmen. $DB PASS = ”123 ”. sondern checked“ oder “. um das aber etwas komfortabler zu machen. Trotzdem noch zwei kleine a Anmerkungen. Im Prinzip sollte es durch die Kommentare selbsterkl¨rend sein. hier k¨nnte man jetzt a o auch schon fast aufh¨ren. } else { Christoph Reeg Seite 171 . ¨ der nachher in der Datenbank stehen soll (0 oder 1). steht im u u u o Kapitel 11. aber das Einf¨gen in die Datenbank u etwas schwieriger.1 Neuen Spruch einf¨gen u Das folgende Script ist im Prinzip genauso aufgebaut. Dadurch ” ” wird zwar die Wiederanzeige des Formulars einfacher. Uber L¨schen und anschließendes Einf¨gen kann man im Prinzip auch o o u a ¨ndern. h. muß man ihn irgendwie ausw¨hlen. 16.

$ F e h l e r . continue . continue . ”<b r>\n ”. mysql_error (). Spruch des Abrufs Neuen Spruch einf¨gen u // Daten OK $ d a t e n [ ” S p r u c h ”] = $ GET[ ” S p r u c h ”].0. default : // S o n s t i g e r F e h l e r // −> F e h l e r m e l d u n g a u s g e b e n $DatenOK = false . } Christoph Reeg Seite 172 . switch ( mysql_errno ()){ case 0: // A l l e s OK header ( ’ L o c a t i o n : h t t p : / / ’ . exit . mysql_select_db ($DB NAME) OR die ( ”Konnte DB n i c h t e r r e i c h e n ”). strrpos ($ SERVER[ ”PHP SELF ”]. mysql_errno (). php4 ’ ). mysql_query ( sprintf ( ’ INSERT INTO s p r u c h ( Spruch . $DB USER. $DB PASS) OR die ( ”Konnte DB n i c h t e r r e i c h e n ! ”). ” : ”. addslashes ( $ d a t e n [ ” S p r u c h ”]). ’ / s h o w a l l . $ d a t e n [ ” a n z e i g e n ”])).16. ’ / ’ )) . } // a n z e i g e n kann nur t r u e o d e r f a l s e s e i n // b e i t r u e i s t e s g e s e t z t if ( isset ($ GET[ ” a n z e i g e n ”])){ $ d a t e n [ ” a n z e i g e n ”] = 1. } else { $ d a t e n [ ” a n z e i g e n ”] = 0. substr ($ SERVER[ ”PHP SELF ”]. case 1062: // S p r u c h d o p p e l t e i n g e t r a g e n $DatenOK = false .$ SERVER[ ”HTTP HOST”].= ”MySQL : ”. % d ) ’ . a n z e i g e n ) VALUES ( ”% s ” . } if ( $DatenOK ){ // Daten i n DB e i n t r a g e n mysql_connect ($DB HOST. $ F e h l e r .= ”Den S p r u c h g i b t e s s c h o n<b r>\n ”.

2 Zuf¨lligen Spruch ausgeben a Das ist jetzt fast der einfachste Teil des Ganzen. $ d a t e n [ ” a n z e i g e n ”] = 1. a a a Ansonsten sollte das Script eigentlich selbsterkl¨rend sein. die ich a Christoph Reeg Seite 173 .1 erkl¨rt. Wie man einen zuf¨lligen Datensatz a ausw¨hlt. ?> ” method = ”GET”> < div align = ” c e n t e r ”> <p> < textarea name = ” S p r u c h ” rows = ”5 ” cols = ”80 ”><? php echo htmlentities ( $ d a t e n [ ” S p r u c h ”]). Spruch des Abrufs Zuf¨lligen Spruch ausgeben a } } else { // Werte v o r b e l e g e n $ d a t e n [ ” S p r u c h ”] = ” ”. } ?> < form action = ”<?php e c h o $ SERVER [ ”PHP_SELF ” ] . } ?> < html > < head > < title > SDA eintragen </ title > </ head > < body > <? php if (! $DatenOK ){ echo ”<h1>$ F e h l e r </h1>”.16. ?></ textarea > </ p > Spruch anzeigen < input type = ” c h e c k b o x ” name = ” a n z e i g e n ” value = ” c h e c k e d ” <? php echo ( $ d a t e n [ ” a n z e i g e n ”] ? ” c h e c k e d ” : ” ”). In der ersten Datei. ?>>< p > < input type = ” s u b m i t ” name = ” s u b m i t ” value = ” A l l e s OK ”> </ div > </ form > </ body > 16. von daher spare ich mir hier die Erkl¨rung. ist bereits im Kapitel 7.

php4 genannt habe. Spruch des Abrufs Zuf¨lligen Spruch ausgeben a sda. mysql_select_db ($DB NAME) OR die ( ”Konnte DB n i c h t e r r e i c h e n ”). mysql_connect ($DB HOST. . die ein Array mit mehreren Spr¨chen zur¨ck gibt. SID∗0+ r a n d ( ) AS s o r t FROM s p r u c h WHERE a n z e i g e n = 1 ORDER BY s o r t LIMIT 1 ’ ). wenn du verhindern willst. Diese kann dann sp¨ter aus beliebigen anderen Dateien per include() eingef¨gt werden.16. $DB NAME = ” c r ”. $ r e s = mysql_query ( ’ SELECT S p r u c h . wird eine Funktion get_spruch() realisiert. $DB PASS) OR die ( ”Konnte DB n i c h t e r r e i c h e n ! ”). werden 3 S p r u e c h e a u s d e r ∗ Datenbank g e h o l t . das deine u u Besucher den Server mit st¨ndigem Neuladen der Webseite uberlasten. } /∗ ∗ ∗ H o l t d i e g e w u e n s c h t e Z a h l an S p r u e c h e n a u s d e r ∗ D a t e n b a n k und g i b t d i e s e a l s Array z u r u e c k . Diese Funktion ist praktisch. } return $row [ ” S p r u c h ”]. $DB USER. a u Es gibt auch noch eine zweite Funktion get_sprueche. ∗/ Christoph Reeg Seite 174 . $DB PASS = ”123 ”. if (! $row = mysql_fetch_array ( $ r e s )){ echo ” F e h l e r im S c r i p t ! ”.-) <? php /∗ ∗ ∗ Ho lt einen z u f a e l l i g e n Spruch aus der Datenbank ∗ und g i b t i h n a l s S t r i n g z u r u e c k ∗/ function get_spruch (){ // V e r b i n d u n g s d a t e n MySQL DB $DB HOST = ” l o c a l h o s t ”. ∗ Wird n i c h t s a n g e g e b e n . um an alle Spr¨che a u ¨ zu kommen. $DB USER = ” c r ”.

$DB USER = ” c r ”. Es liest aus einen GET-Parameter die u u Christoph Reeg Seite 175 . f¨r mehrere Spr¨che. php4 ’ ).16. Spruch des Abrufs Zuf¨lligen Spruch ausgeben a function get_sprueche ( $ a n z a h l =3){ // V e r b i n d u n g s d a t e n MySQL DB $DB HOST = ” l o c a l h o s t ”. $ a n z a h l )). SID∗0+ r a n d ( ) AS s o r t FROM s p r u c h WHERE a n z e i g e n = 1 ORDER BY s o r t LIMIT %d ’ . mysql_select_db ($DB NAME) OR die ( ”Konnte DB n i c h t e r r e i c h e n ”). include ( ’ . while ( $row = mysql_fetch_array ( $ r e s )){ $ s p r u e c h e [] = $row [ ” S p r u c h ”]. ?> </ pre > </ body > Und hier das zweite Script. mysql_connect ($DB HOST. $DB USER. } return $ s p r u e c h e . $DB PASS) OR die ( ”Konnte DB n i c h t e r r e i c h e n ! ”). $DB NAME = ” c r ”. ?> < html > < head > </ head > < body > < pre > <? php echo get_spruch (). daß die Funktion tats¨chlich funktioniert. <? php // Wir w o l l e n s a u b e r p r o g r a m m i e r e n error_reporting ( E_ALL ). $DB PASS = ”123 ”. } ?> Und um zu sehen. hier noch ein sehr komplia ziertes Script. / s d a . $ r e s = mysql_query ( sprintf ( ’ SELECT S p r u c h .

Spruch des Abrufs Alle Spr¨che ausgeben u gew¨nschte Anzahl der Spr¨che. if ( isset ($ GET[ ” a n z a h l ”]) && is_numeric ($ GET[ ” a n z a h l ”]) && $ GET[ ” a n z a h l ”] > 0) { $ a n z a h l = $ GET[ ” a n z a h l ”]. foreach ( $ s p r u e c h e AS $ s p r u c h ){ printf ( ”<p r e >\n%s \ n</ p r e >\n ”. u u <? php // Wir w o l l e n s a u b e r p r o g r a m m i e r e n error_reporting ( E_ALL ). include ( ’ . das heißt jeder kann sich alle a Spr¨che ansehen. $ s p r u c h ). l¨schenden Scripts wird per GET-Parameter an das dann noch zu schreibende o Script ubergeben.16. php4 ’ ). ¨ Auch hier erfolgt keinerlei Paßwortabfrage oder ¨hnliches. Dies soll hier realisiert werden. wird zur Administration eine Ubersicht uber alle existie¨ renden Spr¨che ben¨tigt. aber es funktioniert. } ?> </ body > 16. L¨schen angegeben werden. Dazu muß nat¨rlich zu jedem u o u ¨ Spruch noch ein Link zum Andern bzw. u Das Script ist nicht sehr elegant programmiert. Die ID des zu ¨nderno a den bzw. / s d a .3 Alle Spr¨che ausgeben u ¨ Wie schon anfangs geschrieben. <? php // V e r b i n d u n g s d a t e n MySQL DB $DB HOST = ” l o c a l h o s t ”. Christoph Reeg Seite 176 . } else { $ a n z a h l = 3. } ?> < html > < head > </ head > < body > <? php $ s p r u e c h e = get_sprueche ( $ a n z a h l ).

”\ n ”. $DB PASS = ”123 ”. Den Aufruf o 1 Manche Leute behaupten. mysql_connect ($DB HOST. $DB NAME = ” c r ”.16. php4 ”> Neu einf & uuml . n d e r n </a> &nbsp . $DB PASS) OR die ( ”Konnte DB n i c h t e r r e i c h e n ! ”). $row [ ”SID ”]. } ?> </ ul > </ body > 16. ?> < html > < head > < title > SDA ansehen </ title > </ head > < body > < center > < a href = ” i n s e r t c h a n g e . bei meinen Scripten w¨rde nie die L¨schenfunktion programmiert u o Christoph Reeg Seite 177 . while ( $row = mysql_fetch_array ( $ r e s )){ printf ( ’ < l i ><p r e>%s </ p r e> <a h r e f =”i n s e r t c h a n g e . php4 ? SID=%d”>L&ouml . s c h e n </a> ’ . gen </ a > </ center > < ul > <? php $ r e s = mysql_query ( ’ SELECT SID . mysql_select_db ($DB NAME) OR die ( ”Konnte DB n i c h t e r r e i c h e n ”). php4 ? SID=%d”>&Auml . <a h r e f =”d e l e t e . sie zu l¨schen1 . Das L¨schen ist eigentlich kein großes Problem. S p r u c h FROM s p r u c h ORDER BY SID ’ ). das Script o o braucht nur die ID des zu l¨schenden Spruchs und ruft dann ein DELETE auf. w¨re es evtl. auch ganz u o a praktisch.4 Spruch l¨schen o Nachdem wir nun Spr¨che eintragen und sogar ausgeben k¨nnen. $DB USER. Spruch des Abrufs Spruch l¨schen o $DB USER = ” c r ”. $row [ ”SID ”]). $row [ ” S p r u c h ”].

php4 ’ ). a u a o Wer jetzt faul ist (und wer ist das nicht?) wird denken: Das HTML-Formular haben wir doch schon. Als n¨chstes muß bei der Datenpr¨fung nun auch die o o a u Spruch-ID gepr¨ft werden. oder einfach o ¨ wieder auf z.16. mysql_query ( sprintf ( ’ DELETE FROM s p r u c h WHERE SID=%d ’ . Hier beschr¨nke ich mich auf die Pr¨fung.0. Spruch des Abrufs Spruch ¨ndern a f¨r das Script haben wir ja eben schon geschrieben. daß es bei Bedarf ¨ auch noch die Spruch-ID wieder ubergibt. ’ / ’ )) . da sie an mehreren Stellen ben¨tigt wird (h¨tte man auch durch eine o a Funktion eleganter l¨sen k¨nnen). die Ubersichtsseite weiterleiten. $DB USER = ” c r ”. ?> 16. $DB NAME = ” c r ”. ob es eine Zahl ist. $DB USER. mysql_connect ($DB HOST. ’ / s h o w a l l . einen Spruch auch ¨ndern zu k¨nnen. sondern wir erweitern das Einf¨gen-Script ein wenig. header ( ’ L o c a t i o n : h t t p : / / ’ . substr ($ SERVER[ ”PHP SELF ”]. mysql_select_db ($DB NAME) OR die ( ”Konnte DB n i c h t e r r e i c h e n ”).$ SERVER[ ”HTTP HOST”]. u a u Die eigentliche SQL-Anweisung muß nat¨rlich auch erweitert werden. } // V e r b i n d u n g s d a t e n MySQL DB $DB HOST = ” l o c a l h o s t ”. $ GET[ ”SID ”])). u ¨ Die Anderungen sind eigentlich relativ einfach.5 Spruch ¨ndern a Und als letztes w¨re es nat¨rlich auch ganz nett. $DB PASS = ”123 ”. was hier gemacht wird. Stimmt. deshalb benutzen wir das auch. Schließlich m¨ssen auch irgendwo die alten Werte u geholt werden und als letztes wird das HTML-Formular so erweitert. B. <? php if (! isset ($ GET[ ”SID ”]) || ! is_numeric ($ GET[ ”SID ”])){ die ( ” F e h l e r ”). allerdings nicht per Copy and Paste. strrpos ($ SERVER[ ”PHP SELF ”]. Als erstes wird die Datenbankverbindung immer aufgebaut. Das waren dann auch schon alle Anderungen ¨ Christoph Reeg Seite 178 . die Fehlerabfrage u kann dann jedoch wieder dieselbe sein. u Nach dem L¨schen kann man entweder eine Erfolgsmeldung ausgeben. $DB PASS) OR die ( ”Konnte DB n i c h t e r r e i c h e n ! ”).

$ F e h l e r . $DB USER. mysql_select_db ($DB NAME) OR die ( ”Konnte DB n i c h t e r r e i c h e n ”). $DB USER = ” c r ”. <? php // V e r b i n d u n g s d a t e n MySQL DB $DB HOST = ” l o c a l h o s t ”. } // a n z e i g e n kann nur t r u e o d e r f a l s e s e i n // b e i t r u e i s t e s g e s e t z t if ( isset ($ GET[ ” a n z e i g e n ”])){ $ d a t e n [ ” a n z e i g e n ”] = 1. } else { // Daten OK $ d a t e n [ ” S p r u c h ”] = $ GET[ ” S p r u c h ”]. $ d a t e n [ ” S p r u c h ”] = ” ”.16. if ( isset ($ GET[ ” s u b m i t ”])){ // F o r m u l a r wurde a b g e s c h i c k t −> Daten p r u e f e n if ($ GET[ ” S p r u c h ”] == ” ”){ $DatenOK = false . Spruch des Abrufs Spruch ¨ndern a ¨ und wir haben unser Anderungsscript fertig. $ F e h l e r = ” ”.= ” B i t t e noch e i n e n Text e i n g e b e n !< b r>\n ”. $DB PASS) OR die ( ”Konnte DB n i c h t e r r e i c h e n ! ”). $DB PASS = ”123 ”. } else { $ d a t e n [ ” a n z e i g e n ”] = 0. mysql_connect ($DB HOST. $DB NAME = ” c r ”. Christoph Reeg Seite 179 . } if ( isset ($ GET[ ”SID ”])){ // E i n e S p r u c h−ID wurde u b e r g e b e n ¨ // −> s i e muß g e p r u f t werden ¨ // ¨ // U b e r p r u f u n g . // e r s t m a l i s t a l l e s OK $DatenOK = true . ob s i e t a t s a c h l i c h ¨ ¨ existiert .

’ / s h o w a l l .= ” U n g u l t i g e S p r u c h−ID & uuml . continue . php4 ’ ). % d ) ’ . case 1062: // S p r u c h d o p p e l t e i n g e t r a g e n Christoph Reeg Seite 180 . ’ / ’ )) . } // MySQL−R u c k g a b e w e r t a u s w e r t e n ¨ // Wenn OK −> W e i t e r l e i t e n // s o n s t −> F e h l e r m e l d u n g switch ( mysql_errno ()){ case 0: // A l l e s OK header ( ’ L o c a t i o n : h t t p : / / ’ .16. $ F e h l e r . ¨ } else { // Daten OK $ d a t e n [ ”SID ”] = $ GET[ ”SID ”]. strrpos ($ SERVER[ ”PHP SELF ”].$ SERVER[ ”HTTP HOST”]. $ d a t e n [ ” a n z e i g e n ”]. a n z e i g e n ) VALUES ( ”% s ” . addslashes ( $ d a t e n [ ” S p r u c h ”]).0. } else { // n e u e r S p r u c h −> e i n f u g e n ¨ mysql_query ( sprintf ( ’ INSERT INTO s p r u c h ( Spruch . Spruch des Abrufs Spruch ¨ndern a // k ¨ n n t e a u ch noch e r f o l g e n o if (! is_numeric ($ GET[ ”SID ”])){ $DatenOK = 0. $ d a t e n [ ” a n z e i g e n ”])). b e r g e b e n !< b r>\n ”. substr ($ SERVER[ ”PHP SELF ”]. addslashes ( $ d a t e n [ ” S p r u c h ”]). } } if ( $DatenOK ){ // Daten i n DB e i n t r a g e n if ( isset ( $ d a t e n [ ”SID ”])){ // S p r u c h−ID wurde u b e r g e b e n ¨ // −> S p r u c h w i r d g e ¨ n d e r t a mysql_query ( sprintf ( ’UPDATE s p r u c h SET S p r u c h=”%s ” . a n z e i g e n=%d WHERE SID=%d ’ . $ d a t e n [ ”SID ”])). exit .

= ”Den S p r u c h g i b t e s s c h o n<b r>\n ”. default : // S o n s t i g e r F e h l e r // −> F e h l e r m e l d u n g a u s g e b e n $DatenOK = false . } } } elseif ( isset ($ GET[ ”SID ”])){ // e s s o l l d e r S p r u c h SID g e ¨ n d e r t werden a // −> b i s h e r i g e Werte l a d e n // // SID muss an d e r S t e l l e n i c h t a u f n u m e r i s c h // g e t e s t e t w erd en . mysql_error (). } ?> < html > < head > < title > SDA eintragen </ title > </ head > < body > <? php if (! $DatenOK ){ echo ”<h1>$ F e h l e r </h1>”. $ d a t e n [ ” a n z e i g e n ”] = 1. Spruch des Abrufs Spruch ¨ndern a $DatenOK = false . $ d a t e n [ ” S p r u c h ”] = $row [ ” S p r u c h ”]. Christoph Reeg Seite 181 . } $ d a t e n [ ”SID ”] = $row [ ”SID ”]. ”<b r>\n ”. $ d a t e n [ ” a n z e i g e n ”] = $row [ ” a n z e i g e n ”]. } else { // Werte v o r b e l e g e n $ d a t e n [ ” S p r u c h ”] = ” ”. S p r u c h . a n z e i g e n FROM s p r u c h WHERE SID=%d ’ . $ F e h l e r . continue .= ”MySQL : ”. da e s nur m i t %d im s p r i n t f ( ) // g e n u t z t w i r d $ r e s = mysql_query ( sprintf ( ’ SELECT SID . if (! $row = mysql_fetch_array ( $ r e s )){ $DatenOK = false . mysql_errno (). $ F e h l e r .= ”Konnte S p r u c h n i c h t l a d e n ”. $ F e h l e r . ” : ”. $ GET[ ”SID ”])).16.

ungeschickt.6 Schlußbemerkung Dieses Beispiel erhebt keine Anspruch darauf.16. ¨ Eine Anderung und man muß jede Datei ¨ndern. ?></ textarea > </ p > Spruch anzeigen < input type = ” c h e c k b o x ” name = ” a n z e i g e n ” value = ” c h e c k e d ” <? php echo ( $ d a t e n [ ” a n z e i g e n ”] ? ” c h e c k e d ” : ” ”). Spruch des Abrufs Schlußbemerkung } ?> < form action = ”<?php e c h o $ SERVER [ ”PHP_SELF ” ] . ?>>< p > <? php if ( isset ( $ d a t e n [ ”SID ”])){ ¨ // zum Andern a uch d i e SID u b e r g e b e n ¨ printf ( ’ <i n p u t t y p e =”h i d d e n ” name=”SID ” v a l u e =”%d”> ’ . ¨ Ahnliches gilt f¨r das HTML-Layout der Adminseiten2 . Hier steht es fest in jeder Dau tei. Bei der Gelegenheit k¨nnte man dann auch gleich noch o den ganzen Datenbankverbindungsaufbau mit auslagern. flexibler w¨ren dann z. } ?> < input type = ” s u b m i t ” name = ” s u b m i t ” value = ” A l l e s OK ”> </ div > </ form > </ body > 16. diese Daten in a eine zentrale Datei zu speichern. die jeweils per a include() eingebunden w¨rden. $ d a t e n [ ”SID ”]). So ist es z. Noch geschickter w¨re nat¨rlich a u die Verwendung von OOP. ein elegant programmiertes Script zu sein. u 2 Bei diesem Beispiel k¨nnte man auch fragen: Welches Layout? o Christoph Reeg Seite 182 . B. ?> ” method = ”GET”> < div align = ” c e n t e r ”> <p> < textarea name = ” S p r u c h ” rows = ”5 ” cols = ”80 ”><? php echo htmlentities ( $ d a t e n [ ” S p r u c h ”]). HTML-Header und HTML-Footer Dateien. wie sie in Kapitel 18 beschrieben wird. die Datenbankverbindungsdaten in jede Datei zu schreiben. Es bietet sich also an. B.

o Christoph Reeg Seite 183 . wird es aufwendig.16. dann a u o h¨tte man sich die Abfragen gespart. den beiden SQL-Anweisungen und dem HTML-Formular. o u a ¨ 16. aber sobald man etwas ¨ndern muß. Spruch des Abrufs ¨ Ubung Ein Programmieren mit Copy and Paste geht zwar am Anfang schneller.7 Ubung Wieso habe ich bei der Auswahl von mehrere Spr¨chen eine extra Funktion get_sprueche u implementiert? Ich h¨tte doch auch mit Hilfe einer for-Schleife mehrmals die Funktion a get_spruch aufrufen k¨nnen. Allerdings w¨re der Aufwand beim Einf¨gen eines a a u weiteren Feldes gr¨ßer gewesen. Bei dieser L¨sung muß an 4 Stellen erweitert werden: o o bei der Datenpr¨fung. Beim a a ¨ Andern h¨tte man auch das Einf¨gescript kopieren und dann anpassen k¨nnen. weil jede Stelle ge¨ndert werden muß. Bei der u Kopierl¨sung m¨ßte man zwei mal 3 Stellen ¨ndern.

1 Erste Realisierung Als erstes stellt sich die Frage. indem man ein Script schreibt. die Dateinamen m¨ssen von Hand in die SQL-Tabelle eingetragen werden. bei der zweiten Variante dagegen alle Dateinamen in eine Tabelle geschrieben und dann aus dieser einen zuf¨lligen Eintrag ausw¨hlen lassen. Bei dem folgenden Script erledigen die beiden Funktionen genau dasselbe . und wie u h¨ufig welches Banner angezeigt wurde. wie ein Script zum Bannereinblenden und -z¨hlen aussehen a kann. das zweite kann alles geforderte. Zu Demonstrationszwecken wurde das erste Script sowohl ohne als auch mit Datenbank realisiert. das zweite hingegen der Einfachheit halber nur mit Datenbank. daß wir mit Hilfe der .17 Kleines Bannerscript In diesem Kapitel zeige ich. wie h¨ufig welches Banner angezeigt wurde a a • die zum Banner geh¨rige URL als Link anbieten o • z¨hlen. a a Man k¨nnte dies nat¨rlich kombinieren. h. wie h¨ufig auf welches Banner geklickt wurde a a Das Ganze habe ich in zwei Teile geteilt. a Christoph Reeg Seite 184 . muß ebenfalls von Hand aus den Dateien ausgea lesen bzw. Es erhebt keinen Anspruch darauf.directory functio ons‘ auslesen lassen. Noch ein kurzes Wort zu Installation: Beide Funktionen gehen davon aus.banner‘ liegen. Die Dateisystemvariante ben¨tigt zus¨tzlich noch ein o a Verzeichnis. welche Daten gespeichert werden m¨ssen. a d. das wird hier . in dem die Dateien zum Z¨hlen liegen. um dann nachher nur mit der Tabelle zu arbeiten.mit dem Unterschied. welche Dateien in einem Verzeichnis existieren. Im Moment sind u das noch nicht viele: • welche Banner gibt es? • wie h¨ufig wurde das Banner angezeigt? a Den ersten Punkt k¨nnen wir dadurch abhaken. F¨r die L¨sung ohne u o Datenbank habe ich dies auch gemacht. 17. Die ganze Administrationsoberfl¨che habe ich bei diesem Beispiel ganz dezent ignoriert. was alle m¨glio u o chen Dateinamen aus dem Verzeichnis ausliest und dann in die Tabelle schreibt. perfekt zu sein oder alles zu k¨nnen. Es soll nur o ein paar M¨glichkeiten von PHP demonstrieren. das Script aus dem ersten Teil erf¨llt die u Anforderungen der ersten beiden Punkte.rw‘ genannt. o Was soll das Script k¨nnen? o • zuf¨lliges Banner einblenden a • z¨hlen. aus der Tabelle abgefragt werden. daß die Banner im Unterverzeichnis . daß die erste Funktion ohne Datenbank arbeitet.

Kleines Bannerscript Erste Realisierung F¨r die Datenbankversion wird auch eine entsprechende Tabelle ben¨tigt. } } return $ r e t . Christoph Reeg Seite 185 . if ( empty ( $ c o u n t )){ $ c o u n t = 0. count ( $ f i l e s )-1). if ( file_exists ( $ f i l e n a m e )){ $ f p = fopen ( $ f i l e n a m e .17. $ n r = rand (0. CREATE TABLE banner ( BID int not null primary key auto_increment . Name varchar (50) not null . shown int . ” && $ f i l e != ” . f¨r die hier u o u die entsprechende create table-Anweisung steht. // z u f a l l i g e D a t e i a u s w a h l e n ¨ ¨ $ b a n n e r = $ f i l e s [ $ n r ].2). // Z u f a l l i n i t i a l i s i e r e n srand (( double ) microtime ()*1000000). flock ( $ f p .1024). . ”){ $ r e t []= $ f i l e . // Z ¨ h l e r f u r D a t e i e r h ¨ h e n a o ¨ // Dateiname f u r Z ¨ h l e r i n $ f i l e n a m e s c h r e i b e n a ¨ $ f i l e n a m e = ”rw / ”. Das Script sollte durch die Kommentare eigentlich soweit selbsterkl¨rend sein. $ c o u n t = fgets ( $ f p . ” r+”). $ b a n n e r . while ( $ f i l e = readdir ( $ h a n d l e )){ if ( $ f i l e != ” . unique ( Name ) ). a <? php function file_get_name (){ function get_file_array (){ // g i b t e i n Array m i t a l l e n Dateinamen z u r u c k ¨ $ h a n d l e = opendir ( ’ b a n n e r ’ ). } // a l l e Dateinamen i n Array s c h r e i b e n $ f i l e s = get_file_array ().

$row [ ”BID ”])). } Christoph Reeg Seite 186 . mysql_select_db ($DB NAME). // B i l d n a m e z u r u c k g e b e n ¨ return $row [ ”Name ”]. $ c o u n t ). ’ ). } else { $ f p = fopen ( $ f i l e n a m e . Kleines Bannerscript Erste Realisierung } $ c o u n t ++.0). ”w”). $DB PASSWD). return $ b a n n e r . $DB USER = ” c r ”. BID∗0+ r a n d ( ) AS s o r t from b a n n e r o r d e r by s o r t LIMIT 1 . $DB NAME = ” c r ”. Name . } function db_get_name (){ $DB HOST = ” l o c a l h o s t ”. // shown−Z ¨ h l e r um e i n s e r h ¨ h e n a o mysql_query ( sprintf ( ’ u p d a t e b a n n e r s e t shown = shown+1 where BID=%d ’ . $ r e s = mysql_query ( ’ s e l e c t BID . $DB PASSWD = ”123 ”. $ c o u n t = 1. $DB USER. } // E r g e b n i s h o l e n $row = mysql_fetch_array ( $ r e s ). if (! $ r e s ){ // F e h l e r echo ” F e h l e r i n d e r Datenbank ”.17. fseek ( $ f p . return false . fclose ( $ f p ). mysql_connect ($DB HOST. } fwrite ( $ f p .

><img src=. Wir geben nicht die eigentliche URL an. sondern ein Script o auf unserem Server. ? > ”> < img src = ” b a n n e r /<?php e c h o d b g e t n a m e ( ) . sondern das Ganze als Link zur¨ck. wir k¨nnen o nicht z¨hlen.<a href=. was in Ruhe z¨hlen kann und dann auf die richtige URL weiterleitet.></a>‘ aus. Das Klicken findet auf Clientseite a a statt und dort haben wir mit PHP keine M¨glichkeit.<img src=.show banner‘) ist fast identisch mit der Funktion aus der ersten Realisierung. clicked int . das Ganze noch etwas zu a erweitern. Es fehlen n¨mlich die Felder f¨r die Klicks und f¨r u a u u die URL. wie h¨ufig auf ein Banner geklickt wurde. Sie gibt nun allerdings nicht mehr den Bildnamen. Kleines Bannerscript Zweite Realisierung ?> < html > < head > < title > Banner </ title > </ head > < body > < img src = ” b a n n e r /<?php e c h o f i l e g e t n a m e ( ) .. irgendetwas zu machen1 . Nun aber zum Script. Also m¨ssen o u wir uns etwas anderes uberlegen. Aber erstmal zu unserer Tabelle in der Datenbank.. Name varchar (50) not null . heißt es.. u 1 Viele Leute sagen: Zum Gl¨ck u Christoph Reeg Seite 187 . unique ( Name ) ). wie h¨ufig auf welches Banner geklickt wurde a a Ersteres sollte kein Problem sein.. Es fehlen n¨mlich noch zwei Anforderungspunkte: a • die zum Banner geh¨rige URL als Link anbieten o • z¨hlen. shown int . ¨ Die L¨sung ist relativ einfach. Der erste Teil (die Funktion ..17. Diese muß jetzt nat¨rlich auch u nochmal geringf¨gig erweitert werden. Im Endeffekt ergibt sich daraus folgendes create table: CREATE TABLE banner ( BID int not null primary key auto_increment . Dann haben wir allerdings ein Problem. URL varchar (100) not null . ? > ”> </ body > </ html > 17. a Ich habe das hier in einem Script erledigt.2 Zweite Realisierung Nachdem wir nun die Grundfunktionalit¨t haben.>‘ geben wir einfach ein .. An Stelle von .

$DB PASSWD). $DB USER. // shown−Z ¨ h l e r um e i n s e r h ¨ h e n a o mysql_query ( sprintf ( ’ u p d a t e b a n n e r s e t shown = shown+1 where BID=%d ’ . BID∗0+ r a n d ( ) AS s o r t from b a n n e r o r d e r by s o r t LIMIT 1 . ” c r ”. } // E r g e b n i s h o l e n $row = mysql_fetch_array ( $ r e s ). ”123 ”. diese beiden Funktionen in zwei a verschiedene Scripte zu packen. ” c r ”. mysql_select_db ($DB NAME). Name . // Banner m i t L i n k a u s g e b e n printf ( ’ <a h r e f =”%s ? b i d=%d”> ’ . $row [ ”Name ”]). mysql_connect ($DB HOST.bid‘ aufgerufen. $row [ ”BID ”])). function show_banner (){ // z u f ¨ l l i g e s Banner a u s DB h o l e n a $ r e s = mysql_query ( ’ s e l e c t BID . Hier wird nun nicht mehr nur o die Funktion aufgerufen. if (! $ r e s ){ // F e h l e r echo ” F e h l e r i n d e r Datenbank ”. sondern es gibt eine Fallunterscheidung. $ SERVER[ ”PHP SELF ”]. ’ <img s r c =”b a n n e r/%s ” b o r d e r =”0”></ a> ’ . Wird das Ganze ohne . so wird das Banner zur¨ckgegeben. $row [ ”BID ”]. <? php $DB HOST $DB USER $DB PASSWD $DB NAME = = = = ” l o c a l h o s t ”. weil man alles u zusammen hat.17. Kleines Bannerscript Zweite Realisierung ¨ Die gr¨ßte Anderung befindet sich im Hauptprogramm. Die Kombination in einem Script mag f¨r diesen Fall einfacher sein. ansonsten wird der Klick gez¨hlt und u a zur URL weitergeleitet. Christoph Reeg Seite 188 . ’ ). h¨ufig ist es aber wahrscheinlich besser. return false .

} else { // Banner a n z e i g e n ?> < html > < head > < title > Banner </ title > </ head > < body > <? php show_banner ().17. $row [ ”URL”]). $ GET[ ” b i d ”])). $ GET[ ” b i d ”])). Kleines Bannerscript Zweite Realisierung } /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Hauptprogramm ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ if ( isset ($ GET[ ” b i d ”])){ // b i d g e s e t z t −> e s wurde a u f e i n e Banner g e k l i c k // −> User w e i t e r l e i t e n if (! is_numeric ($ GET[ ” b i d ”])){ // b i d muß immer n u m e r i s c h s e i n die ( ’ K e i n e g u l t i g e ID u b e r g e b e n ’ ). } // c l i c k −Z a e h l e r um e i n s e r h o h e n ¨ mysql_query ( sprintf ( ’ u p d a t e b a n n e r s e t c l i c k e d = c l i c k e d +1 where BID=%d ’ . ¨ ¨ } // URL a u s DB h o l e n $ r e s = mysql_query ( sprintf ( ’ s e l e c t URL from b a n n e r where b i d=%d ’ . // User a u f d i e r i c h t i g e S e i t e w e i t e r l e i t e n header ( ’ L o c a t i o n : ’ . ?> </ body > </ html > Christoph Reeg Seite 189 . if (! $row = mysql_fetch_array ( $ r e s )){ // F e h l e r die ( ” F e h l e r i n d e r Datenbank ”). exit .

Kleines Bannerscript Zweite Realisierung <? php } ?> Christoph Reeg Seite 190 .17.

Teil V Objektorientierung theorethisch Jens Hatlak Seite 191 .

Im n¨chsten Teil kommt dann die Realisierung in PHP. Bei der Programmierung mit Funktionen wird das ganze schon etwas ubersichtlicher. Diese besitzen ein Display. hatten keine große Struktur: In ihnen wird einfach am Anfang des Programmes angefangen und am Ende aufgeh¨rt. o Wir k¨nnen auch nicht direkt die Uhrzeit ¨ndern. sondern m¨ssen die Tasten benutzen und o a u k¨nnen dadurch z. Das o Ganze wird allerdings schnell un¨bersichtlich und Teile lassen sich nur durch Cut’n’Paste u wieder verwenden. um die aktuelle Uhrzeit. das heißt die u Werte m¨ssen alle uber das aufrufende Programm gehen. o denn die genaue Darstellung des Problems f¨hrt zur L¨sung. Es ¨ gibt Funktionen. das Datum und die Weckzeit anzuzeigen. auch nicht 25:00 Uhr einstellen. das Ganze mit Funktionen nachzubauen. h¨tten wir ein a Problem: Wir k¨nnten zwar Funktionen wie setTime() oder setAlarm() programmieren. ein wenig hin und her gesprungen. Im Prinzip hat man damit versucht. die Funktionen (hier Methoden genannt) auf gemeinsame Daten (Attribute. Teilweise wird mit if & Co. Klasse genannt. Wie die Uhr die einzelnen Werte speichert. Wenn wir uns jetzt vorstellen. und die ¨ Kapselung ist ein zentraler Bestandteil der Objektorientierung2 . a a Die ersten Beispielprogramme. und uber Tasten k¨nnen letztere auch eingestellt o ¨ werden. die Uhrzeit ist gekapselt o und man kommt nur uber die entsprechenden Funktionen an sie heran.oder Instanzvariablen genannt) zugreifen k¨nnen. u o Albert Einstein In diesem Teil soll die Objektorientierte Programmierung (kurz OO bzw. daß in einer solchen Einheit. u ¨ Bei der Objektorientierung ist man einen Schritt weiter gegangen und hat die Daten und die Funktionen zusammengefaßt. Das heißt. als die L¨sung zu erkennen. Allerdings k¨nnen die Funktionen untereinander o (¨ber den eigentlichen Funktionsaufruf hinaus) keine Werte austauschen. k¨nnen wir von außen nicht feststellen1 . Klassen. die im Verlauf dieses Manuals besprochen wurden.1 Ein kleines Beispiel: Funkwecker Jeder kennt digitale Funkwecker. o 18. B. die bei einem Aufruf mit den ubergebenen Werten etwas machen. Die Gesamtheit ¨ aller Tasten in diesem Beispiel nennt man in der OOP ubrigens Schnittstelle.18 Bedeutung von Objektorientierung Das Problem zu erkennen ist wichtiger. so daß man sie nun als eine Einheit betrachtet. Konkret heißt das. OOP) allgemein erkl¨rt werden. o 1 2 Normalerweise interessiert uns das auch gar nicht Wenn auch einer. Diese ¨ Funktionen lassen sich in diverse Dateien ausgliedern und k¨nnen dadurch in mehreren o Programmen wieder verwendet werden. die reale Welt abzubilden. der in PHP bisher nicht konsequent umgesetzt wurde – mehr dazu sp¨ter a Jens Hatlak Seite 192 .

jederzeit vorgenommen werden k¨nnen. Auch sollten Eigenschaften grunds¨tzlich nur uber die Schnittstelu a ¨ ¨ le abruf. Den DSP-Werken uberlassen wir es. die Weckfunktion nicht funktionieren w¨rde. h. einzubauen). B. solange man nur die Schnittstelle unver¨ndert l¨ßt und nat¨rlich am zu a a u erwartenden Ergebnis einer Funktion nichts ver¨ndert (wenn man bisher immer beschleua nigt hat. wenn man aufs Gaspedal getreten hat. ist das einer Autofabrik. bremst. Uns interessiert auch gar nicht. denn dieses besitzt das Attribut Uhrzeit und kann diese mit Hilfe der Methode setTime() nach einer Plausibil¨tspr¨fung setzen. u 18. daß er sich wie u ein ganz normales Auto verh¨lt. daß die DSP-Werke nur ein Modell CR“ herstellen (das aber ” in millionenfacher Auflage). einen f¨r jeden Ehepartner. B. ohne weitere Abh¨ngigkeiten verfolgen zu o a m¨ssen. sondern lieber einen dunkelgr¨nen CR in der u Family-Ausf¨hrung. k¨nnen also o selbst keine weiteren Exemplare herstellen. Alles. Innerhalb der DSP-Werke ist f¨r diese Bestellung der Konstruktor u u zust¨ndig: Er nimmt die Daten auf und sorgt daf¨r. was wir dazu kennen m¨ssen. das w¨re ja langweilig. die gew¨nschte Funka u ¨ tionalit¨t zur Verf¨gung zu stellen (d. haben wir als Besitzer eines DSP CR nur genau ein Exemplar. wie etwas gel¨st a o wurde.-) o u Jens Hatlak Seite 193 . ist die Schnittstelle des DSP CR: Wie startet man den Wagen. ). schaltet und lenkt man? An dieser Stelle kann man schon etwas sehr grundlegendes der Objektorientierung feststellen: Durch die Kapselung der Funktionalit¨t erreicht man. das oft verwendet wird. daß man diese problemlos a optimieren kann. :-) Die u beiden Wagen sollen aber nat¨rlich nicht genau gleich sein. Das Beispiel Funkwecker hinkt nat¨rlich etwas. das in den DSP-Werken u hergestellt wird. da a u u Objekte im Hintergrund nicht einfach weiterlaufen und damit z. daß wir diesmal keinen Standard-Silbermetallic-CR haben wollen. Stellen wir uns vor.und ver¨nderbar sein. daß diese allen daran interessierten a u Fabrikationsstationen des Werkes in der einen oder anderen Form zur Verf¨gung gestellt u werden. Bei einem Objekt gibt es das Problem nicht. wenn a ¨ die DSP-Werke in der n¨chsten Modellgeneration einfach die Bremse mit dem Gaspedal a verbinden w¨rden . B. Gleichzeitig gibt o es aber noch Millionen anderer DSPs.2 Jedem sein Auto Ein weiteres anschauliches Beispiel. sondern doch lieber zwei – z. damit etwaige Anderungen an der Art. f¨r Donner-schneller Pfeil stehen . u wie beschleunigt. 3 K¨nnte z. Wir u a sagen den DSP-Werken also beim Bestellen des Zweitwagens gleich. es also benutzen.18. Wir wollen aber vielleicht nicht nur a u einen Wagen haben. u Doch zur¨ck zum Autofahren: Wir erwarten also von unserem Wagen. die allesamt aus dem DSP-Werk stammen. . dann haben wir hier ein prima Beispiel f¨r die Beziehungen u der Objektorientierung: W¨hrend die DSP-Werke die Pl¨ne f¨r die Konstruktion von Autos des Modells DSP a a u CR haben. Wenn wir vereinfachend annehmen. Bedeutung von Objektorientierung Jedem sein Auto k¨nnten die Werte aber nicht speichern (auf globale Variablen wollen wir unter anderem o des guten Programmierstils wegen verzichten). wir w¨rden ein Auto der Marke DSP3 fahren. . w¨re man sicher mehr als uberrascht. Wir bekommen – entweder direkt von der Fabrik oder uber einen H¨ndler a ¨ – ein Exemplar eines nagelneuen DSPs geliefert und der geh¨rt dann uns. wie der Fertigungsprozeß aussieht – wir wollen ja nur mit dem Auto fahren.

Doch Halt! Das war alles schon objektorientiert! :-) Was noch fehlt. ver¨nderbar sein. ist eigentlich nur noch die Erkl¨rung. von der Klasse B abgeleitet wurde. Bedeutung von Objektorientierung Von Autos zu Objekten Nun stellen die DSP-Werke im Wesentlichen nat¨rlich DSP-Modelle her.bzw.18. muß man einige neue a Begriffe einf¨hren.4 Vererbung Wer hat nicht schon einmal von Vererbung geh¨rt? Beim Programmieren und insbesondere o bei Objekten geht es nat¨rlich nicht um den biologischen Begriff. u 4 Außer. In der folgenden Tabelle werden daher die Begriffe des Beispiels denen u der tats¨chlichen Objektorientierung gegen¨bergestellt. aber o sie haben eine Gemeinsamkeit: Sie sollen beide auch indirekt von jedem Besitzer eines DSP CR aufruf. denn wenn ein solcher Dienst von jemandem erbeten wird. Logischerweise d¨rfen Extra-Dienste der DSP-Werke a u auf keine Eigenschaften von DSP-Modellen zugreifen. der keinen DSP CR besitzt. der nicht direkt abh¨ngig von einem a Wagen ist. a u Welt der Autos DSP-Werk mein DSP CR Eigenschaften des DSP CR Funktionalit¨t des DSP CR a Konstruktor der DSP-Werke Zweitwagen Extra-Dienste der DSP-Werke Sonderaktion der DSP-Werke Welt der Objekte Klasse DSP Objekt der Klasse DSP Attribute der Klasse DSP Methoden der Klasse DSP Konstruktor der Klasse DSP anderes Objekt der Klasse DSP static-Methoden der Klasse DSP static-Attribut der Klasse DSP Tabelle 18. daß jedes Objekt einer Klasse B dieselben Methoden beherrscht wie ein Objekt der Klasse A.3 Von Autos zu Objekten Nun haben wir hoffentlich alle verstanden. dann kann auch an keinem DSP CR eine Ver¨nderung durchgef¨hrt werden – nicht einmal die Abfrage von Daten eines a u DSP-Modells ist erlaubt4 ! 18. zur Objektorientierung zu kommen. welche Beziehungen zwischen den Autofahrern und den DSP-Werken bestehen – es wird Zeit. jedoch sinnvollerweise von den DSP-Werken angeboten wird. Vielleicht will der DSP-Konzern aber auch einfach nur eine Sonderaktion starten und f¨r begrenzte Zeit ein Logo auf jeden gefertigten DSP CR spr¨hen lassen.1: Von Autos zu Objekten 18. Die beiden F¨lle u u a scheinen auf den ersten Blick v¨llig unterschiedliche Problematiken zu beschreiben. h. ob er einen DSP CR hat oder o nicht. geerbt hat. Wenn man von obigem Beispiel zur OOP kommen will. Sicher gibt u es aber auch den einen oder anderen Extra-Dienst. Zus¨tzlich kann es noch eigene Methoden definieren oder vorhandene a Methoden neu definieren (¨berschreiben). Auf diesen ExtraDienst soll jeder Außenstehende zugreifen k¨nnen – egal. d. Vererbung ist der zweite u fundamentale Begriff der OOP und bedeutet. ein solches Datum ist wiederum vom gleichen Charakter wie die Sonderaktion Jens Hatlak Seite 194 .

In vielen Programmieru sprachen – so auch in PHP – heißt der Konstruktor so wie die Klasse.4.5 Konstruktor Wie schon in der Erkl¨rung des Auto-Beispiels gesehen. y). wenn u alle Ideen des Modells CR verworfen werden m¨ßten – niemals aber die Grundidee des u Autos! 18.-) Denkbar ist doch. Auch daf¨r wurde eine M¨glichkeit geschaffen. B. Destruktor gea u o 5 Die oben erw¨hnten static-Methoden m¨ssen nat¨rlich immer funktionieren a u u Jens Hatlak Seite 195 . die am Ende die Aufr¨umarbeiten erledigt. die das Bild anzeigt. die mit Hilfe der Image-Funktionen der Program” miersprache ein leeres Bild mit definierbarer H¨he und Breite erzeugt. Bedeutung von Objektorientierung Konstruktor Bezogen auf das obige Auto-Beispiel k¨nnten z. das heißt Point“ erbt alle Methoden und Attribute von ” ” Image“. wobei letzteres durch die Spezialform Square“ (Quadrat) ” ¨ erweitert werden kann. die keine Return-Anweisung enthalten darf. Der Einfachheit halber nehmen sie dazu die Pl¨ne des DSP a CR. braucht man zum Erzeugen eia nes Objektes einen sogenannten Konstruktor. Bei unserem Image-Beispiel haben wir die Methode init(). nehmen wir Point“ (Punkt) a ¨ ” als Erweiterung von Image“. Das ganze wird sp¨ter als Ubung noch etwas vertieft werden. a 18.6 Destruktor Manchmal braucht man neben einem Konstruktor auch eine Funktion. Diese Klasse kennt o die Methode show(). F¨r diesen Zweck gibt es die Methode set(x. Auf dieselbe Weise kann man von Point“ wiederum Circle“ (Kreis) und Rec” ” ” ” tangle“ (Rechteck) ableiten. Wird dies nicht gemacht. Der Konstruktor ist im Grunde nichts anderes als eine spezielle Methode. daß die Klasse nicht richtig funktioniert5 . Ein leeres Bild ist aber langweilig. 18. der wieder herausgekramt werden kann. Allgemeiner Konstruktor“ ist nat¨rlich nur ein Oberbegriff f¨r alle Konu u ” struktoren außer dem Standardkonstruktor. Ebenso ist der DSP CR im Grunde auch nur ein Auto. erg¨nzen hier und ¨ndern da etwas – das neue Modell basiert ja auf dem erfolgreichen a a DSP CR. kann es passieren.18. die bei jedem Objekt als erstes einmal aufgerufen werden muß.1 Image-Beispiel Ein Beispiel aus der Programmier-Praxis zeigt es noch deutlicher: Wir haben eine Klasse Image“ (Bild). weil der Konstruktor grunds¨tzlich und implizit ein Objekt der Klasse zur¨ckliefert. W¨hrend ersterer parameterlos und dadurch eindeutig bestimmt ist. wurde der Konstruktor eingef¨hrt. daß irgendwo in den Tiefen des DSPArchivs schon ein Plan f¨r ein Ur-Auto liegt. also ben¨o tigen wir eine neue Klasse Point“. a u Es gibt die Unterscheidung zwischen dem Standardkonstruktor und dem Allgemeinen Konstruktor. einen Punkt in diesem o ” Bild zu malen. die DSP-Werke ein neues Modell DSP o CR-JH herausbringen wollen. Damit aber eine solche Initialisierungsfunktion immer einmal aufgerufen wird. Da die Methode show() u mehr oder weniger unver¨ndert ubernommen werden kann. damit verschiedene Attribute initialisiert werden. erwara tet letzterer mindestens einen Parameter und ist dadurch allgemein brauchbar (daher die Bezeichnung). durch die es m¨glich sein soll. also warum f¨r jedes u Modell das Rad neu erfinden? .

kann ” dir ein Biologe sagen. sollte man a sich zumindest grundlegende. Die Klasse wiederum ist die abstrakte Definition der Eigenschaften eines Objektes. h. daß du ein Objekt der Klasse Lebewesen“ ” bist: du bist ein konkretes Exemplar der abstrakten Gattung Lebewesen. die ausschließlich von der Klasse selbst (oder erbenden Klassen) und nur intern benutzt werden. Bedeutung von Objektorientierung Klasse oder Objekt nannt. die jedes Objekt einer solchen Klasse benutzen k¨nnen soll. Auf der anderen Seite sollen Daten ja gekapselt sein. private oder doch protected? Bei Klassen gibt es Methoden. wird sich unweigerlich fragen. u Jens Hatlak Seite 196 . o In unserem Beispiel sind das init(). private und protected. F¨r genau diese u Unterscheidung gibt es die drei Schl¨sselw¨rter public“ (auf die Methode / das Attribut u o ” darf von uberall aus zugegriffen werden). Nehmen wir als Beispiel die Klasse Lebewesen“. der kann sich beruhigt zur¨cklehnen und aufatmen: PHP u 4 kennt noch keine Unterscheidung zwischen public. o u ” m¨ssen sie auf protected gesetzt werden. d. private“ (nur aus genau der definierenden ¨ ” Klasse darf auf die Methode / das Attribut zugegriffen werden) und protected“ (aus ” der Klasse und allen abgeleiteten Klassen darf auf die Methode / das Attribut zugegriffen werden).-) 18. . aus der Klasse Point“ darauf zuzugreifen. Die Erkl¨rung zum a Auto-Beispiel sollte diese Frage eigentlich schon gekl¨rt haben. width oder height. Bei unserem obigen Image-Beispiel m¨ssen die genannten Methoden public sein (sonst u w¨rden sie keinen Sinn machen). Da sich das jedoch mit PHP 5 definitiv ¨ndern wird (siehe 20. doch allgemein k¨nnte man a o sagen.18. Wenn sie nun in der Klasse Image“ auf private gesetzt w¨rden. grobe Gedanken machen und z.7 Klasse oder Objekt Wer das erste Mal von Klassen und Objekten h¨rt. Die Attribute wie z. show() und set().8 Zugriffsrechte: public. B. Man kann sich uber die Funktion ¨ register_shutdown_function() einen Behelf zusammenbauen oder sich PHP 5 anschauen. man kann nicht direkt darauf zugreifen. u Wem dies jetzt zu viel war.5). durch u Kennzeichnung mittels einem (keinesfalls zwei!) vorangestelltem Unterstrich – gilt auch f¨r Attribute. die uber u ¨ init() gesetzt werden. o PHP kennt allerdings bisher leider keine Destruktoren. B. h¨tten wir u a ” keine M¨glichkeit. Zus¨tzlich d¨rfen alle Objekte einer Klasse auf alle Eigenschaften eines Objekts a u derselben Klasse zugreifen (also auch private-definierte). z. B. was o diese Begriffe bedeuten und was der Unterschied zwischen beiden ist. an das Ende der Klasse verfrachten und f¨r private oder protected vormerken. 18. damit nicht jeder an sie heran kommt. Ich kann dir nur sagen. Es ist einfach alles public. ein Objekt ist einfach ein konkretes Exemplar einer Klasse. Wenn dies gew¨nscht ist. Destruktoren k¨nnen keine Parameter haben. sollten nicht auf public gesetzt werden. Welche Eigenschaften ein Exemplar dieser Klasse haben muß. alle Methoden.

19 Bezeichnungen Im Rahmen der Objektorientierung gibt es eigene Vokabeln wie Objekte. Ich versuche.3 Klasse Eine Klasse ist die Definition. zusammen mit den Methoden (wobei die Attribute Eigenschaften wie ¨ Farbe oder Gr¨ße sein k¨nnen – Attribute eben – und Methoden z.3. a 19. Offnen oder Lesen o o und Schreiben. also eine ganz bestimmte Instanz. Methoden. also eine gewisse F¨higkeit). u 19.1 Basisklasse Die Klasse. a Jens Hatlak Seite 197 . also quasi ihr direkter Vorfahre. Attribute werden oft auch Eigenschaften eines Objekts genannt. welche Attribute und F¨higkeiten ein Objekt sp¨ter haben a a soll. B. Im Endeffekt wird nur mit den Objekten gearbeitet.1 Instanz Eine Instanz ist ein konkretes Exemplar. das zu genau einer Klasse geh¨rt. Vererbung etc.5 Attribut Die Variablen einer Klasse heißen Attribute.4 Methode In der OOP werden die Funktionen einer Klasse als Methoden bezeichnet. sie hier zu erkl¨ren. 19. Also quasi ein Bauplan f¨r Objekte.2 Objekt Ein Objekt ist eine Instanz einer Klasse. Klassen. 19. von der eine Klasse erbt. 19. der man einen Namen gegeben hat. 19. Vom Prinzip her kann man Objekte mit Variablen und Klassen mit Datentypen vergleichen. also von ihr o erzeugt wurde.

7 Destruktor Das Gegenteil vom Konstruktor: Die Methode wird beim L¨schen des Objektes automao tisch aufgerufen. PHP 4 kennt keine Destruktoren. um Initialisierungen vorzunehmen.6 Konstruktor Methode.5). erst die kommende Version 5 (siehe 20. 1 Erstellen einer Instanz Jens Hatlak Seite 198 .19. die beim Instanzieren1 eines Objektes einmal automatisch aufgerufen wird. Bezeichnungen Konstruktor 19. 19. Diese wird in der Regel genutzt.

Teil VI Objektorientierung praktisch Jens Hatlak Seite 199 .

die mit zwei Underscores (z. um als zur Klasse geh¨rig u o 1. hat erst mit Version 4 brauchbare u objektorientierte Z¨ge angenommen. a o Anders als etwa in Java kann es in PHP immer nur genau einen Konstruktor pro Klasse geben. Das folgende Kapitel gilt der Einfachheit halber nur f¨r PHP 4. urspr¨nglich eine prozedurale Skriptsprache.06 aufw¨rts. B.1. In diesem Kapitel will ich versuchen zu zeigen.1 Klassen in PHP Klassen beginnen in PHP mit dem Schl¨sselwort class. daß der Name stdClass“ in PHP4 reserviert ist. } 20. ebenso wie alle Me” thodennamen. Parameter im Funktionskopf auf 1 Vorsicht: In PHP3 gilt eine Methode mit dem Namen einer Klasse auch dann als Konstruktor dieser Klasse. erkannt zu werden Zu beachten ist. Durch die Eigenschaft von PHP-Funktionen.. wie u man objektorientiert in PHP programmiert und auch ein paar Beispiele geben. exklusive PHP u a 5. Wie bei Funktionen wird der Klassenrumpf von geschweiften Klammern umschlossen. daß sich das ¨ bißchen Mehraufwand wirklich lohnt (Stichwort Ubersichtlichkeit/Wiederverwendbarkeit). Alle Attribute bzw.. wie man von der Problemstellung zur OO-Umsetzung kommt und auch. a Kristian K¨hntopp o PHP.1 Konstruktoren Konstruktoren in PHP heißen grunds¨tzlich genau so wie die Klasse..20 Objektorientierung in PHP Objektorientiert: Den Code habe ich von meinem Vorg¨nger geerbt. wenn sich die betreffende Methode gar nicht innerhalb dieser Klasse befindet! Jens Hatlak Seite 200 . __sleep. um zu sehen. gefolgt von einem Bezeichner. Beispiel: class DSP_CR { function Auto () { . __wakeup) beginnen. dem u Klassennamen. } . Klassen-/Instanzvariablen sowie Methoden (einschließlich der Konstruktoren) m¨ssen sich in diesem Block befinden. 20.. zu der sie geh¨ren.

20... Objektorientierung in PHP Klassen in PHP Defaultwerte setzen zu k¨nnen.1. hierf¨r sollte der Konstruktor verwendet werden... Die Unf¨higkeit von PHP3. } class DSP_CR extends Auto { // h i e r i n E r ma n ge lun g von Methoden noch // n i c h t u b e r den K o n s t r u k t o r g e s e t z t ¨ var $ f a r b e = ” m e t a l l i c ”. o 20. von der geerbt werden soll. Beispiel: class Auto { var $ b a u j a h r . dies zu meistern. } 2 Noch ist es m¨glich. var $ f a r b e . Beispiel: class Auto { .7) deklariert werden. o u Eine Besonderheit beim Umgang mit Konstruktoren ist schließlich noch der implizite Aufruf des Konstruktors der Basisklasse in dem Fall. warum nach a M¨glichkeit PHP4 eingesetzt werden sollte. .. es wird aber wahrscheinlich irgendwann nicht mehr erlaubt sein o Jens Hatlak Seite 201 . die Verwendung des Punktoperators oder Variablenzuweisungen sind bei ihrer Definition nicht erlaubt. dem der Name der Klasu se. Klassen-/Instanzvariablen werden in PHP mit dem Schl¨sselwort var deu finiert und k¨nnen optional mit beliebigen statischen Werten initialisiert werden.. .. durch if-Abfragen oder o o switch-Bl¨cke die meisten Konstellationen von Parameter¨bergaben abzudecken. folgen muß.. die in PHP ja mitu tels der define()-Funktion (8. Funktio onsaufrufe. daß eine Klasse keinen Konstruktor besitzt.2.1. ist auch der Grund. } class DSP_CR extends Auto { .3 Attribute in PHP Attribute bzw. } 20. hierf¨r u sollte genauso der Konstruktor verwendet werden wie f¨r Konstanten.2 Vererbung in PHP Vererbung wird mittels des Schl¨sselwortes extends signalisiert. Der gesamte Vererbungsausdruck ist jedoch optional. Die Wertzuweiu sung von Attributen direkt bei ihrer Deklaration ist allerdings nicht empfohlen2 . ergibt sich jedoch die M¨glichkeit.

function Auto () { . R¨ckgabewerte.. sogar Sichtbarkeit)...1. Parameter. 20.5 Klassen dokumentieren Eine ¨ußerst sinnvolle Methode. Hierbei wird die Klasse selbst ebenso ber¨cksichtigt wie Konstruktoren.1. werden diese auch genau wie Funktionen definiert. var $ f a r b e .2.. u Jens Hatlak Seite 202 .1). u Attribute und Methoden samt ihrer spezifischen Eigenschaften (Copyright. } function setzeFarbe ( $ f a r b e ) { . Klassen zu dokumentieren und zu kommentieren stellt a PHPDoc dar (14).. ggf. } Zur Referenzierung von Methoden mehr weiter unten (20. 20. else $ t h i s -> farbe = $ f a r b e . m¨ ssen h i e r k e i n e V a r i a b l e n u // d e f i n i e r t w erd en .2. } class DSP_CR extends Auto { // Da DSP CR von Auto e r b t . u ¨ Beispiel: class Auto { var $ b a u j a h r .... } .1). } .20. ¨ function DSP_CR ( $ f a r b e ) { if ( empty ( $ f a r b e )) $ t h i s -> farbe = ” m e t a l l i c ”. Sie k¨nnen also Parameter unterschiedlicher Anzahl o ubergeben bekommen und Werte mittels return zur¨ckliefern.4 Methoden in PHP Da Methoden nichts anderes sind als Funktionen innerhalb einer Klasse. Mehr dazu im angegebenen Kapitel. Die g e e r b t e n A t t r i b u t e ( und auch // Methoden ) d e r B a s i s k l a s s e kann man n a t u r l i c h n u t z e n . Objektorientierung in PHP Klassen in PHP Zur Referenzierung von Attributen mehr weiter unten (20.

Folgender Code ist somit g¨ltig: u $meinWagen = new DSP_CR (). bis es explizit auf NULL gesetzt wird oder das Skript beendet wird. Jens Hatlak Seite 203 .inc. der Parameter erwartet. in der das Schl¨sselwort new neu eingef¨hrt wird. Allgemein kann man mit Objektvariablen ubrigens ganz analog zu normalen Primitivtyp-Variablen Objekt-Zuweisungen durchf¨hu ¨ ren. aber der Inhalt der beiden Objekte ist nun so lange gleich. erzeugt in PHP ein u u Objekt: $meinWagen = new DSP_CR (). Ublicherweise lagert man Klassendefinitionen in Include-Dateien aus. die Eigenschaften des Objekts annimmt. In PHP definiert man Objekte genau wie Variablen mit dem Dollarzeichen. wo man ein spezielles Objekt betrachtet. erfolgt die Objektinitialisierung ganz analog. Trotzdem kann eine Klaso se nat¨rlich beliebige Objekte anderer Klassen erzeugen und auch als eigene Attribute u verwalten. ein Objekt abh¨ngig von seinen ganz o a pers¨nlichen“ Eigenschaften zu ver¨ndern. Auf das so erzeugte Objekt kann nun so lange zugegriffen werden. in das Objekt selbst! Dadurch hat man die M¨glichkeit. Objektorientierung in PHP Objekte und Referenzierung in PHP 20. so sollte es doch im Folgenden klar werden. die dazu ihren parameterlosen Konstruktor benutzt. so u verwandelt sie sich doch in dem Moment. bevor eine solche Zuweisung erfolgen kann. Folgende Syntax. Wenn also die Klasse eigentlich nur der Bauplan f¨r Objekte ist. z. Die Erzeugung eines Objektes geschieht grunds¨tzlich außerhalb a der Klasse.20. $meinWagen = $ m e i n Z w e i t w a g e n . liegt der Gedanke nahe. Da die Klasse quasi den Plan“ f¨r ein Objekt darstellt. Achtung: Bis vor der Zuweisung waren meinWagen und meinZweitwagen noch v¨llig o unterschiedliche Objekte! Danach enthalten die beiden Objektvariablen zwar auch noch unterschiedliche Referenzen (zeigen also nicht auf das gleiche Objekt). wo man ein einzelnes Objekt betrachtet. B. $ m e i n Z w e i t w a g e n = new DSP_CR (). nach dem Schema <KlassenName>.2 Objekte und Referenzierung in PHP Wie wir bereits aus dem Kapitel Bedeutung von Objektorientierung“ (18) wissen. bis eines der Objekte ge¨ndert wird. zu der es geh¨rt (außer bei rekursiven Definitionen).3 Der Quelltext der Klasse muß nat¨rlich bereits u ¨ vom PHP-Parser gelesen worden sein. Das Objekt meinWagen wird hierbei von der Klasse DSP_CR erzeugt. ohne es beim Erstellen der Klasse schon zu o a ” kennen! :-) 3 4 Vorsicht: Die bisherigen Beispiele waren noch unvollst¨ndig! a Wenn das auch an dieser Stelle etwas verwirrend erscheint. Wird anstelle des parameterlosen Konstruktor einer verwendet. und importiert sie mit include() oder require().4 a Innerhalb einer Klasse geh¨ren die Attribute und Methoden der Klasse immer dem o gerade zu betrachtenden Objekt. daß dieser u ” Plan in dem Moment. sind Ob” jekte konkrete Exemplare einer Klasse. indem man wie bei Funktionsaufrufen die Parameter in entsprechender Reihenfolge innerhalb der runden Klammern angibt. das wie gesagt nur außerhalb der Klasse existiert.

B.6 u Eine kleine Anmerkung noch: Wie vielleicht bekannt sein d¨rfte. muß man das Schl¨sselwort this anstelle des Objektnamens verwenden.1. Boolean. u bei Objekten also eine Kopie der Referenz. wenn versucht wird. Referenzsemantik Beim Aufruf einer Methode kann man dieser – vorausgesetzt. gefolgt vom Namen des zu referenzierenden Objektes. die Klasse gehen.20. Will man innerhalb einer Klasse auf die Attribute oder Methoden derselben Klasse zugreifen (die wie gesagt in dem Moment. wo bei Objekten statt der Kopiersemantik die sog. werden in in doppelten u Anf¨hrungsstrichen geschriebenen Strings Variablen ersetzt. daß eine Referenz auch als solche behandelt wird? In PHP gibt es daf¨r spezielle Syntax. mittels einer return-Anweisung die lokale a u o Referenz zur¨ckzugeben und der urspr¨nglichen Objektvariable zuzuweisen. String): Es wird eine Kopie des urspr¨nglichen Datums.1. funktioniert dies nicht. erfolgt dies bei PHP standardm¨ßig nur auf der Referenzkopie. muß man quasi den Umweg“ ” uber das Objekt bzw.vs. mit NULL) uberschreiben. die a a lokal in der Methode sichtbar ist. Ist einer dieser Parameter ein Objekt.2 Ausweg aus dem Referenzdilemma Wie also kann man sicherstellen.2. Das gilt aber nur f¨r solche u u Variablen. einer Klasse aufzurufen. W¨hrend Java innerhalb einer aufgerufenen Methode n¨ma a a lich tats¨chlich das Attribut sowohl der ubergebenen als auch der urspr¨nglichen Referenz a u ¨ auf das Objekt ¨ndert. deren Namen nur aus Buchstaben bestehen. das Objekt selbst darstellt). beginnt man mit dem f¨r PHP tyu pischen Dollarzeichen. diese erlaubt das – Parameter ubergeben.2. den Wert eines Objekt-Attributes zu ¨ndern. Grunds¨tzlich ist es nat¨rlich immer m¨glich. wo man ein Objekt betrachtet. denn PHP muß schließlich wissen. 20. Steht hinter dem Pfeil auch ein Dollar. Call by reference“ ” ” Jens Hatlak Seite 204 . es aber nicht selbst darstellt. erzeugt und ubergeben. bei der das Kaufmanns-Und den Referenz-Charakter u einer Zuweisung oder einer Variablen-Betrachtung anzeigt: 5 6 7 Im gesamten Ausdruck also nur ganz vorne ein Dollarzeichen. Objektorientierung in PHP Objekte und Referenzierung in PHP 20. Auch in u ¨ Java. da sie notwendigerweise den Strichpfeil enthalten. einem Strichpfeil (->) und dem Namen des Attributs bzw. Insbesondere werden Referenzen nicht erkannt. man spricht daher auch von Call by value“ bzw. wird dieser Teil als variabel aufgefaßt und zuerst ersetzt! Eine implizite Referenzierung ohne Angabe eines Objekts wie in Java gibt es in PHP nicht.1 Kopier. kann folglich keine Methode das urspr¨ngliche Objekt (z. Referenzsemantik zum Einsatz kommt7 . wessen Methode ¨ aufgerufen werden soll (unterschiedliche Klassen k¨nnen nat¨rlich Methoden mit genau o u demselben Namen definieren!). Will man also Attribute oder Methoden referenzieren.1 Referenzierung Um eine Methode eines Objekts bzw.2. Hier ist also ein Unterbrechen des Strings unter Zuhilfenahme des Punkt-Stringoperators geboten. so findet in PHP bei der Ubergabe dasselbe Vorgehen statt wie bei gew¨hnlichen o Primitivtypen (Integer. genauer: eine Referenz auf ein ¨ ¨ Objekt. der Methode5 . u u 20. Da eine Referenz auf ¨ ein Objekt ja immer nur das Objekt bezeichnet. Der Unterschied zwischen Java und PHP in der Behandlung von Objekten kommt erst dann zum Tragen.

daß alle drei Variablen den Wert 42 annehmen. Die letzte Anweisung a bewirkt folglich. $ d s p = new DSP_CR (). Auch bei Funktions. ”\ n ”.20. Die Ausgabe obigen Codes ist nat¨rlich 41. die implizit gemeint sein k¨nnte. // m i t K o p i e r s e m a n t i k foreach ( $ m y c a r s as $ o b j e c t c o p y ) echo $ o b j e c t c o p y -> farbe .19 beschrieben. $ m y c a r s = array ( $ c a r . um auf das Original-Objekt u zuzugreifen: $ c a r = new Auto (). a ¨ das ist hier aber nicht gemeint Jens Hatlak Seite 205 . In Java w¨re das nicht so offensichtlich. nur den jeweiligen Arrayu u Schl¨ssel in Erfahrung zu bringen und diesen zu nutzen. $ c = 42.3 foreach mit Objektreferenzen Wie bereits im foreach-Kapitel 8. // R e f e r e n z s e m a n t i k I foreach ( $ m y c a r s as $ k e y => $ o b j e c t ) 8 Dieser Begriff beschreibt zwar auch das. Objektorientierung in PHP Objekte und Referenzierung in PHP $a = & $b . stellt man hierbei bei einer Funktions/Methodendefinition einer zu referenzierenden Parameter-Variablen ein Kaufmanns-Und voran: function Plus ( $ v a r ) { $ v a r ++.und Methodenaufrufen wird normalerweise Kopiersemantik angewandt. Die beiden obigen Zuweisung bewirken gleichermaßen. } $ v a r = 42.2 findet sich noch eine Ubung zu komplexeren Anwendungen der Referenzsemantik. Minus ( $ v a r ). sondern auch eine Wert¨nderung einer der Variablen automaa tisch die exakt selbe Wert¨nderung der anderen Variablen bewirkt.1. eine Klassena a variable namens var existieren k¨nnte. daß jeweils beide Variablen nicht nur denselben Wert haben. Plus ( $ v a r ). Hat man nun ein Array von Objektreferenzen. $ c =& $a .2. was sich von einem Schleifendurchlauf zum n¨chsten andert. benutzt diese Schleifenvariante8 stets Kopien der Arrayinhalte. 20.2. da hier u. $ d s p ). Um explizit Referenzsemantik zu fordern. ¨ Unter 20. da nur die Funktion Minus den Wert der u Variablen $var ¨ndert. U. echo $ v a r . In PHP m¨ßte o o u man dann aber $this->var schreiben. Deshalb macht es hier Sinn.7. } function Minus (& $ v a r ) { $ v a r --. kann dies leicht zu unerw¨nschten Effekten f¨hren.

auf Attribute nur per o a o Getter.1 static Manchmal ist es n¨tig. kommt folgende Syntax zum Einsatz: Jens Hatlak Seite 206 . zugreifen darf. } . in der sie sich befindet.. o 20. Beispiel: Angenommen. ”\ n ”.3.2 parent Im Falle von Zugriffen auf geerbte. was das nachtr¨gliche Vornehmen von Anderungen a z. Lokale und globale Variablen d¨rfen dagegen nat¨rlich benutzt u u werden.3.und Settermethoden zuzugreifen. ohne ein Objekt derselben o erzeugt zu haben. 20. Außerdem sollte man sich grunds¨tzlich angew¨hnen. Das ist in PHP4 auch gar kein Problem. eine Methode einer Klasse aufzurufen.. Ein primitives Beispiel: class Auto { . wir h¨tten in der Klasse DSP_CR die Methode lenke(drehung) a der Klasse Auto uberschrieben. daß eine so aufgerufene Klassenmethode“ nirgends auf die Attribute ” der Klasse. ”\ n ”. weil die Klasse Auto außer dem Konstruktor keine bekannten Methoden hat. } echo Auto :: Erfinder (). function Erfinder () { return ” E t i e n n e L e n o i r . in PHP5 wird das je nach Sichtbarkeitsdefinition aber nicht mehr m¨glich sein. auch erst nachtr¨glich) a geeignete Plausibilit¨tstests gemacht und diese bei Bedarf in erbenden Klassen uberschriea ¨ ben werden k¨nnen. von der DSP_CR erbt.20. C a r l Benz ”. Objektorientierung in PHP Methoden-Aufrufe echo $ m y c a r s [ $ k e y ]-> farbe . stark erleichtert. Will man nun innerhalb von DSP_CR ¨ auf die gleichnamige Methode der Basisklasse Auto zugreifen.. aber uberschriebene Methoden sollte man statt des ¨ Klassennamens das Schl¨sselwort parent benutzen.. Zu ” beachten ist dabei. In diesem Fall kann man einen sogenannten static“-Aufruf machen.3 Methoden-Aufrufe 20. // R e f e r e n z s e m a n t i k I I foreach ( array_keys ( $ m y c a r s ) as $ k e y ) echo $ m y c a r s [ $ k e y ]-> farbe . In diesem Beispiel habe ich direkt auf die Klassenvariable $farbe zugegriffen. da diese ja nur im Kontext einer Instanz (Objekt) vorhanden sind. Außerdem wird dadurch auch der Unterschied zwischen static“ ” (kein Objekt vorhanden) und normalem Instanz-Methodenaufruf deutlich. da in diesen dann (ggf. Dadurch taucht der Name der beerbu ¨ ten Klasse nur hinter extends auf. T.

. // Methode d e r B a s i s k l a s s e a u f r u f e n parent :: lenke ( $ d r e h u n g ). /∗ ∗ ∗ Konstruktor ∗ @param $farbe gewunschte Farbe ¨ ∗/ function Auto ( $ f a r b e ) { $ t h i s -> farbe = $ f a r b e .4 Das fertige Beispiel /∗ ∗ ∗ Auto K l a s s e ∗ ∗ @ a u t h o r DSP ∗ @version 1 . 20. 0 ∗/ class Auto { /∗ ∗ ∗ Baujahr ∗ @type i n t ∗/ var $ b a u j a h r . } /∗ ∗ ¨ ∗ Andert d i e Wagenfarbe ∗ @param $ f a r b e gewunschte Farbe ¨ ∗/ Jens Hatlak Seite 207 . /∗ ∗ ∗ Farbe ∗ @type s t r i n g ∗/ var $ f a r b e .. $ t h i s -> baujahr = date (). } . function lenke ( $ d r e h u n g ) { // S e r v o a k t i v i e r e n $ d r e h u n g = $ t h i s -> servo ( $ d r e h u n g ).20.. Objektorientierung in PHP Das fertige Beispiel ..

kann man auch folgende Syntax verwenden. parent :: Auto ( $ f a r b e ). Objektorientierung in PHP Das fertige Beispiel function setzeFarbe ( $ f a r b e ) { $ t h i s -> farbe = $ f a r b e . } Jens Hatlak Seite 208 . } } Alternativ zum letzten Codeteil. die unabh¨ngig vom Namen der Baa sisklasse ist . ∗/ function DSP_CR ( $ f a r b e ) { if ( empty ( $ f a r b e )) $ f a r b e = ” m e t a l l i c ”. class A extends B { function A ( $param ) { $ p a r e n t = get_parent_class ( $ t h i s ).in Java w¨rde man das ubrigens mit einem einfachen super(parameter) u ¨ machen. 0 ∗/ class DSP_CR extends Auto { /∗ ∗ ∗ Konstruktor ∗ e i g e n t l i c h w¨ re g a r k e i n e r n o t w e n d i g . . $ t h i s -> $ p a r e n t ( $param ). in dem der Konstruktor der Basisklasse aufgerufen wird.20. . } } /∗ ∗ ∗ DSP CR K l a s s e ∗ Konstruktor der B a s i s k l a s s e wird i m p l i z i t aufgerufen ∗ ∗ @ a u t h o r DSP ∗ @version 1 . } /∗ ∗ ∗ Welches Baujahr ? ∗ ∗ @ r e t u r n Das B a u j a h r ∗ @returns s t r i n g ∗/ function Baujahr () { return $ t h i s -> baujahr . a ∗ aber wir w o l l e n j a d i e Farbe i n i t i a l i s i e r e n .

final beschreibt nicht in u erbenden Klassen uberschreibbare Methoden bzw. also z.. $myObject->__clone(). B. sondern auch bei Parameter¨bergaben an Funktionen und Methoden! u Implementieren. die immer dann automatisch aufgerufen werden. das bewirkt. im Unterschied dazu wird einfach ein neues Schl¨sselwort u eingef¨hrt. welche Funktionalit¨t a (Methoden) eine Klasse. Diese neue Spezialmethode erm¨glicht aber z. heißt in diesem Zusammenhang genau das Beschriebene Richtig. z. wer darauf von wo zugreifen darf. wenn u die letzte Referenz auf ein Objekt gel¨scht wird. womit der Konstruktor der a Basisklasse mittels parent::__construct() eindeutig bestimmt ist. Nat¨rlich ist die neue Zend-Engine auch a u um einiges schneller. Analog dazu heißen die neu eingef¨hrten Destruktoren. Auch von Java bekannt sind abstrakte Klassen und Interfaces. also einerseits nichtinstanzierbare Klassen mit Methoden. Wem das Java vorkommt. u a Mit PHP5 kann man Attribute und Methoden als public. daß $this nicht verwendet werden darf). Eine echte Kopie stellt man dann mittels der nun jeder Klasse inh¨rent zugeh¨rigen magic“ Methode __clone a o ” her. dem Absturz der PHP-Engine).20. auch hier l¨ßt wieder Java gr¨ßen! :-) a u Jens Hatlak Seite 209 . engl. Wen wundert’s noch. __destruct. Konstruktoren heißen jetzt standardm¨ßig __construct. dem a werden auch static und final sowie const etwas sagen: Ersteres ist vom Prinzip her weiter oben beschrieben (20. das sind behandelbare Laufzeitfehler im Unterschied zu nicht abfangbaren. Attribute und const konnte man bisher ¨ mittels define() simulieren: konstante. der kann nun auch ganz explizit die erwarteten Klassenzugeh¨rigkeiten vor die Variablen im Parameterteil von Methodendeklarationen schreiben.3. Schließlich gibt es nun auch ein ausgekl¨geltes System zum Abfangen von Exceptions u (Ausnahmen. die ein bestimmtes Interface implementiert 10 . daß sie Objekte grunds¨tzlich o a mit Referenz-Semantik behandelt9 statt wie bisher standardm¨ßig mit Kopiersemantik a (wie es bei Primitivtypen wie integer auch weiterhin der Fall ist). daß sich dieses try-catch nennt?11 Wem PHPDoc nicht genug ist.. o also z. also nach dem Setzen nicht mehr ver¨nderbare a Instanzvariablen. bieten muß. die definieren. die von erbenden Klassen uberschrieben werden mus¨ ¨ sen und andererseits Schnittstellenbeschreibungen. Neu ist auch die Unterst¨tzung eines der zentralen Grunds¨tze der OOP: Sichtbarkeit.1. aber ihr gr¨ßter Vorteil ist sicherlich. private oder protected deklarieren und damit einschr¨nken. o Debuginformationen sammeln oder Datenbankverbindungen sauber beenden. 9 10 11 Also nicht nur bei Zuweisungen.5 Ausblick: PHP5 Mit PHP 5 bricht ein neues Zeitalter f¨r die Skriptsprache an. Objektorientierung in PHP Ausblick: PHP5 } 20. B. Endlich halten die zenu tralen Bestandteile der OOP Einzug und erm¨glichen es damit. B. o auch das gleichzeitige.: . function setMetallic ( Auto $ c a r ) { $ c a r -> setzeFarbe ( ” m e t a l l i c ”). B. B. to implement. auch in dieser Sprache o tats¨chlich objektorientiert zu programmieren. Mit ihnen kann man z. teilweise Modifizieren der Kopie.

wird eine Fehlermeldung ausgegeben.20. die von Auto oder einer davon u erbenden Klasse (z. wird sicherlich is_a und Konsorten bem¨ht haben. Die neue __autoload() Funktion erleichtert das Einbinden von Klassen. ¨ Nett ist auch. Zu den weiteren Neuerungen in PHP5 z¨hlen die rundum erneuerte XML-Unterst¨tzung a u (libxml2-basiert). Mit PHP5 u gibt es nun ganz analog zu Java die Infix-Notation instanceof. sprich gequotet). } } MyTest ()-> print (). Wer schon einmal herausfinden wollte. wo sich die Geister scheiden und Lager bilden – OOP-pur-Verfechter auf der einen und PHP3-Hacker auf der anderen Seite . u sprich dereferenziert. function __construct () { $ t h i s -> test = ” 4 2 i s t h e a n s w e r . Bleibt noch anzumerken. SQLite-Integration (daf¨r ist MySQL-Support nicht mehr direkt eingeu baut) sowie verbesserte Handhabung von Streams12 .. Die Setter-Funktionen werden dabei konsequenterweise nicht nur bei Zuweisungen. Mit ihrer Hilfe kann man z. } function print () { echo $ t h i s -> test . .. 12 Wobei diese sicher trotzdem keine so zentrale Rolle spielen werden wie etwa in C++ Jens Hatlak Seite 210 . die dasselbe erm¨glicht o (im Gegensatz zu is_a wird der Klassenname aber nicht als PHP-String aufgefaßt. werden k¨nnen. In PHP4 muß der R¨ckgabewert eines Funktionso u aufrufs immer erst in einer (Objekt-) Variablen abgespeichert werden... leichten Anpassungen auch unter PHP5 laufen.. sondern auch auch beim Inkrementieren und Dekrementieren aufgerufen. class MyTest { var $ t e s t . indem sie immer dann automatisch aufgerufen wird. __get ¨ und __set). u a PHP4-Skripts sollten mit evtl. Diese Methode w¨rde also alle Objekte akzeptieren. B. Falls ein Objekt von anderem Typ oder gar ein Primitivtyp ubergeben wird. vom Namen der Klasse abh¨ngig verschiedene includes definieren. Beispiel f¨r die neue Freiheit: u . daß nun von Methoden zur¨ckgelieferte Objekte direkt angesprochen. Methodenaufrufe sowie das o Setzen und Abfragen von Variablen zu uberschreiben (mittels Methoden __call. Das ist wohl der Punkt. ”. sonst ist das ja trivial). d. . Mit diesen Eigenschaften eignen sich diese Funktionen nat¨rlich besonders gut zum sauberen u Debuggen. wenn eine Klasse nicht gefunden wird. . daß all dies r¨ckw¨rtskompatibel implementiert wurde. DSP CR) instanziert worden sind. B. a Ganz besonders schick ist die extra geschaffene M¨glichkeit.. von welcher Klasse ein Objekt ist (zur Laufzeit. Objektorientierung in PHP Ausblick: PHP5 } . h. auf die man dann weitere Aufrufe anwenden kann.

daß man Subjekte. B. dort gibt es ein Liste aller a Image-Funktionen samt Syntax.1 OOP Das Beispiel aus Abschnitt 18. Objektorientierung in PHP Konzeptionelle Beispiele Wer sich selbst ein Bild machen will.net/ zend-engine-2. Leite von dieser Klasse eine neue namens Point“ab mit der Methode set(x. php ansehen.20. f¨llt es leicht. kann diese gerne an Christoph schicken. die einen Punkt malt. Lese. Die Eigenschaften des Subjekts setzt o man der OO-Logik folgend in Form von Attributen (Klassenvariablen) um.4. diese sind aber intern u o und k¨nnten daher .private‘ bzw. Und nun mein Ansatz: Als erstes sollte man das Problem auf die zentrale Funktionalit¨t reduzieren. aber vielleicht helfen dir ja die folgenden Beispiele aus o meiner Programmiererfahrung. Rectangle“ (Rechteck) als Erben von Point“ sowie die Klasse ” ” ” Square“ (Quadrat).und ¨ Schreibzugriff f¨r die Eigenschaften und einige zus¨tzliche Funktionen n¨tig. die Schnittstelle der sp¨teren Klasse. Dar¨ber a o u hinaus werden nat¨rlich meist noch weitere Funktionen ben¨tigt. Folgende Aufgabe ist zu l¨sen: o Schreibe eine Klasse Image“. die Rectangle“ erweitert. denn diese a bildet i. eigenst¨ndige Prozesse wie Datei-Ein-/Ausgabe oder die jeweils zentrale Infora mationseinheit. Es folgen einige Beispiele – wer a noch Anschauliches hat. daß man in erster Linie die Funktionalit¨t in eine Klasse steckt.7. um das jeweilige Symbol auszugeben. Schließlich muß man sich noch uber die Schnittstelle Gedanken machen – i.-) ¨ 20. .php. 13 14 Siehe auch die unten folgenden Beispiele Sp¨testens hier solltest du einen Blick in das offizielle PHP-Manual werfen. also die ben¨tigten Funktionen. o Zu beachten ist auch. B. die allesamt u a o als Methoden der Klasse implementiert werden. A. um OOP verstehen zu lernen. .1 bietet sich an. Eine generell optimale ” L¨sung gibt es wie immer nicht.7 Ubung 20. deren Daten z. wie man eine Prou blemstellung am besten abstrahiert und objektorientiert“ denkt. In der Programmierpraxis sind das z. A. Erstelle von jeder malf¨higen Klasse ein a ” ” Objekt und benutze es jeweils.protected‘ deklariert werden. diese Subjekte mit Objekten zu assozia ieren. Zuerst jedoch die Methode.6 Konzeptionelle Beispiele F¨r Neulinge der Objektorientierung stellt sich anfangs oft die Frage. also Teile des Ganzen mit individuellen Eigenschaften. identifizieren kann. in einer Datenbank festgehalten werden13 . sollte sich mal http:// www. y). die Christoph bevorzugt: Man abstrahiert von der Problemstellung soweit. der sich mit Objektorientierung in PHP mindestens so gut auskennt wie ich. die zu einer zu erstellenden Klasse geh¨ren. die mit Hilfe der PHP-Image-Funktionen14 ein leeres Bild ” erzeugt und die Methode show() implementiert. Hat man diese Abstraktion erst einmal geschafft. Programmiere schließlich die ” Klassen Circle“ (Kreis). Jens Hatlak Seite 211 . 20. sind Konstruktor. a die gemeinsame Daten (die sp¨teren Attribute) verwendet.

20.1: IMAP-Webmail-System Gemeinsame Daten zus¨tzlich zu Webmail (Vererbung!) a • Newsgroupdaten Zentrale Funktionalit¨t a zus¨tzlich zu Webmail (Vererbung!) a • Newsgroup-Liste ausgeben • Newsgroup wechseln • Mail verschicken • Mail(s) l¨schen o • Meldungen/Fehler ausgeben Tabelle 20.2: IMAP-Webnews-System Jens Hatlak Seite 212 . Objektorientierung in PHP ¨ Ubung Gemeinsame Daten • IMAP-Session/Mailbox • ID der aktuellen Nachricht • String mit Meldungen • Sortierungsdaten • Anzahl Nachrichten in der Mailbox Zentrale Funktionalit¨t a ¨ • Mailbox-Ubersicht ausgeben – einzelne Daten aus den Mail-Headern lesen – Sortierung ¨ndern a • einzelne Mail lesen – einzelne Daten aus den Mail-Headern lesen – Umbruch/Formatierung • Mail verschicken • Mail(s) l¨schen o • Attachmentmanagement • Meldungen/Fehler ausgeben Tabelle 20.

4: Mehrbenutzer-Bookmarkverwaltung Jens Hatlak Seite 213 .3: Mehrbenutzer-Adreßbuch Gemeinsame Daten • Benutzer • String mit Meldungen Zentrale Funktionalit¨t a • Bookmarks hinzuf¨gen u • Bookmarks aktualisieren • Bookmarks l¨schen o • Bookmarkauswahlliste • Gruppennamen ¨ndern a • Gruppen l¨schen o • Gruppenauswahlliste • Anzeige/Ausgabe Tabelle 20.20. Objektorientierung in PHP ¨ Ubung Gemeinsame Daten • Benutzer • String mit Meldungen Zentrale Funktionalit¨t a • Adressen hinzuf¨gen u • Adressen aktualisieren • Adressen l¨schen o • Adressauswahlliste • Suchfunktion • Adreßliste • Ausf¨hrliche Anzeige u • Schnittstelle zu Webmail • Exportm¨glichkeit o Tabelle 20.

$ t e s t -> setVar (0). die die besonderen Erfordernisse der ” Verwendung von Referenzen schlicht ignoriert und damit sicher nicht das Gew¨nschte u leistet. } function setVar ( $ v a r ) { $ t h i s -> var = $ v a r . o o 20. $ a r r a y ) { $ t h i s -> var = $ v a r . B. z. kann man aber auch in PHP 4 so programmieren. h. } } $ a r r a y = new MyArray (). daß a ¨ Referenzen auch als solche behandelt werden. 15 Mit PHP 5 wird standardm¨ßige Referenzsemantik f¨r Objekte eingef¨hrt.2 Referenzsemantik Wenn man von anderen objektorientierten Sprachen wie Java her gewohnt ist. wenn pro Zeile maximal ein Zeichen (welches wohl?) hinzugef¨gt wird. welches eine korrekte Implementierung erzeugen w¨rde – und deine L¨sung ist das doch hoffentlich.7. function Test ( $ v a r .15 Wie sich zeigt. Vorgegeben ist folgende naive“ Implementierung. also das. In dieser Ubung soll deshalb eine bestehende Implementierung derart abge¨ndert werden. $ t e s t 2 -> getVar (). d.Referenzsemantik anzuwenden. oder? :-) u o Hinweis: Eine korrekte Implementierung kann schon erreicht werden. $ t e s t = new Test (42. echo $ t e s t -> getVar (). u class MyArray { var $ a r r a y . so daß sich dann das a u u folgende zumindest teilweise er¨brigt u Jens Hatlak Seite 214 . daß sie alle Referenzen auch als solche a behandelt. bestimmte Dinge mit Referenzen machen zu k¨nnen. $ a r r a y -> add ( $ t h i s ). Außerdem steht unten noch das erwartete Ergebnis. Objektorientierung in PHP ¨ Ubung Eine m¨gliche L¨sung findet sich in Abschnitt B. $test2 = $test . } } class Test { var $ v a r . wird man von PHP 4 zumindest anfangs o entt¨uscht sein. bei Zuweisungen statt Kopier. function MyArray () {} function add ( $ v a l ) { $ t h i s -> array [] = $ v a l .9.20. ”\ n ”. } function getVar () { return $ t h i s -> var . ” ”. $ a r r a y ).

20. Bei falscher Implementierung (wie hier) wird ” statt dessen 0 42“ ausgegeben. Objektorientierung in PHP ¨ Ubung var_dump ( $ a r r a y ). o o Jens Hatlak Seite 215 . Das Beispiel soll zuerst 0 0“ ausgeben. object(myarray)(1) { ["array"]=> array(1) { [0]=> &object(test)(1) { ["var"]=> int(0) } } } Eine m¨gliche L¨sung findet sich in Kapitel B. daß tata ” s¨chlich eine Referenz auf das Objekt $test im Array $array abgelegt wurde. Der Variablen-Dump schließlich soll best¨tigen. Ist dies nicht a der Fall.10. ist der Wert der Variablen var 42 statt 0 und es steht dann kein Kaufmanns-Und vor object.

Teil VII PHP Erweitert David Peter Seite 216 .

ohne dabei den Bezug zum jeweiligen Benutzer bzw.form=fakeentry" 1 2 3 4 5 F¨r komplexere Systeme gibt es zudem die M¨glichkeit.: Sitzung) bezeichnet man alle Daten.ini richtig eingestellt hat: url_rewriter.frame=src. was er normalerweise wieder mit Cookies macht – ein Teufelskreis. denn der Server kann bei einer normalen Anfrage nicht herausfinden. welche gespeicherte Session er dem Client zuweisen soll. B. ” einem personalisierten System) w¨hrend dem Verweilen eines Benutzers auf derselben a bekannt sind.tags = "a=href. . sondern auf dem Server gespeichert. Session-ID zur Identifikation ¨ selbst speichern.1 Technisch kann man sich die uber einen Nutzer bekannten Daten als einen serverseitigen ¨ ” 2“ vorstellen. Mehr dazu weiter unten. Die Chance. indem verschiedene u o Sessionnamen vergeben werden. .1 Was sind Sessions? Mit Session“ (engl. Cookies sind Variablen mit Werten.input=src. Das klingt nat¨rlich erstmal fantastisch.21 Sessions 21. Manche Browser (oder deren User) nehmen keine Cookies an Die Session-ID ist ein md5-verschl¨sselter Zufallswert. wenn man die entsprechenden ¨ Stellen in der Konfigurationsdatei php. die Session-ID per URL o weiterzugeben. Verschiedene Benutzer werden somit auch durch verschiedene Sessions identifiziert. Es gibt auch die M¨glichkeit. da man sich so keine Gedanken u uber Browser-spezifische Probleme3 machen m¨ßte.php?PHPSESSID=edb0e8zz5et4e9042fe0176a89cbde16 Einen Teil dieser Arbeit kann PHP selbst ubernehmen. Sessions zu gruppieren.area=href. Doch gleich die schlechte Nachricht: u ¨ So einfach funktioniert das nicht. Die Daten k¨nnen uber einzelne Seiten hinweg benutzt und manipuo Cookie ¨ liert werden. Es muß dabei – egal ob POST. das muß aber nicht immer so sein ” David Peter Seite 217 . Keine Arme. die zwischen Server und Client (Browser) ausgetauscht werden. Abrufer zu verlieren. die dem Server einer Site (z.oder GET-Anfrage – die 32-stellige ID4 immer ubergeben werden. Deswegen muß diese Aufgabe wiederum der Client ubernehmen: Er muß eine sog. keine Kekse . ihn zu erraten. Das passiert bei einer POST-Anfrage (Formular) uber versteckte ¨ ¨ Felder5 : <form> <input type="hidden" name="PHPSESSID" value="edb0e8zz5et4e9042fe0176a89cbde16" /> </form> und bei GET uber die URL: ¨ index. Sie werden aber – im Gegensatz zum normalen Cookie – nicht beim Client. ist 1 : 2128 u Im Beispiel heißt die Session PHPSESSID“.

bei Nicht-UNIX-Systemen6 noch angepaßt werden: session. ”<b r /> ”.save_path = c:\temp\ 21.2 Praxis 21. 6 Standard: /tmp/ David Peter Seite 218 . <frame>. <input> und <form> selbst einzutragen.php <? php session_start ().2. ” a r r a y ”).index2. Sessions Praxis Dies veranlaßt PHP dazu.21.2.index. $ SESSION [ ’ i n t e g e r ’ ]. ”Wert2 ”). php ”> Weiter zu Index2 </ a > </ body > </ html > 21. ” i n t e g e r ”. Außerdem muß der Pfad. die entsprechenden Erweiterungen bei den HTML-Tags <a>. print ” I n t e g e r : ”. $ SESSION [ ’ s t r i n g ’ ]. ”<b r /> ”. $ s t r i n g = ” T e s t ”. unter dem die Sessions auf dem Server gespeichert werden sollen.php <? php session_start (). $ a r r a y = array ( ”Wert1 ”. ?> < html > < head > < title > Beginn </ title > </ head > < body > < a href = ” i n d e x 2 . session_register ( ” s t r i n g ”.1 Datei 1 . $ i n t e g e r = 1. <area>.2 Datei 2 . ?> < html > < head > < title > Beginn </ title > </ head > < body > < pre > <? php print ” S t r i n g : ”.

die den Namen als String zur¨ckgibt8 . so wird zuerst eine Session durch session_start gestartet. ”0 ”). Das gleiche gilt f¨r die u u Session-ID. was nicht unbedingt vorteilhaft ¨ ist. Danach f¨llen wir 3 Variablen mit verschiedenen Werten. . < / a> ’ . benutzen wir die Funktion session_name(). // I n d e r S e s s i o n g e s p e i c h e r t e n Wert v e r ¨ n d e r n a $ SESSION [ ’ i n t e g e r ’ ]++. php?% s=%s ”> W e i t e r .. die Session-ID manuell weiterzugeben. . sondern uberlassen diese Aufgabe PHP. m¨ssen wir diese Aufgabe selbst ubernehmen und an jeden u ¨ Link in der HTML-Ausgabe den String ?SESSION-NAME =SESSION-ID“ anh¨ngen. die Session-ID als Cookie zu speichern und gleichzeitig teilweise die ID der URL hinzuf¨gt. Wenn wir eine Cookie-unabh¨ngige Seiu a te programmieren wollen. Beispiel: <? php // U n t e r b i n d e n von C o o k i e s : ini_set ( ” s e s s i o n . da PHP den Browser dazu veranlaßt. . Ein solcher Aufruf muß logischerweise immer vor dem ersten Benutzen/Manipulieren der Session gemacht werden. Seite aufruft.. // Da w i r d i e S e s s i o n−ID a u t o m a t i s c h a n f u g e n . t a g s ”. hier verwenden wir die Funktion session_id() oder alternativ die Konstante SID. ” ”).21. Sessions Praxis print ” Array :< b r /> ”. bekommt man die eben gespeicherten Werte ¨ angezeigt. php ”> Erneut aufrufen </ a > </ body > </ html > Rufen wir die Datei index. ¨ // muß PHP d i e s e A u f g a b e n i c h t mehr u bernehmen : ¨ ini_set ( ” u r l r e w r i t e r . indem man derselben Funktion einen String als Parameter uber¨ gibt. Wenn wir sichergehen wollen. ?> 7 8 Nimmt beliebig viele Parameter entgegen Setzen kann man den Sessionnamen. u s e c o o k i e s ”. a ” Der Standard-Sessionname ist PHPSESSID.php auf. David Peter Seite 219 . die dann durch u session_register 7 f¨r die Session registriert (also gespeichert) werden. Wir haben in diesem Fall keinen Versuch unternommen. session_id () ). print_r ( $ SESSION [ ’ a r r a y ’ ]). Wenn man dau nach uber den Link die 2. session_name (). printf ( ’ <a h r e f =”i n d e x 2 . ?> </ pre > < a href = ” i n d e x 2 .

wie man sie u oft in Onlineshops sieht. diese wieder zu entfernen.3. php ? l o g o u t=t r u e ”).php Irgendwann will man eine Session auch mal beenden. <? php ini_set ( ” s e s s i o n .. startet sie auch die Session und registriert die Variable warenkorb als Session-Variable. session_register ( ’ w a r e n k o r b ’ ).2.3 Logout .21. 21. .).php enth¨lt ein Array9 mit verf¨gbaren Produkten. Aufzurufen per Link: < a href = ” l o g o u t . unset ( $mySessVar1 . u s e c o o k i e s ”. ini_set ( ” u r l r e w r i t e r . ¨ o • Ubersicht der bereits bestellten Produkte mit der M¨glichkeit. ”0 ”). Das geht so: session_unset (). // j e t z t s i n d d i e V a r i a b l e n auch l o k a l n i c h t mehr d e f i n i e r t header ( ” L o c a t i o n : i n d e x . session_start ()..1 Waren Die Datei waren. ” ”). $waren = array ( ’ 1 ’ => array ( 9 Bei einem richtigen Onlineshop w¨rden die Produkte mit Sicherheit aus einer Datenbank kommen u David Peter Seite 220 .logout. Unser Warenkorb soll so einfach wie m¨glich sein: o ¨ o • Ubersichtsseite mit Produkten. Sessions Beispiel Warenkorb 21. die uber einen Link bestellt werden k¨nnen und ¨ dadurch in den Warenkorb gelegt werden. php ”> < input type = ” s u b m i t ” value = ” L o g o ut ”> </ form > 21. $mySessVar2 . Da diese Seite von a u allen anderen eingebunden wird. session_destroy (). php ”> Logout </ a > oder Button: < form action = ” l o g o u t . t a g s ”. exit .3 Beispiel Warenkorb Ein gutes Beispiel f¨r den Gebrauch von Sessions ist eine Warenkorbfunktion.

3.90. SID David Peter Seite 221 .php soll einen Uberblick uber die angebotenen Produkte liefern. ’2’ ’ ’ ’ ). htmlentities ( $ p r o d u k t [ ’ t e x t ’ ]). php ? i d=%d&%s ”> B e s t e l l e n </a> </p> ’ . $ p r o d u k t [ ’ t i t e l ’ ]. $ p r o d u k t [ ’ p r e i s ’ ]. ’ ¨ ist . ’ t e x t ’ => ’ Das S t a n d a r d w e r k zum Thema Datenbank .90.2 Ubersicht ¨ Die Seite index. Uber einen a u Entfernen-Link kann man seine bisherige Bestellung außerdem noch korrigieren. ?> < html > < head > < title > Warenkorb </ title > </ head > < body > ¨ 21. was man bereits bestellt hat. Sessions Beispiel Warenkorb ’ t i t e l ’ => ’ DSP T aschenbuch ’ . 2 f </b><b r /> B e s c h r e i b u n g : < b>%s </b><b r /> <a h r e f =”b e s t e l l e n . <? php include_once ( ”waren . ’ ). ’ p r e i s ’ => 9. $id . php ”).90. ¨ p r e i s ’ => 29. ’3’ ’ ’ ’ => array ( t i t e l ’ => ’ DSP a u f CD’ . Wei¨ ¨ ¨ ter unten erh¨lt man einen Uberblick dar¨ber.21. t e x t ’ => ’ Wenn I h n e n d i e D o w n l o a d z e i t zu w e r t v o l l k¨ nnen s i e DSP auch a l s CD b e s t e l l e n . SQL und PHP a l s h a n d l i c h e s Taschenbuch . ’ o => array ( t i t e l ’ => ’ DSP H o r s p i e l ’ . SQL und PHP f u r A n a l p h a b e t e n . t e x t ’ => ’ Das S t a n d a r d w e r k zum Thema Datenbank . ) ). foreach ( $waren as $ i d => $ p r o d u k t ) { printf ( ’ <p> <b>%s </b><b r /> P r e i s : < b>Euro % 0 1 . p r e i s ’ => 19.

21. } print ”</ u l>”. htmlentities ( $waren [ $ i d ][ ’ t i t e l ’ ]). foreach ( $ SESSION [ ’ w a r e n k o r b ’ ] as $ i d ) { printf ( ’ < l i > %s (<a h r e f =”e n t f e r n e n .php legt Produkte in den Warenkorb <? php include_once ( ”waren . } if ( isset ( $ SESSION [ ’ w a r e n k o r b ’ ]) && ! empty ( $ SESSION [ ’ w a r e n k o r b ’ ])) { print ” S i e haben f o l g e n d e Waren b e r e i t s ausgew&auml . SID ). if (! isset ($ GET[ ’ i d ’ ])) { die ( ”Kein P r o d u k t ausgew&auml .3 Bestellen Die Datei bestellen. $ SESSION [ ’ w a r e n k o r b ’ ])) { // I n den Warenkorb l e g e n : $ SESSION [ ’ w a r e n k o r b ’ ][] = $ GET[ ’ i d ’ ]. $id . } ?> </ body > </ html > 21. h l t . . } // Wenn d a s P r o d u k t noch n i c h t g e k a u f t wurde . Sessions Beispiel Warenkorb ). if (! isset ( $ SESSION [ ’ w a r e n k o r b ’ ]) || ! in_array ($ GET[ ’ i d ’ ]. ”). php ”). print ”<u l>”.3. h l t : ”. } ?> <p> David Peter Seite 222 . . php ? i d=%d&%s ”> Entfernen </a>) </ l i > ’ .

} ?> < br /> < a href = ” i n d e x . h l t . ”). . ? > ”> Zur & uuml . gt .21. s c h t . php?<?php p r i n t SID . Sessions Beispiel Warenkorb Das Produkt wurde Ihrem Warenkorb hinzugef & uuml .php kann man schließlich noch einzelne Produkte aus dem Warenkorb l¨schen. $ SESSION [ ’ w a r e n k o r b ’ ])) { print ( ” S i e haben d i e s e s P ro du kt noch n i c h t b e s t e l l t . ? > ”> Zur & uuml . ”.4 Entfernen Mit der Seite entfernen. ck zur Startseite </ a > </ body > </ html > David Peter Seite 223 . ck zur Startseite </ a > </ p > </ body > </ html > 21.< br /> < a href = ” i n d e x . php ”). o <? php include_once ( ”waren . o d e r k e i n P r o d ukt ausgew&auml . php?<?php p r i n t SID . o d e r a // d a s P r o d u k t n i c h t im Warenkorb i s t . } else { foreach ( $ SESSION [ ’ w a r e n k o r b ’ ] as $ i d => $ p r o d u k t ) { if ( $ p r o d u k t == $ GET[ ’ i d ’ ]) { unset ( $ SESSION [ ’ w a r e n k o r b ’ ][ $ i d ]). } } print ”Das P r o d u k t wurde a u s Ihrem Warenkorb g e l&ouml . . // Wenn k e i n P r o d u k t a u s g e w ¨ h l t wurde . if (! isset ($ GET[ ’ i d ’ ]) || ! in_array ($ GET[ ’ i d ’ ].3.

22. wie zum Beispiel Expat (http: o 3 -¨hnlicher. ihre Namen klein schreiben und Attributwerte in doppelte Anf¨hrungszeichen einschließen! u Simple API for XML David Peter Seite 224 . Auf den ersten Blick scheint XML wie eine Weiterentwicklung von HTML.22 XML-Dokumente parsen In diesem Abschnitt geht es um das Parsen von XML-Dokumenten1 22.com/ xml/ ). um strukturierte Daten in einer Textdatei abzulegen.jclark. also alle Tags ¨ ” schließen. Solche u ” Ereignisse k¨nnen sein: o • Startendes Element <abschnitt titel="XML-Dokumente"> • Abschließendes Element </abschnitt> • CDATA (Normaler Text) • PIs (Processing Instructions. // www. Dar¨ber hinaus wurde a a u HTML nach Version 4 in XML umgesetzt und sinngem¨ßerweise in XHTML umgetauft. da es sich a a nur um reine Textdaten handelt.w3. ?> • Kommentare 1 2 3 http:// www.2 a Ein wichtiger Aspekt von XML ist die vollst¨ndige Plattformunabh¨ngigkeit.1 Was ist XML? Die Extensible Markup Language (XML) ist eine Methode. Expat ist ein SAX a Der Ablauf eines Parsevorgangs ist einfach: Es werden zuerst sog. In Wirklichkeit basieren aber sowohl XML als auch HTML auf der zwar m¨chtigeren aber auch sehr schwer verst¨ndlichen Sprache SGML.org/ XML/ In dieser neue Sprach. Handler ( Behandler“) f¨r bestimmte Ereignisse definiert.2 Parsen von XML-Daten Unter PHP gibt es zu diesem Thema elegante L¨sungen.Version“ muß man sich ubrigens strikt an die XML-Regeln halten. ereignisorientierter XML-Parser. Verarbeitungs-Instruktionen) <?php echo "hello world!".

3. 22. </ abschnitt > < abschnitt titel = ” B e i s p i e l e ”> < index keyword = ” b e i s p i e l e ” /> Wie im < ref id = ” e x p a t ”>1.. David Peter Seite 225 .3. so ruft er die passende.2 Das PHP-Skript // Z u e r s t d e f i n i e r e n w i r d i e F u n k t i o n e n . Abschnitt </ ref > gezeigt . XML-Dokumente parsen Beispiel 1 <!-.eXpat-abschnitt-Ende --> • DTD-Tags <![CDATA[ (\$a <= \$b \&\& \$a >= \$c) ]]> Findet der Parser ein startendes Element. $ a t t s ) { global $html .22. d i e s p ¨ t e r a u f a // d i e d i v e r s e n E r e i g n i s s e r e a g i e r e n s o l l e n /∗ ∗ ∗ Diese Funktion b e h a n d e l t e i n ¨ f f n e n d e s Element ..xml) <? xml version = ” 1 .. vordefinierte Funktion auf und ubergibt dieser den Namen des ¨ Elements(abschnitt) sowie die Attribute (titel = XML-Dokumente). $name . o ∗ A l l e P a r a m e t e r w erden a u t o m a t i s c h vom P a r s e r u b e r g e b e n ¨ ∗ ∗ @param parser Object Parserobjekt ∗ @param name string Name d e s ¨ f f n e n d e n E l e m e n t s o ∗ @param atts array Array m i t A t t r i b u t e n ∗/ function startElement ( $ p a r s e r . .1 Die XML-Datei (tutorial.3 Beispiel 1 22.. 0 ”?> < tutorial titel = ” e x p a t ”> < abschnitt titel = ” E i n f u e h r u n g ”> < index keyword = ” e x p a t ” /> Text . wie <abschnitt titel="XML-Dokumente"> . </ abschnitt > </ tutorial > 22.

break .= ”<h2>”. /∗ ∗ ∗ Diese Funktion b e h a n d e l t e i n a b s c h l i e ß e n d e s Element ∗ A l l e P a r a m e t e r w erden a u t o m a t i s c h vom P a r s e r u b e r g e b e n ¨ ∗ David Peter Seite 226 . – ref: Ein Verweis auf eine gesetzte Referenz wird erstellt.22. – Falls ein anderes Element ubergeben wird. passiert folgendes: o • startElement() wird mit den entsprechenden Parametern aufgerufen. $name . case ” a b s c h n i t t ”. $ a t t s [ ”TITEL ”]. break . ”</h2>”. ¨ // D e s h a l b w a n d e l n w i r s i e m i t s t r t o l o w e r ( ) i n K l e i n− // b u c h s t a b e n um . gibt das Script einen Fehler aus.= ”<h1>”. } } Wenn im XML-Dokument ein ¨ffnendes Element gefunden wird. ¨ • Dabei werden die in $atts gespeicherten Elemente verwendet. XML-Dokumente parsen Beispiel 1 // Die XML−Namen w e rden i n G r o ß b u c h s t a b e n u b e r g e b e n . ”</h1>”. $ a t t s [ ”ID ” ] . a ¨ – abschnitt: Eine kleinere Uberschrift wird erzeugt.= ”<a name=\ ” ” . $ a t t s [ ”TITEL ”]. ”\ ”></a>”. case ” r e f ”: // V e r w e i s a u f e i n e n HTML−Anker : $html . ”>”. ¨ $ e r r o r = ” U n d e f i n i e r t e s Element < ”. welches Element vorliegt u ¨ ¨ – tutorial: Eine Uberschrift wird an das Ausgabe-Dokument($html) angeh¨ngt. – index: Eine HTML-Referenz wird erstellt. switch ( strtolower ( $name )) { case ” t u t o r i a l ”: ¨ // Wir f u g e n d e r g l o b a l e n V a r i a b l e e i n e U b e r s c h r i f t h i n z u : ¨ $html . break . break . $ a t t s [ ”KEYWORD ” ] . case ” i n d e x ”: // Einen HTML−Anker e r z e u g e n : $html . default : // Ein u n g u l t i g e s E l e m e n t i s t vorgekommen . • in der switch()-Schleife wird uberpr¨ft. break . $html .= ”<a h r e f =\ ”# ” . ”\ ”>”. ” i n Z e i l e ” . x m l _ g e t _ c u r r e n t _l i ne _ nu mb e r ( $ p a r s e r )). die ( $ e r r o r .

} } Diese Funktion schließt einen eventuell offenen HTML-Link. } Die Funktion cdata() wird aufgerufen. // Der n o r m a l e T e x t w i r d e i n f a c h an $html a n g e h ¨ n g t : a $html . ” s t a r t E l e m e n t ”. wenn normaler Text im XML-Dokument gefunden wird. In diesem Fall wird dieser einfach an die Ausgabe angeh¨ngt.22. xml_parser_free ( $ p a r s e r ). // P a r s e n xml_parse ( $ p a r s e r . XML-Dokumente parsen Beispiel 1 ∗ @param p a r s e r Object Parserobjekt ∗ @param name string Name d e s s c h l i e ß e n d e n E l e m e n t s ∗/ function endElement ( $ p a r s e r . break . // G i b t a l l e v e r b r a u c h t e n R e s s o u r c e n w i e d e r f r e i . ” e nd E l e m e n t ”). // Der P a r s e r w i r d e r s t e l l t $ p a r s e r = xml_parser_create (). file ( ” t u t o r i a l . xml ”)). switch ( strtolower ( $name )) { case ” r e f ”: // Den HTML−L i n k s c h l i e ß e n : $html . /∗ ∗ ∗ Diese Funktion b e h a n d e l t normalen Text ∗ A l l e P a r a m e t e r w erden a u t o m a t i s c h vom P a r s e r u b e r g e b e n ¨ ∗ ∗ @param parser Object Parserobjekt ∗ @param text string Der T e x t ∗/ function cdata ( $ p a r s e r .= $ t e x t . $ t e x t ) { global $html . // S e t z e n d e r H a n d l e r x m l _ s e t _ e l e m e n t _ h a n d l er ( $ p a r s e r . a // Die XML−D a t e i w i r d i n d i e V a r i a b l e $ x m l F i l e e i n g e l e s e n $ x m l F i l e = implode ( ” ”. $ x m l F i l e ). ” c d a t a ”). $name ) { global $html . // S e t z e n d e s CDATA−H a n d l e r s x m l _ s e t _ c h a r a c t e r _ d a t a _ h a n d l e r ( $ p a r s e r . David Peter Seite 227 .= ”</a>”.

22. u a Und dort verwenden wir wieder ein Entity. wenn man a &amp. Ouml . zum Beispiel bei Codea Beispielen: David Peter Seite 228 . ”> <! ENTITY Ouml ”&amp . (ein ¨) wird zu &amp. &auml.4 Nachteile Das erste Beispiel hat den Nachteil. Zum Beispiel m¨ssen &-Zeichen u immer mit &amp.auml. ”> ]> < tutorial titel = ” e x p a t ”> < abschnitt titel = ” B e i s p i e l e ”> < index keyword = ” b e i s p i e l e ” /> Im normalen Text k & ouml . 0 ”?> <! DOCTYPE tutorial [ <! ENTITY auml ”&amp . gibt das Script einen Fehler aus und zeigt an. Man l¨st dieses Problem meistens o o durch Entities: <? xml version = ” 1 . Also den Ausgangszuo a stand. Und auch ein scharfes S : & szlig . Allerdings hat auch diese Methode ihre Nachteile. erh¨lt man &amp. </ abschnitt > </ tutorial > Dieses Dokument ist etwas kompliziert. & Uuml . Auml . auml . & uuml . Das ist ziemlich l¨stig. wird &auml.. & ouml . XML-Dokumente parsen Nachteile // A u s g a b e d e r g l o b a l e n V a r i a b l e $html . Wenn man das XML-Dokument etwas ab¨ndert und ein fehlerhaftes Element an einer a beliebigen Stelle einf¨gt. nnen wir jetzt Umlaute verwenden : & Auml . in welcher Zeile u das falsche Element gefunden wurde. Uuml . geschrieben werden. daß im Dokument keine Umlaute oder XMLspezifischen Sonderzeichen verwendet werden k¨nnen. ”> <! ENTITY uuml ”&amp .. wiederum aufl¨st. ”> <! ENTITY Auml ”&amp . s z l i g . print $html . 22. uuml . Das ist aber gew¨nscht! Die Ausgabe soll n¨mlich in HTML gewandelt werden. ”> <! ENTITY Uuml ”&amp .auml. ”> <! ENTITY szlig ”&amp . & Ouml . ”> <! ENTITY ouml ”&amp . ouml . & auml .

<! ENTITY Ouml ”&amp . 0 ”?> <! DOCTYPE tutorial [ <! ENTITY auml ”&amp .. Zun¨chst ben¨tigen wir ein neues XML-Dokument: a o <? xml version = ” 1 ... ]]> verwenden: .5 Beispiel 2 Erweitern wir unser Parser-Script. } ]]> </ code > . < tutorial . <! ENTITY uuml ”&amp .. Uuml .& amp . <! ENTITY Auml ”&amp . < code language = ”php ”> <![ CDATA [ if ( $a && $b ) { print ”\ $a und \ $b s i n d n i c h t ’ 0 ’ ”... < tutorial . Außerdem sollen keine globalen Funktionen/Variablen mehr benutzt werden.. XML-Dokumente parsen Beispiel 2 . } </ code > . $b ) { print ”\ $a und \ $b s i n d n i c h t ’ 0 ’ ”.. Es soll jetzt zus¨tzlich auch noch: a • PHP-Code ausf¨hren k¨nnen und u o • Codeabschnitte formatiert darstellen.. ”> ”> ”> ”> ”> ”> David Peter Seite 229 . </ tutorial > In diesem Fall kann man aber auch <![CDATA[ . uuml ... Auml .> . auml . o ¨ 22.. </ tutorial > Das Aufl¨sen von Entities und CDATA-Abschnitten ubernimmt expat. Ouml ..22..> . < code language = ”php ”> if ( $a & amp .... <! ENTITY Uuml ”&amp . ouml . <! ENTITY ouml ”&amp ..

$b = 5. ”> ]> < tutorial titel = ” B o o l e s c h e Werte ”> < abschnitt titel = ” B e i s p i e l e ”> Nachfolgend ein paar Beispiele zu booleschen Abfragen . lt man folgende Ausgabe . if ( $a && $b ) { print ’ $a und $b s i n d n i c h t ”0 ”< b r /> ’ . bleibt uns als einziger Ausweg die Verwendung einer Klasse. XML-Dokumente parsen Beispiel 2 <! ENTITY szlig ”&amp . < code language = ”php ”> <![ CDATA [ $a = 3. // E r s t e l l t e r HTML−Code function TutorialParser ( $ f i l e ) { ¨ // U b e r p r u f e n . class TutorialParser { var $html .22. s z l i g . ren erh & auml . } if ( $a < $b ) { print ’ $a i s t } ?> </ abschnitt > </ tutorial > k l e i n e r a l s $b<b r /> ’ . ob d i e D a t e i v o r h a n d e n i s t : ¨ if (! file_exists ( $ f i l e )) { $ t h i s -> error ( ’ D a t e i ’ . $b = 5. $ f i l e . <? php $a = 3. } if ( $a < $b ) { print ’ $a i s t k l e i n e r a l s $b<b r /> ’ . } ]]> </ code > Beim Ausf & uuml . ’ kann n i c h t g e f u n d e n werden ! ’ ). if ( $a && $b ) { print ’ $a und $b s i n d n i c h t ”0 ”< b r /> ’ . David Peter Seite 230 . Um globale Funktionen/Variablen zu vermeiden.

’ ”> ’ . $a [ ’ i d ’ ]. $a ) { // Wie im e r s t e n B e i s p i e l . $name . ’ c d a t a H a n d l e r ’ ). ’ p i H a n d l e r ’ ). case ’ c o d e ’ : $ t h i s -> html . // S e t z t den H a n d l e r f u r P r o c e s s i n g I n s t r u c t i o n s . ’ </h2> ’ . x m l _ s e t _ e l e m e n t _handler ( $p . case ’ i n d e x ’ : $ t h i s -> html . ’ s t a r t E l e m e n t ’ . $ l i n e ). case ’ r e f ’ : $ t h i s -> html . case ’ a b s c h n i t t ’ .= ’ <a h r e f =”# ’ . xml_parser_free ( $p ). a l l e r d i n g s w i r d d i e K l a s s e n− // V a r i a b l e $html a n s t e l l e d e r g l o b a l e n b e n u t z t . x ml _ pa rs e r_ se t _option ( $p . $ b u f f e r ). } } function startElement ( $ p a r s e r . daß d e r P a r s e r n i c h t g l o b a l e F u n k t i o n e n // a u f r u f t . xml_set_object ( $p . $name . David Peter Seite 231 . s o n d e r n Methoden d i e s e r K l a s s e . break . ’ i n Z e i l e ’ .22. $ t h i s ). $ t h i s -> html . break . ’ . default : $ e r r o r = ’ U n d e f i n i e r t e s Element & l t . // W i c h t i g .= ’ <h1> ’ . $ l i n e = x m l _ g e t _ c ur r en t_ l in e _n u mb e r ( $ p a r s e r ).= ’ <h2> ’ .= ’ <p r e> ’ . x m l _ s e t _ c h a r a c t e r _ d a t a _ h a n d l e r ( $p . xml_parse ( $p . 0). ¨ x m l _ s e t _ p r o c e s s i n g _ i n s t r u c t i o n _ h a n d l e r ( $p . $p = xml_parser_create (). $a [ ’ t i t e l ’ ]. ’ . ’ c l o s e E l e m e n t ’ ). switch ( $name ) { case ’ t u t o r i a l ’ : $ t h i s -> html . ’ &g t . $a [ ’ t i t e l ’ ]. $a [ ’ keyword ’ ]. break . file ( $ f i l e )). XML-Dokumente parsen Beispiel 2 } else { $ b u f f e r = implode ( ’ ’ . break . XML_OPTION_CASE_FOLDING . // Durch d a s S e t z e n d i e s e r O p t i o n werden n i c h t a l l e // E l e m e n t − und A t t r i b u t n a m e n i n G r o ß b u c h s t a b e n // u m g e w a n d e l t . $ t h i s -> error ( $ e r r o r . ’ </h1> ’ .= ’ <a name=”’ . ’ ”></a> ’ . break .

22. d i e // a u s g e f u h r t w erden s o l l . break . // A u s g a b e v e r w e r f e n ob_end_clean (). XML-Dokumente parsen Beispiel 2 } } function closeElement ( $ p a r s e r . } function get () { // G i b t den e r z e u g t e n HTML−Code z u r u c k . d a m i t d i e g e s a m t e // A u s g a b e e i n g e f a n g e n werden kann . } } function cdataHandler ( $ p a r s e r . // ” Einsammeln ” d e r A u s g a b e $ o u t p u t = ob_get_contents (). $name ) { switch ( $name ) { case ’ r e f ’ : $ t h i s -> html . case ’ c o d e ’ : $ t h i s -> html .= ’ </a> ’ . $ c d a t a ) { $ t h i s -> html . Z u e r s t s t a r t e n ¨ // w i r den A u s g a b e p u f f e r . } function piHandler ( $ p a r s e r . $ s t r ). $ d a t a ) { switch ( $ t a r g e t ) { case ’ php ’ : // Es wurde e i n e C o d e s t e l l e g e f u n d e n .= $ o u t p u t . // Anh¨ ngen d e r A u s g a b e an $html : a $ t h i s -> html . ¨ David Peter Seite 232 . break . } } function error ( $ s t r ) { // A u s g e b e n e i n e r F e h l e r m e l d u n g : die ( ’ <b>F e h l e r :</ b> ’ . ob_start (). break . $ t a r g e t .= ’ <b>Ausgabe :</ b><b r /> ’ .= ’ </ p r e> ’ .= $ c d a t a . // A u s f u h r e n d e s PHP−Codes ¨ eval ( $ d a t a ). $ t h i s -> html .

include_once ” t p . XML-Dokumente parsen Beispiel 2 return $ t h i s -> html . das die Klassenfunktionen benutzt. // E i n b i n d e n d e r K l a s s e $ t p = new TutorialParser ( ’ t u t o r i a l .22. print $ t h i s -> get (). David Peter Seite 233 . } function show () { // G i b t den e r z e u g t e n HTML−Code a u s . } } Zuletzt brauchen wir noch ein kleines Script. $ t p -> show (). xml ’ ). php ”.

1 PHP Extension and Application Repository David Peter Seite 234 . das mit PHP (ab Version 4) mitgeliefert wird. u Da wir uns nicht mit regul¨ren Ausdr¨cken herumschlagen wollen. f¨gt er Variablen/Platzhalter ein. Es ist Bestandteil des Code-Repositorys PEAR1 und ist somit bei korrekter Installation von PEAR per include "HTML/ITX. php ”. 23. die meistens aus HTML-Code bestehen. das die Variablen titel“ und inhalt“ mit ” ” entsprechenden Werten f¨llt. Wenn sich in der HTML-Datei etwas ¨ndert.2 PEAR::IT[X] Integrated Template (Extension) ist ein Templatemodul. Der Hauptvorteil von Templates besteht in der strikten Trennung von PHP-Code und HTML. Ich will in den weiteren Abschnitten zwei solcher Module vorstellen. wo sp¨ter a der dynamische Inhalt eingesetzt werden soll. Auch die Arbeit u ¨ an der Homepage kann besser zwischen Scripter und Designer aufgeteilt werden. u <? php include_once ”HTML/ITX . Somit wird eine Website nicht nur ubersichtlicher (f¨r den Webmaster). Der Designer kann in Ruhe ein HTML-Dokument erstellen. muß das Script nicht ge¨ndert u a a werden – und umgekehrt. Als Gegenst¨ck dazu muß vom o u Programmierer ein Script geschrieben werden. An den Stellen. und muß sich somit nicht um das Design u k¨mmern.1 Beispiel < html > < head > < title >{ titel }</ title > </ head > < body > < h1 >{ titel }</ h1 > <p> { inhalt } </ p > </ body > </ html > So k¨nnte ein einfaches Template zum Beispiel aussehen. Der Prou grammierer setzt f¨r diese Variablen Werte ein. 23. verwenden wir ein a u Templatemodul.php" verf¨gbar.23 Templates Templates sind Layout/Design-Vorlagen.

” T e s t−Template ”). Mit Hilfe der Block-API ist der Programmierer in der Lage. // A u s g e b e n $ t p l -> show (). . Wenn diese Optionen dynamisch generiert werden. // S e t z e n d e r V a r i a b l e n $ t p l -> setVariable ( ” t i t e l ”. a kommt man mit den herk¨mmlichen Platzhaltern nicht mehr weit. // ITX e r w a r t e t a l s P a r a m e t e r den P f a d z u den T e m p l a t e $ t p l = new I n t e g r a t e d T em pl a te E xt e ns i on ( ” . ” J u s t a t e s t . o < html > < body > < select > <!-. ”Noch e i n e O p t i o n ”. html ”). html ”).23. $ t p l -> setVariable ( ” i n h a l t ”. Es o hat mehrere Optionen zum ausw¨hlen.2. ”). Als Beispiel k¨nnte man zum Beispiel ein HTML-Selectfeld nehmen. ” O p t i o n 2 ”. $ t p l -> loadTemplateFile ( ” t e m p l a t e . / ”). $ t p l -> loadTemplateFile ( ” t e m p l a t e .1 Block-API IT[X] bietet auch noch weitere interessante Features an. ?> 23. Templates PEAR::IT[X] // ITX e r w a r t e t den P f a d z u den T e m p l a t e s a l s P a r a m e t e r $ t p l = new I n t e g r a t e d T em pl a te E xt e ns i on ( ” . David Peter Seite 235 . . php ”. u u und f¨r wert“ etwas einf¨gen. u u ” <? php include_once ”HTML/ITX . / ”). Teile des Templates mehrmals auszugeben (mit unterschiedlichen Werten).BEGIN option_loop --> < option >{ wert }</ option > <!-. // Array a u s O p t i o n e n $ o p t i o n e n = array ( ” O p t i o n 1 ”.END option_loop --> </ select > </ body > </ html > Das PHP-Script soll in diesem Fall f¨r jede einzelne Option den gesamten Block einf¨gen.

} // A u s g e b e n $ t p l -> show (). David Peter Seite 236 . Wie man sieht. die hier nicht alle aufgelistet werden k¨nnen. foreach ( $ o p t i o n e n as $ w e r t ) { $ t p l -> setVariable ( ” w e r t ”. $ w e r t ). Die Smarty-Templates sind um einiges flexibler. Trotzdem o ein kleines Beispiel: < html > < head > < title >{ $ t i t e l }</ title > </ head > < body > < select > { html_options output = $ o p t i o n e n } </ select > </ body > </ html > Ich habe hier eine kombinierte Version der beiden oberen Beispiele benutzt. $ s m a r t y = new Smarty . ”Smarty−T e s t ”). // Z u l e t z t muß d e r B l o c k nach dem S e t z e n // d e r V a r i a b l e ( n ) g e p a r s e d werden $ t p l -> parseCurrentBlock (). aber auch komplizierter. $ s m a r t y -> assign ( ” o p t i o n e n ”.23. Smarty bietet viele Features. ” <? php include_once ”Smarty . Außerdem gibt es schon a u vorgefertigte Funktionen. php ”. c l a s s .3 Smarty Smarty wird nicht mit PHP mitgeliefert. welche eine Select-Liste erstellt. array ( ” O p t i o n 1 ”. // A u s w ¨ h l e n d e s B l o c k s a $ t p l -> setCurrentBlock ( ” o p t i o n l o o p ”). wie zum Beispiel html options“. Templates Smarty ”Wieder e i n e ”. ”Und d i e l e t z t e ” ). sondern muß von http:// smarty.php. $ s m a r t y -> assign ( ” t i t e l ”. hat Smarty eine leicht ver¨nderte Syntax f¨r Variablen.net/ heruntergeladen werden. ?> 23.

”Und d i e l e t z t e ”)). ”Noch e i n e O p t i o n ”. wieviel Zeit zum Parsen ben¨tigt wurde. Aus dem Array mit a u dem Optionen erstellt Smarty direkt eine Select-Liste. Auch If-Else-Abfragen. t p l ”). wie zum Beispiel eine Art Debugger. da die Templates oft sehr un¨bersichtlich werden. ob man nicht gleich den PHP-Code in die HTML-Datei einbetten sollte. was etwas Tipp-Arbeit erspart. // T e m p l a t e s w erden b e i // Smarty a l s . auch ausgibt.23. ”Wieder e i n e ”. t p l g e s p e i c h e r t ?> Der Titel wird ¨hnlich wie bei IT[X] in das Template eingef¨gt. u David Peter Seite 237 . Foreach-Schleifen und Include-Direktiven sind kein Problem. Allerdings stellt man sich bei der F¨lle an Funktiou nen manchmal die Frage. Smarty bietet noch viele weitere Funktionen. Templates Smarty ” O p t i o n 2 ”. der außer einer Angabe. welche Vao riablen mit welchen Werten belegt wurden. $ s m a r t y -> display ( ” t e s t .

Teil VIII Anhang Christoph Reeg Seite 238 .

VNr INT. Kennzeichen VARCHAR(10) NOT NULL. Typ VARCHAR(30). PRIMARY KEY(MNr). PRIMARY KEY (MNr. AbtNr INT NOT NULL. AbtNr INT NOT NULL.Datum). FOREIGN KEY(AbtNr) REFERENCES Abteilung(AbtNr) ). GebDat DATE. FOREIGN KEY(AbtNr) REFERENCES Abteilung(AbtNr) ).1 Zu erstellende Tabellen CREATE TABLE Abteilung ( AbtNr INT NOT NULL AUTO_INCREMENT. Datum DATETIME NOT NULL. CREATE TABLE PKW ( PKWNr INT NOT NULL AUTO_INCREMENT. FOREIGN KEY(VNr) REFERENCES Mitarbeiter(MNr). UNIQUE(Kennzeichen). CREATE TABLE Fahrbuch ( MNr INT NOT NULL. Telefon VARCHAR(30). PRIMARY KEY(AbtNr) ). Name VARCHAR(30) NOT NULL. FOREIGN KEY(PKWNr) REFERENCES PKW(PKWNr) ). CREATE TABLE Mitarbeiter ( MNr INT NOT NULL AUTO_INCREMENT. PRIMARY KEY(PKWNr). Christoph Reeg Seite 239 .A Unser Beispiel in SQL A. Name VARCHAR(30). PKWNr INT NOT NULL. FOREIGN KEY(MNr) REFERENCES Mitarbeiter(MNr).PKWNr.

sollen folgende Werte in o Name Christoph Reeg junetz.AbtNr. Unser Beispiel in SQL Daten einf¨gen u A.Telefon) VALUES (6.Name) VALUES (3.3.’1979-5-13’).1.Telefon) VALUES (4.Name) VALUES (1.’069/764758’).’Uli’).AbtNr.2000 03.Name.1.2.’JCP’.VNr.’069/764758’).’1998-3-5’.VNr.1979 5. INSERT INTO Mitarbeiter (MNr.’Christoph Reeg’.1. mit unsere DB eingef¨gt werden. INSERT INTO Mitarbeiter (MNr.de Uli JCP Maier Meier GebDat 13.5.VNr.Name.1.2 Daten einf¨gen u Um ein paar Daten zu haben. INSERT INTO Mitarbeiter (MNr.AbtNr.Name) VALUES (3.05.GebDat) VALUES (1.1. INSERT INTO Mitarbeiter (MNr.’069/97640232’).Telefon) VALUES (2.1998 PKW PKWNr 1 2 Das ganze AbtNr 3 1 in SQL: Kennzeichen MTK-CR 1 F-JN 1 Typ RR VW-Golf INSERT INTO Abteilung (AbtNr. INSERT INTO Abteilung (AbtNr.2.1. INSERT INTO Mitarbeiter (MNr.1998 NULL NULL NULL NULL Telefon NULL 069/764758 NULL 069/764758 06196/671797 069/97640232 Abteilung AbtNr 1 2 3 Name EDV Verwaltung Chefetage Fahrtenbuch MNr 1 1 PKWNr 1 2 Datum 13.AbtNr.5.’Chefetage’).de’. INSERT INTO Mitarbeiter (MNr.3.3.’EDV’).AbtNr.Telefon) VALUES (5.’06196/671797’). u Mitarbeiter MNr VNr AbtNr 1 NULL 3 2 1 1 3 1 1 4 3 1 5 1 2 6 5 2 denen wir arbeiten k¨nnen. INSERT INTO Abteilung (AbtNr.VNr.’Maier’.’Meier’.GebDat.’junetz.AbtNr.Name.Name.A.Name.VNr.Name) VALUES (2.05. Christoph Reeg Seite 240 .’Verwaltung’).

A.Datum) VALUES (2.’F-JN 1’.Typ) VALUES (2. Unser Beispiel in SQL Daten einf¨gen u INSERT INTO PKW (PKWNr.AbtNr.AbtNr. INSERT INTO Fahrbuch (MNr.’1998-5-3’).’2000-5-13’).’VW-Golf’).Typ) VALUES (1.’MTK-CR 1’.3.Kennzeichen. INSERT INTO PKW (PKWNr.Kennzeichen.Datum) VALUES (1.PKWNr. Christoph Reeg Seite 241 .1.2.’RR’).1. INSERT INTO Fahrbuch (MNr.PKWNr.

8).3).4).8). ’ B2 ’ .3).1). ’ C 1 I I ’ . (4. ’ A1 ’ .1). ’ C1 ’ . die einzelnen Abfragen: • mysql> SELECT * FROM vaterzeiger -> WHERE VID = 0. ’ Root ’ .B Losungen ¨ B. ’ B ’ . (9. (3. +----------+ | count(*) | +----------+ Christoph Reeg Seite 242 . ’ C ’ . (8.2). +----+------+------+ | ID | Name | VID | +----+------+------+ | 1 | Root | 0 | +----+------+------+ 1 row in set (0. (11. INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO INTO vaterzeiger vaterzeiger vaterzeiger vaterzeiger vaterzeiger vaterzeiger vaterzeiger vaterzeiger vaterzeiger vaterzeiger vaterzeiger VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES (1. VID int ). (7. Nachdem nun die Tabelle existiert. ’ C1I ’ . daß man die ID der Wurzel kennt. (10. (2. (5.1. (6.0).1 Vater-Zeiger Die CREATE TABLE mit anschließender INSERT Anweisung sollte nicht das Problem sein: CREATE TABLE vaterzeiger ( ID int not null primary key .1).00 sec) • Ich bin hier einfach mal davon ausgegangen. Name varchar (100). mysql> SELECT count(*) FROM vaterzeiger -> WHERE VID = 1. ’ A ’ . ’ B1 ’ . ’ A1I ’ .1 L¨sung zu Baumdarstellungen o B.5).

+------+-----------------+------+ | Name | ist Vater von | Name | +------+-----------------+------+ | Root | ist Vater von | A | | Root | ist Vater von | B | | Root | ist Vater von | C | +------+-----------------+------+ 3 rows in set (0.VID = 0.Name. nur das count() wird weggelassen. vaterzeiger S -> WHERE (V. +-------+------+ | Tiefe | Name | +-------+------+ | 0 | Root | Christoph Reeg Seite 243 .VID = 0.ID = S. L¨sungen o L¨sung zu Baumdarstellungen o | 3 | +----------+ 1 row in set (0.VID -> AND V.ID = S. +----------+ | count(*) | +----------+ | 3 | +----------+ 1 row in set (0. vaterzeiger S -> WHERE V.VID = 0. da MySQL keine Unterabfragen unterst¨tzt. S.Name -> FROM vaterzeiger V.01 sec) Hier wird ein Self-Join gemacht. ’ ist Vater von ’.00 sec) Wenn man die ID der Wurzel nicht kennt. vaterzeiger S -> WHERE V.VID != 0 AS Tiefe.VID OR S. u • Dies ist im Prinzip dieselbe Abfrage wie gerade eben.ID = S.VID -> AND V. • Eine M¨glichkeit w¨re o a mysql> SELECT V. wird die Abfrage etwas l¨nger: a mysql> SELECT count(*) -> FROM vaterzeiger V.00 sec) Viel sch¨ner finde ich aber folgende Ausgabe: o mysql> SELECT S.B.VID = 0) -> AND V. S.Name -> FROM vaterzeiger V.

allerdings wird dadurch o die maximale Tiefe des Baums bestimmt und die Abfrage ist nicht mehr wirklich sch¨n und performant.l.l AND v. die wir dann bei u der eigentlichen Abfrage verwenden.1.00 sec) Mit Hilfe der ersten Abfrage holen wir uns die Werte f¨r l und r. NestedSet s_id -> WHERE s. +------+------+ | l | r | +------+------+ | 14 | 21 | +------+------+ 1 row in set (0. +------+-------+ | Name | Level | +------+-------+ | C | 2 | | C1 | 3 | | C1I | 4 | | C1II | 4 | +------+-------+ 4 rows in set (0.Name.B.00 sec) mysql> SELECT s.2 Nested Set • Die einfachere Variante ist die folgende mit zwei Abfragen: mysql> SELECT l. L¨sungen o L¨sung zu Baumdarstellungen o | 1 | A | | 1 | B | | 1 | C | +-------+------+ 4 rows in set (0.l BETWEEN 14 AND 21 -> GROUP BY s.00 sec) ¨ • Uber entsprechend viele Self-Joins (hier 4) ist dies m¨glich.r -> FROM NestedSet -> WHERE Name = "C". count(*) AS Level -> FROM NestedSet v.l BETWEEN v. sieht eine m¨gliche Abfrage so aus: o mysql> SELECT s.r -> AND s.l BETWEEN v. Wenn du nur eine Anweisung haben willst.l AND v. o B.r Christoph Reeg Seite 244 . NestedSet s -> WHERE s.Name. NestedSet s. count(*) AS Level -> FROM NestedSet v.

00 | 4 | 1 | | C1II | 0.Name OR s. +------+-------+ | Name | Level | +------+-------+ | C | 2 | | C1 | 3 | | C1I | 4 | | C1II | 4 | +------+-------+ 4 rows in set (0.l BETWEEN v. ich habe auch einen Moment f¨r diese Abfrage gebraucht und mußte u etwas basteln.00 | 3 | 0 | | C | 3.00 | 3 | 1 | | B2 | 0.B.Name = "C" -> AND s.r)-s.r -> AND (v.r-s.l-1)/2 AS Nachfolger.00 sec) • Die Abfrage lautet: mysql> SELECT s.00 | 2 | 1 | | B1 | 0.00 | 4 | 0 | +------+------------+-------+--------+ 11 rows in set (0. -> ((min(v.00 | 2 | 0 | | C1 | 2. NestedSet s -> WHERE s.l>1) AS Tiefe.Name.00 | 1 | 0 | | A | 2.l = 1) -> GROUP BY s.r-(s.00 | 3 | 0 | | A1I | 0.l>1))/2) > 0 AS Bruder -> FROM NestedSet v. oder? . +------+------------+-------+--------+ | Name | Nachfolger | Tiefe | Bruder | +------+------------+-------+--------+ | Root | 10.l BETWEEN s_id.l.r -> GROUP BY s.00 | 4 | 0 | | B | 2.00 | 2 | 1 | | A1 | 1.00 sec) Eigentlich gar nicht so schwierig.Name -> ORDER BY s.l.l AND s_id.-) Ich gebe zu. Christoph Reeg Seite 245 .l AND v. -> count(*)+(s.Name != s.00 | 3 | 0 | | C1I | 0. L¨sungen o L¨sung zu Baumdarstellungen o -> AND s_id. -> (s. bis es endlich funktioniert hat.

// T a b e l l e n e n d e echo ”</ t a b l e >\n ”. Teilschritt function print_result_table ( $ r e s u l t ){ // T a b e l l e n a n f a n g echo ”<t a b l e >\n ”. function print_result_table ( $ r e s u l t ){ // T a b e l l e n a n f a n g echo ”<t a b l e >\n ”. // e r s t e s F e l d d e r Z e i l e a u s g e b e n echo ” <t d>$row [ 0 ] < / t d>\n ”. // T a b e l l e n z e i l e n −Ende echo ” </ t r >\n ”. } 2. // T a b e l l e n z e i l e n −Anfang echo ” <t r >\n ”.B. Teilschritt deutlich. // e r s t e s F e l d d e r Z e i l e a u s g e b e n echo ” <t d>$row [ 0 ] < / t d>\n ”. mit einer o Schleife einen numerischen Index durchzugehen. } // T a b e l l e n e n d e echo ”</ t a b l e >\n ”. Das wird im 3. // A l l e E r g e b n i s z e i l e n d u r c h g e h e n while ( $row = mysql_fetch_row ( $ r e s u l t )){ // T a b e l l e n z e i l e n −Anfang echo ” <t r >\n ”. // T a b e l l e n z e i l e n −Ende echo ” </ t r >\n ”. Teilschritt Ich habe bei der L¨sung mysql_fetch_row() verwendet. L¨sungen o L¨sung f¨r Ergebnis-Tabelle ausgeben I“ o u ” B. // Z e i l e a u s DB−A n f r a g e h o l e n $row = mysql_fetch_row ( $ r e s u l t ).2 L¨sung f¨r Ergebnis-Tabelle ausgeben I o u “ ” 1. weil es einfacher ist. Christoph Reeg Seite 246 .

} 4. Mit einer for-Schleife werden einfach alle Felder ausgeu geben. function print_result_table ( $ r e s u l t ){ // T a b e l l e n a n f a n g echo ”<t a b l e >\n ”. } // T a b e l l e n z e i l e n −Ende echo ” </ t r >\n ”. mysql_field_name ( $ r e s u l t . T a b e l l e n z e i l e Anfang echo ” <t r >\n ”. $ i < mysql_num_fields ( $ r e s u l t ). function print_result_table ( $ r e s u l t ){ // T a b e l l e n a n f a n g echo ”<t a b l e >\n ”. wie viele Spalten bei der Abfrage zur¨ckgegeben wurden. Christoph Reeg Seite 247 . Teilschritt Als letztes m¨ssen wir noch abfragen. } // 1 . } // T a b e l l e n e n d e echo ”</ t a b l e >\n ”. T a b e l l e n z e i l e Ende echo ” </ t r >\n ”. ”</t h>\n ”. L¨sungen o L¨sung f¨r Ergebnis-Tabelle ausgeben I“ o u ” } 3. $ i < mysql_num_fields ( $ r e s u l t ). int field_index). Das macht die Funktion u string mysql_field_name(int result. $ i ++){ echo ” <t d>$row [ $ i ]</ t d>\n ”. // A l l e S p a l t e n d u r c h g e h e n for ( $ i = 0.B. $ i ). Teilschritt Mit int mysql_num_fields(int result) kann man abfragen. // A l l e E r g e b n i s z e i l e n d u r c h g e h e n while ( $row = mysql_fetch_row ( $ r e s u l t )){ // T a b e l l e n z e i l e n −Anfang echo ” <t r >\n ”. $ i ++){ echo ” <t h>”. wie die Spalten heißen. for ( $ i = 0. // 1 .

Christoph Reeg Seite 248 . damit keine Mitarbeiter gefunden werden. <? php $db host $db user $db pass $datab = = = = ” l o c a l h o s t ”. einen falschen Namen bei $db_user eintragen oder die Abfrage zu einem SELECT * FROM Mitarbeiter WHERE MNr ” = 0“ erweitern. $ d b u s e r . L¨sungen o L¨sung f¨r Ergebnis-Tabelle ausgeben II“ o u ” // A l l e E r g e b n i s z e i l e n d u r c h g e h e n while ( $row = mysql_fetch_row ( $ r e s u l t )){ // T a b e l l e n z e i l e n −Anfang echo ” <t r >\n ”.3 L¨sung f¨r Ergebnis-Tabelle ausgeben II o u “ ” Kleiner Tipp vorweg: Um zu testen. ” c r ”. o . $ i ++){ echo ” <t d>$row [ $ i ]</ t d>\n ”. kann man einfach mal einen Fehler provozieren.B. } // T a b e l l e n z e i l e n −Ende echo ” </ t r >\n ”. $db ) OR die ( mysql_error ()). ”123 ”. function print_result_table ( $ r e s u l t ){ // s . B. } // T a b e l l e n e n d e echo ”</ t a b l e >\n ”. ” c r ”. } // Hauptprogramm /∗ V e r b i n d u n g z u r D a t e n b a n k a u f b a u e n ∗/ $db = @mysql_connect ( $ d b h o s t . @mysql_select_db ( $ d a t a b . $ d b p a s s ) OR die ( mysql_error ()). // A l l e S p a l t e n d u r c h g e h e n for ( $ i = 0. } B. $ i < mysql_num_fields ( $ r e s u l t ). ob die eine oder andere Abfrage sauber funktioniert. also z.

In diesem Fall sind also zwei Prozentzeichen n¨tig: Eins zum Escapen und o das Prozentzeichen an sich f¨r die Abfrage mit LIKE als Allquantor.B. %3\02d“: Ein Backslash allein macht noch keine Argument-Referenz . 3. L¨sungen o L¨sung f¨r Abfrage mit sprintf()“ o u ” /∗ HTML−S t a r t c o d e a u s g e b e n ∗/ echo ”<html>\n<body>\n ”. . nicht das zweite. ” 4. sind zwei Tricks n¨tig: Zum einen muß das Erzeugen der u o MNr MySQL uberlassen werden und zum anderen muß diese ID abgefragt werden.4 L¨sung f¨r Abfrage mit sprintf() o u “ ” Die vier Fehler sind im Einzelnen: 1. ” 2. Außerdem ist die Jahresangabe in Standard-Notation vierstellig (also zwei Fehler). } // s o n s t d i e F u n k t i o n a u f r u f e n else { print_result_table ( $ r e s u l t ). -%’“: Soll ein einzelnes Prozentzeichen wirklich ausgegeben werden. /∗ Wenn d i e Fehlernummer ! = 0 i s t . um die ¨ Christoph Reeg Seite 249 . } } /∗ HTML−Endcode a u s g e b e n ∗/ echo ”</body>\n</html>\n ”.5 L¨sung f¨r Einf¨gen mit automatischer ID o u u Um das gew¨nschte zu erreichen. dann g a b e s e i n e n F e h l e r => F e h l e r m e l d u n g a u s g e b e n ∗/ if ( mysql_errno () != 0){ echo mysql_error (). /∗ SQL−A b f r a g e ∗/ $ r e s u l t = @mysql_query ( ”SELECT ∗ FROM M i t a r b e i t e r ”). . u B. SELECT %0\$s“: Es gibt kein nulltes Argument. ?> B. muß man es ” escapen. Nie. } // e s g a b k e i n e F e h l e r => E r g e b n i s a u s g e b e n else { // Wie v i e l e D a t e n s a t z e wurden g e f u n d e n ? ¨ // B e i 0 Meldung a u s g e b e n if ( mysql_num_rows ( $ r e s u l t ) == 0){ echo ” K e i n e D a t e n s&auml . t z e g e f u n d e n ! ”. %2\$02d“: Im ISO-Datumsformat steht das Jahr vorne – es m¨ßte also das dritte u ” Argument ausgewertet werden.

2 . $ d b p a s s ) OR die ( mysql_error ()). Im zweiten Text kommt das Wort hallo“ gar nicht vor und ” in dem ersten ist es groß geschrieben. L¨sungen o L¨sungen zu Regul¨ren Ausdr¨cken o a u VNr f¨r die zweite Einf¨geoperation zu haben. ’ 1 9 8 1 − 0 5 − 2 6 ’ ) ”). // K i l e e i n f u g e n und J e n s u n t e r s t e l l e n ¨ mysql_query ( ”INSERT INTO M i t a r b e i t e r ( VNr . $ d b u s e r .3 Wieder zwei mal ja. ’ K i l e ’ ) ”).1. Name ) VALUES ( $ v n r . ’ J e n s ’ . Folgender Code implementiert dies: $db host $db user $db pass $datab = = = = ” l o c a l h o s t ”.B.6 L¨sungen zu Regul¨ren Ausdr¨cken o a u B.1 Das Ergebnis ist zweimal nein. GebDat ) VALUES ( 1 . // J e n s e i n f u g e n ¨ mysql_query ( ”INSERT INTO M i t a r b e i t e r ( VNr . /∗ V e r b i n d u n g z u r D a t e n b a n k a u f b a u e n ∗/ $db = @mysql_connect ( $ d b h o s t . B.1.1 L¨sung zu einfache Suchmuster“ o ” B. 1 . echo mysql_error (). B. B. Christoph Reeg Seite 250 . ”123 ”. $ v n r = mysql_insert_id (). letzteres durch mysql_insert_id(). ” c r ”. AbtNr .6.6. Es wird auf Groß-/Kleinschreibung geachtet. in beiden F¨llen ist das letzte Zeichen kein großer Buchu a stabe oder eine Zahl. $db ) OR die ( mysql_error ()). echo mysql_error (). AbtNr . @mysql_select_db ( $ d a t a b . ” c r ”. Ersteres erreicht man durch Weglassen der u u MNr bei der Liste der Felder (oder bei Angabe der MNr Setzen des Wertes auf NULL).1. Name .6.6.2 Diesmal passen beide Ausdr¨cke.

3 Dieselbe Antwort wie bei der vorigen Frage. Das habe ich an dieser Stelle mit einem [\w. B. Im ersten Text lautet das 4-stellige Wort allo“. ist mir a a u bis jetzt noch nichts besseres eingefallen. auf den zweiten immer noch nicht. Er ist noch nicht optimal (siehe auch die Erkl¨rung).6.2.6.5 Ja. Da der Punkt und der Bindestrich vorkommen darf. B.B.\d" [1-5]\d{2} [-\d]*$/ Was macht der Ausdruck? Als erstes soll er die gesamte Zeile uberpr¨fen. L¨sungen o L¨sungen zu Regul¨ren Ausdr¨cken o a u B. Der erste besteht zwar aus zwei W¨rtern.2.-]+ [-\w]+ [-\w]+ \[\d{2}\/\w{3}\/\d{4}:\d{2}:\d{2}:\d{2} [+-]\d{4}\] "\w+ [\/.6.6.1.5 Auf den ersten Text paßt er nicht.6. o aber das Ausrufezeichen ! ist nicht in \w enthalten.\w]+ HTTP\/\d\. u B. Es ist keine Aussage gemacht. m¨ssen sie hier extra aufgef¨hrt werden. aber nicht bei den “Wort“-Zeichen enthalten ist.-]+ erschlagen.2 L¨sung zu Quantifizierer“ o ” B.6 Der folgende Ausdruck (eigentlich geh¨rt alles in eine Zeile. a ” oder nicht.2 Auf den ersten Text paßt jetzt der Ausdruck.6. Wer einen besseren Ausdruck weiß.6. Dieser Teil ist u u Christoph Reeg Seite 251 .2. B.4 Zweimal ja.2. Am Anfang der Zeile soll der Name bzw. gefolgt von einem Leerzeichen und einem zweiten Wort. die IP des Anfragenden kommen.1. B. In beiden Texten gibt es ein Wort aus vier Buchstaben.2. wo ” noch ein H“ davor h¨ngt. aber da ich bei den regul¨ren Ausdr¨cken auch noch am Lernen bin.2. nur aus Platzgr¨nden ist er o u umbrochen) paßt auf die angegebene Log-Zeile. nein. /^[\w. kann ihn mir gerne schicken.4 Und nochmal passen beide.6. was vor dem Wort stehen darf. daf¨r auf den zweiten. B. B. In beiden Strings kommt ein 5 Zeichen langes Wort vor. deshalb das u ¨ Dach ^ am Anfang und das Dollarzeichen $ am Ende.1 Der Ausdruck paßt bei keinem der beiden Texte.6.

Ahnliches gilt f¨r den Slash: u ” ” Wenn ich ihn nicht mit einem Backslash escaped h¨tte. u Der zweite Fehler steckt in der Ausgabe. Die n¨chsten beiden Felder sind einfacher.3. In den Anf¨hrungszeichen steht das n¨chste nicht-Optimum. Daher dieser Ausdruck. damit nur der Punkt paßt und nicht ein beliebiges Zeichen.“. Damit wurde nicht die Variable mit dem Wert verglichen. trotzdem muß ich beliebige W¨rter u o ” ” erlauben. Das Programm gibt folgendes ohne Fehlermeldung aus: Die Variable 1 hat den Wert 1“. . Somit wurde in der ” ” IF-Anweisung der 1.B. habe ich sie hier explizit angegeben. Da der Statuscode immer eine dreistellige Zahl zwischen 100 und 505 ist.1“. trotzdem aber auf den Ausdruck passen. wenn es keinen Sinn machen w¨rde.name“ oder rechnername“ keine g¨ltigen Namen u ” ” ” oder IP-Adressen sind. L¨sungen o L¨sungen zur Fehlersuche o nicht optimal. wie man Oder realisiert. u ¨ Wenn ja. keine. Das erste Wort in den u a Anf¨hrungszeichen ist entweder GET“ oder POST“.1 /(\d*).3 Gruppierungen B. Da die Anzahl der u einzelnen Zeichen feststehen. weil 1. Der Punkt bei HTTP muß auch mit einem Backslash escaped werden. .6. Der Ausdruck in den eckigen Klammern m¨ßte eigentlich klar sein. muß auch hier explizit die Anzahl der Ziffern angegeben.gueltiger. sondern der Variablen wurde der Wert 1“ zugewiesen. weil ich noch nicht geschrieben habe. w¨re der Ausdruck an der Stelle a a zu Ende. Zu Beginn wird die Variable $i auf einen Wert gesetzt (hier 0) und dann uberpr¨ft. sondern die Zeichen ¨ eckige Klammer auf“ und eckige Klammer zu“ haben will. Die Gr¨ßenangabe (das letzte Feld) kann auch nichts (d. u B. Es gibt zwei L¨sungen f¨r das Problem. ob sie den Wert 1 hat. h. Anweisungsblock ausgef¨hrt. soll der Text Die Variable $i hat den Wert 1“ ausgegeben werden. dazu muß man statt $i ein \$i schreiben. weil ich hier keine Menge von Zeichen definieren will. ein Minus u o -) enthalten. sonst Die ” ” Variable hat nicht den Wert 1“. weil nicht weit genug gepr¨ft wird.7 L¨sungen zur Fehlersuche o B. Anschließend wurde dieser Wert genommen.\1DM/ B.“ und nicht Die Variable 1 .1 L¨sung f¨r ein komisches IF o u “ ” Teil 1 Der Sinn des Programms sollte eigentlich auf den ersten Blick klar sein. . so ” daß alle Werte. Ist auch nicht ganz optimal. Christoph Reeg Seite 252 .7.6. Entweder o u ” benutzt man die einfachen Anf¨hrungszeichen und verhindert damit das Ersetzen von u Variablennamen durch deren Werte oder man escaped das $. Die eckigen Klammern m¨ssen mit einem Backslash u u ” escaped werden. Ausgegeben werden sollte Die Variable $i ” . ” Der erste ist ein beliebter Fehler: statt des Vergleichsoperators == wurde der Zuweisungsoperator = benutzt. . die nicht 0“ waren. weil hier entweder normale W¨rter oder ein a o Minus f¨r nicht vorhanden“ stehen. als true“ interpretiert wurden.

” ” B. Dann erhielte man n¨mlich eine Fehlermeldung. PHP kann das erst am Ende der Datei merken. L¨sungen o L¨sungen zur Fehlersuche o Solche Fehler k¨nnte man vermeiden. Auf jeden Fall l¨ßt sich so a a der Fehler leichter finden. $i++){ echo "$i<br>\n". Vorteilhaft in solchen Situationen ist es auch. Bei der u if-Anweisung wird der Wert 0“ genommen und der gilt als false“. Bei folgender Schreibu weise f¨llt leichter auf. der zueinander geh¨rige Klammern farblich hervorhebt. Vermeiden kann man solche Fehler. einen Editor zu benutzen.B.2 L¨sung f¨r Fehler in einer leeren Zeile? o u “ ” Die Ausgabe des Programms sollte eigentlich folgende sein: 1 2 3 4 5 Das waren die Zahlen 1-5 Das Programm gibt aber unter PHP3 folgendes aus: 1 Das waren die Zahlen 1-5 Parse error: parse error in /home/httpd/html/test. indem man richtig einr¨ckt. Christoph Reeg Seite 253 . $i<=5.7. daß in Zeile 2 ein Anweisungsblock mit einer { angefangen.php4 on line 6 Die unterschiedlichen Ausgaben kommen vom unterschiedlichen Design von PHP3 und PHP4. daß die (geschweifte Klammer zu) fehlt. aber nicht mehr beendet wurde. Teil 2 Im Prinzip gilt das oben Gesagte. Hier wird allerdings der else-Block ausgef¨hrt. ?> Manche schreiben es noch deutlicher. w¨rde man statt if ($i == 1) ein if (1 == $i) o u schreiben. Die Fehlermeldung ist aber in beiden F¨llen dieselbe: In Zeile 6 gibt es einen parse a error. Zeile 6 ist allerdings leer. Der Fehler ist. o <?php for ($i=1. wenn man nur 1 = $i schriebe.php3 on line 6 Und bei PHP4 folgendes: Parse error: parse error in /home/httpd/html/test. daher wird in der Fehlermeldung Zeile 6 angegeben. echo "Das waren die Zahlen 1-5". a weil man dem Wert 1 nicht den Wert der Variablen zuweisen kann.

” An diesem Beispiel sieht man.8 L¨sung zu Spruch des Abrufs o Es gibt zwei Gr¨nde f¨r die zus¨tzliche Funktion: u u a • Es ist einfach deutlich schneller. • Durch diese L¨sung vermeide ich. ?> B.‘ wo eins ist?“ o ” ¨ Das gewollte Ergebnis ist dasselbe wie in der vorigen Ubung. Z. reservierte W¨rter in dunkelrot. was eigentlich in den Anf¨hrungszeichen stehen sollte. Ausgabe von PHP3 (die letzten beiden Zeilen sind eigentlich eine): 1 . B. u Daher auch die Ausgabe bei PHP3. a o Christoph Reeg Seite 254 .’’ or ‘’. wenn es ein get_sprueche gibt? 1 farbliche Hervorhebung in Abh¨ngigkeit der Bedeutung. w¨re sie sinnvoll: Wozu die Funktion get_spruch u a implementieren.3 L¨sung zu Wieso fehlt ein ‘. u Wenn man die Frage umdrehen w¨rde. Text in Anf¨hrungszeichen wird gr¨n a u u gef¨rbt. in unserem Fall in Zeile 5. echo "Das waren die Zahlen 1-5".7.’’ in /home/httpd/html/test. daß der Fehler nicht immer in der gemeldeten Zeile liegen muß.’’ or ‘’. PHP erwartet in Zeile 5 ein . expecting ‘’. expecting ‘’. L¨sungen o L¨sung zu Spruch des Abrufs o <?php for ($i=1. Nach dem Anf¨hrungszeichen in Zeile 3 wird alles bis u zum n¨chsten Anf¨hrungszeichen ausgegeben. daß wir erstmal mit einem .php3 on line 5 Ausgabe von PHP4: Parse error: parse error.“ die Anweisung beenden.B. } echo Parse error: parse error.“. Bei genauerem Betrachten sieht diese aber richtig aus. $i++) { echo "$i<br>\n". In diesem Fall hilft nur konzentriertes Programmieren und ein Editor mit SyntaxHighlighting1 . als Reihe von PHP-Befehlen u interpretiert. Und mit einem Das“ nach einer Ausgabe kann PHP eben nicht viel anfangen ” und will.’’ in /home/httpd/html/test. daß ein Spruch bei zwei Abfragen zuf¨llig ausgew¨hlt o a a w¨rde. Dort werden die Anf¨hrungszeichen nicht wieder geschlossen. Die Ausgabe unterscheidet sich wieder je nach PHP-Version. als mehrere Abfragen mit nur jeweils einem Datensatz. B. daß ein Spruch mehrmals vorkommt. $i<=5. Der ” Fehler steckt in Zeile 3.php4 on line 5 Wie im obigen Fall ist auch hier die Fehlermeldung bei beiden Versionen dieselbe. Damit wird aber a u das. Bei mehreren o Abfragen k¨nnte es ja passieren. nur eine Abfrage mit mehreren Datens¨tzen als a Ergebnis zu machen.

B. I ma ge C ol o rT ra n sp a rent ( $ t h i s -> im . unterst¨tzt das GIF-Format aus lizenzu rechtlichen Gr¨nden nicht mehr u Christoph Reeg Seite 255 . $ t h i s -> height = $ h e i g h t . s c h w a r z e r ” S t i f t ” $ w h i t e c o l = ImageColorAllocate ( $ t h i s -> im . /∗ ∗ B r e i t e ∗/ var $ w i d t h . /∗ ∗ M a l f a r b e ∗/ var $ d c o l o r . es werden Bilder erstellt. /∗ ∗ H¨ he ∗/ o var $ h e i g h t . /∗ ∗ ∗ Konstruktor ∗ B i l d a n l e g e n und S t a n d a r d f a r b e n s e t z e n ∗ ∗ @param i n t B r e i t e ∗ @param i n t H¨ he o ∗/ function Image ( $ w i d t h =100. die von den Image-Funktionen benutzt wird. $ w h i t e c o l ). L¨sungen o L¨sung zum Image-Beispiel o B. // t r a n s p a r e n t e r H i n t e r g r u n d . $ t h i s -> width = $ w i d t h . 2 Die GD-Lib. 0). $ t h i s -> im = @ImageCreate ( $ w i d t h . 0. kein HTML! Als erstes die Image-Klasse: /∗ ∗ ∗ Image K l a s s e ∗ L e g t e i n B i l d ( d e f a u l t : 1 0 0 x 1 0 0 ) an ∗ und g i b t e s b e i B e d a r f a u s ∗/ class Image { /∗ ∗ Image s t r e a m ∗/ var $im . $ h e i g h t ) or die ( ”Konnte k e i n e n Image s t r e a m a n l e g e n ”). Wohlgemerkt. 0. $ h e i g h t =100) { if ( $ w i d t h <1 || $ h e i g h t <1) $ w i d t h = $ h e i g h t = 100.9 L¨sung zum Image-Beispiel o Der folgende Code erzeugt transparente Bilder im PNG-Format2 .

0).B. ImagePNG ( $ t h i s -> im ). 0. } } Nun die Punkt-Klasse: /∗ ∗ ∗ Point Klasse ∗ Kann e i n e n Punkt malen und a u s g e b e n ∗/ class Point extends Image { /∗ ∗ X−K o o r d i n a t e ∗/ var $x = 0. } /∗ ∗ ∗ H¨ he d e s B i l d e s z u r u c k l i e f e r n o ¨ ∗ ∗ @ r e t u r n i n t H¨ he o ∗/ function getHeight () { return $ t h i s -> height . } /∗ ∗ ∗ Breite des Bildes z u r u c k l i e f e r n ¨ ∗ ∗ @return i n t B r e i t e ∗/ function getWidth () { return $ t h i s -> width . } /∗ ∗ ∗ B i l d a n z e i g e n (PNG) ∗/ function show () { Header ( ” C o n t e n t−t y p e : image / png ”). /∗ ∗ Y−K o o r d i n a t e ∗/ var $y = 0. 0. /∗ ∗ ∗ K o o r d i n a t e n und s o n s t i g e s s e t z e n ∗ ∗ @param i n t X−K o o r d i n a t e Christoph Reeg Seite 256 . L¨sungen o L¨sung zum Image-Beispiel o $ t h i s -> dcolor = ImageColorAllocate ( $ t h i s -> im .

B. $ t h i s -> dcolor ). L¨sungen o L¨sung zum Image-Beispiel o ∗ @param i n t Y−K o o r d i n a t e ∗/ function set ( $x =0. $ t h i s -> r = $ r . Da ich die GD-Lib 2. 0 ∗/ class Circle extends Point { /∗ ∗ R a d i u s ∗/ var $ r = 0. $y =0) { $ t h i s -> x = $x . /∗ ∗ ∗ K o o r d i n a t e n und R a d i u s s e t z e n ∗ ∗ @param i n t X−K o o r d i n a t e ∗ @param i n t Y−K o o r d i n a t e ∗ @param i n t R a d i u s ∗/ function set ( $x =0. $ t h i s -> y . Ein Rechteck ist auch nicht schwer zu erstellen: Christoph Reeg Seite 257 . ∗ e r f o r d e r t a b e r d i e GD−L i b 2 . $ t h i s -> r . } } Kreis-Ausgabe (funktioniert nur mit GD-Lib 2. $ m y c i r c l e -> show (). Als n¨chstes der Kreis: a /∗ ∗ ∗ Circle Klasse ∗ Kann e i n e n K r e i s malen und a u s g e b e n . $ t h i s -> dcolor ).0!): $ m y c i r c l e = new Circle (). $ t h i s -> y . $y ). $ t h i s -> r . $ r =10) { parent :: set ( $x .0 nicht habe. 50). fehlt hier das entsprechende Bild . ImageEllipse ( $ t h i s -> im . 30). . $ t h i s -> y = $y . $ m ypo int -> set (50. $ m y c i r c l e -> set (50. $ t h i s -> x . } } Und schließlich die Ausgabe: $ m ypo int = new Point (). $y =0. $ t h i s -> x . 50. $ m ypo int -> show (). ImageSetPixel ( $ t h i s -> im . .

30. $ m y r e c t -> set (50.$ h e i g h t /2). $ t h i s -> x2 . /∗ ∗ z w e i t e Y−K o o r d i n a t e ∗/ var $y2 . ∗ ggf . $ t h i s -> y . } // ( x . y2 ) r e c h t s u n t e n ImageRectangle ( $ t h i s -> im . $y .$ w i d t h /2. ( x2 . } } Beispiel-Rechteck: $ m y r e c t = new Rectangle ().B. $y =0. $ w i d t h =10. 40. /∗ ∗ ∗ K o o r d i n a t e n und Ausmaße s e t z e n . Zum Schluß noch das Quadrat: /∗ ∗ Christoph Reeg Seite 258 . L¨sungen o L¨sung zum Image-Beispiel o /∗ ∗ ∗ Rectangle Klasse ∗ Kann e i n R e c h t e c k malen und a u s g e b e n ∗/ class Rectangle extends Point { /∗ ∗ z w e i t e X−K o o r d i n a t e ∗/ var $x2 . $ t h i s -> x2 = $x + $ w i d t h . } else { parent :: set ( $x . 50. zentrieren ∗ ∗ @param i n t X−K o o r d i n a t e ∗ @param i n t Y−K o o r d i n a t e ∗ @param i n t B r e i t e ∗ @param i n t H¨ he o ∗ @param b o o l e a n Um X/Y−K o o r d i n a t e n z e n t r i e r e n ∗/ function set ( $x =0. y ) i s t l i n k s o b e n . $ t h i s -> dcolor ). $y ). $ t h i s -> y2 = $y + $ h e i g h t /2. $ c e n t e r = false ){ if ( $ c e n t e r ) { parent :: set ( $x . $ t h i s -> x2 = $x + $ w i d t h /2. $ m y r e c t -> show (). $ t h i s -> y2 = $y + $ h e i g h t . true ). $ h e i g h t =10. $ t h i s -> x . $ t h i s -> y2 .

B. 30).10 L¨sung zur Referenzsemantik o Eine korrekte Implementierung s¨he z. ∗ ggf . } } Christoph Reeg Seite 259 . $ l e n g t h . zentrieren ∗ ∗ @param i n t X−K o o r d i n a t e ∗ @param i n t Y−K o o r d i n a t e ∗ @param i n t S e i t e n l ¨ n g e a ∗ @param b o o l e a n Um X/Y−K o o r d i n a t e n z e n t r i e r e n ∗/ function set ( $x =0. $y . $m ys qua re -> show (). L¨sungen o L¨sung zur Referenzsemantik o ∗ Square Klasse ∗ Kann e i n Q u a d r a t malen und a u s g e b e n ∗/ class Square extends Rectangle { /∗ ∗ ∗ K o o r d i n a t e n und Ausmaße s e t z e n .B. Abbildung B. $y =0. 50. so aus: a class MyArray { var $ a r r a y . Rechteck und Quadrat B. $ l e n g t h . $m ysqua re -> set (50.1: erzeugte Bilder: Punkt. function MyArray () {} function add (& $ v a l ) { $ t h i s -> array [] =& $ v a l . } } Und die obligatorische Ausgabe: $m ysqua re = new Square (). $ c e n t e r = false ) { parent :: set ( $x . $ l e n g t h =10. $ c e n t e r ).

$ t e s t -> setVar (0). ”\ n ”.B. $test =& new Test (42. echo $ t e s t -> getVar (). ” ”. var_dump ( $ a r r a y ). } function getVar () { return $ t h i s -> var . } function setVar ( $ v a r ) { $ t h i s -> var = $ v a r . & $ a r r a y ) { $ t h i s -> var = $ v a r . Christoph Reeg Seite 260 . } } $ a r r a y = new MyArray (). $ t e s t 2 -> getVar (). L¨sungen o L¨sung zur Referenzsemantik o class Test { var $ v a r . $ t e s t 2 =& $ t e s t . function Test ( $ v a r . $ a r r a y ). $ a r r a y -> add ( $ t h i s ).

Mere aggregation of Open Publication works or a portion of an Open Publication work with other works or programs on the same media shall not cause this license to apply to those other works. NO WARRANTY. unless otherwise explicitly stated in the document.opencontent. not using any of the Open Publication License Options from section LICENSE OPTIONS. 8 June 1999 C. SEVERABILITY. express or implied. Proper form for an incorporation by reference is as follows: Copyright (c) 2000 by Christoph Reeg. the implied warranties of merchantability and fitness for a particular purpose or a warranty of noninfringement. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License. including. SCOPE OF LICENSE The following license terms apply to all Open Publication works. The publisher and author’s names shall appear on all outer surfaces of the book. in any medium physical or electronic. Christoph Reeg Seite 261 . COPYRIGHT The copyright to each Open Publication is owned by its author(s) or designee. the remaining portions of the license remain in force. On all outer surfaces of the book the original publisher’s name shall be as large as the title of the work and cited as possessive with respect to the title.C Open Publication License Draft v1. and that this license or an incorporation of it by reference (with any options elected by the author(s) and/or publisher) is displayed in the reproduction. If any part of this license is found to be unenforceable in any jurisdiction. The aggregate work shall contain a notice specifying the inclusion of the Open Publication material and appropriate copyright notice. v1. provided that the terms of this license are adhered to. Commercial redistribution of Open Publication-licensed material is permitted. but not limited to. Any publication in standard (paper) book form shall require the citation of the original publisher and author.0 or later (the latest version is presently available at http://www.0. Open Publication works are licensed and provided as is“ without ” warranty of any kind.org/openpub/).1 Englische Version REQUIREMENTS ON BOTH UNMODIFIED AND MODIFIED VERSIONS The Open Publication works may be reproduced and distributed in whole or in part.

C. made to the document. add the phrase ‘Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. SSubstantive modification¨ defined as a change to the ıs semantic content of the document. • To prohibit distribution of substantively modified versions without the explicit permission of the author(s). These options are considered part of the license instance and must be included with the license (or its incorporation by reference) in derived works. • The location of the original unmodified document must be identified. This notification should describe modifications. • All substantive modifications (including deletions) be either clearly marked up in the document or else described in an attachment to the document. if any. you provide email notification to the authors of your intent to redistribute at least thirty days before your manuscript or media freeze. it is considered good form to offer a free copy of any hardcopy and CD-ROM expression of an Open Publicationlicensed work to its author(s). and excludes mere changes in format or typographical corrections. must meet the following requirements: • The modified version must be labeled as such. LICENSE OPTIONS The author(s) and/or publisher of an Open Publication-licensed document may elect certain options by appending language to the reference to or copy of the license. To accomplish this. to give the authors time to provide updated documents. it is requested from and strongly recommended of redistributors that: • If you are distributing Open Publication works on hardcopy or CD-ROM. GOOD-PRACTICE RECOMMENDATIONS In addition to the requirements of this license. Open Publication License Englische Version REQUIREMENTS ON MODIFIED WORKS All modified versions of documents covered by this license. anthologies. • The person making the modifications must be identified and the modifications dated. • Acknowledgement of the original author and publisher if applicable must be retained according to normal academic citation practices. Christoph Reeg Seite 262 . including translations.’ to the license reference or copy. while it is not mandatory under this license. • Finally. • The original author’s (or authors’) name(s) may not be used to assert or imply endorsement of the resulting document without the original author’s (or authors’) permission. compilations and partial documents.

die von dem Autor / den Autoren und/oder dem Herausgeber gew¨hlt wurde) a wird in der Reproduktion angezeigt.(Papier-) Buch-Format erfordert die Zitierung der Original-Herausgeber und Autoren. a Die bloße Zusammenfassung von Open-Publication-Arbeiten oder eines Teils einer OpenPublication-Arbeit mit anderen Arbeiten oder Programmen auf dem selben Medium bewirkt nicht. Eine geeignete Form einer Aufnahme durch Verweis lautet wir folgt: Copyright (c) 2000 by Christoph Reeg. Diese Ver¨ffentlichung macht von keiner der o im Abschnitt LIZENZ-OPTIONEN genannten Optionen Gebrauch. physisch oder elektronisch. C. add the phrase ’Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder. verteilt werden (die letzte Version ist gegenw¨rtig verf¨gbar unter a u http://www. Die zusam- Christoph Reeg Seite 263 .C. Version v1. in beliebigen Medien. Jegliche Publikation im Standard.2 Deutsche Version ¨ Inoffizielle deutsche Ubersetzung des englischen Originals (von Stefan Meretz).opencontent. Auf allen ¨ußeren Deckfl¨chen des Buchs a a a a soll der Name des Original-Herausgebers genauso groß sein wie der Titel der Arbeit und so einnehmend genannt werden im Hinblick auf den Titel. und diese Lizenz oder ein Verweis auf diese Lizenz (mit jeder o Option. vorausgesetzt. Dieses Material darf nur gem¨ß der Rea geln und Bedingungen wie sie von der Open Publication Licence. festgelegt werden. ¨ GULTIGKEITSBEREICH DER LIZENZ Die nachfolgenden Lizenzregeln werden auf alle Open-Publication-Arbeiten angewendet.’ to the license reference or copy. Die kommerzielle Weiterverbreitung von Open Publication lizensiertem Material ist untersagt. daß die Lizenz auch auf diese anderen Arbeiten angewendet wird. COPYRIGHT Das Copyright jeder Open Publication geh¨rt dem Autor / den Autoren oder Zeichnungso berechtigten.org/openpub/ ). Open Publication License Deutsche Version • To prohibit any publication of this work or derivative works in whole or in part in standard (paper) book form for commercial purposes is prohibited unless prior permission is obtained from the copyright holder. die Bedingungen dieser Lizenz geh¨ren dazu. To accomplish this. sofern nicht explizit anders lautend im Dokument erw¨hnt. ¨ ERFORDERNISSE FUR UNMODIFIZIERTE UND MODIFIZIERTE VERSIONEN Open-Publication-Arbeiten d¨rfen als Ganzes oder in Teilen reproduziert und verteilt weru den. Die Namen von Herausgeber und Autor/en sollen auf allen ¨ußeren Deckfl¨chen des Buchs erscheinen.0.

m¨ssen die folu genden Erfordernisse erf¨llen: u • Die modifizierte Version muß als solche gekennzeichnet werden. die die Modifikationen vornimmt. bleiben die verbleibenden Teile der Lizenz in Kraft. einschließlich. Open-Publication-Arbeiten werden lizensiert und verbreitet ”wie sie sind¨hne Gew¨hrleistung jeglicher Art. der impliziten Gew¨hrleistung des Vertriebs und der Geignetheit a f¨r einen besonderen Zweck oder eine Gew¨hleistung einer non-infringement. • Die Person. o a aber nicht begrenzt auf. EMPFEHLUNGEN EINER GUTEN PRAXIS In Erg¨nzung zu den Erfordernissen dieser Lizenz. Christoph Reeg Seite 264 . Schließlich.m¨ssen in u ¨ Ubereinstimmung mit der normalen akademischen Zitierungspraxis erhalten bleiben. wird von den Weiterverteilenden era wartet und ihnen stark empfohlen: • Wenn Sie Open-Publication-Arbeiten als Hardcopy oder auf CD-ROM verteilen. ABTRENNBARKEIT. Anthologien. die die Aufnahme von Open-PublicationMaterial und eine geeignete Copyright-Notiz angibt. ¨ KEINE GEWAHRLEISTUNG. u • Danksagungen der Original-Autors und -Herausgebers . um u den Autoren Zeit zu geben aktualisierte Dokumente anzubieten. eine vorgeschlagene gute Form eine kostenlose Kopie jedes Hardcopy. ist es. explizit oder implizit. Die Ank¨ndigung u ¨ sollte die Anderungen beschreiben. u a ¨ ERFORDERNISSE FUR MODIFIZIERTE ARBEITEN Alle modifizierten Versionen. schicken Sie eine E-Mail-Ank¨ndigung Ihrer Absicht der Weiterverteilung mindestens u dreißig Tage bevor Ihr Manuskript oder das Medium endg¨ltig festgelegt ist. die durch diese Lizenz abgedeckt werden. obwohl nicht erforderlich unter dieser Lizenz. Open Publication License Deutsche Version mengefaßte Arbeit soll einen Hinweis enthalten. muß genannt und die Modifikationen m¨ssen datiert werden. • Der Ort des originalen unmodifizierten Dokuments muß benannt werden.und CD-ROM-Ursprungs einer unter Open Publication lizensierten Arbeit dem Autor / den Autoren anzubieten.sofern vorhanden . die gegebenenfalls am Dokument vorgenommen wurden.C. • Die Namen der Original-Autoren d¨rfen nicht benutzt werden ohne die Erlaubnis u des Original-Autors / der Original-Autoren. einschließlich von ¨ Ubersetzungen. • Alle substantiellen Modifikationen (einschließlich L¨schungen) sind entweder im Doo kument klar zu kennzeichnen oder sonst in einem Anhang zu beschreiben. Zusammenstellungen und Teildokumenten. Wenn irgendein Teil dieser Lizenz durch irgendeine Rechtsprechung außer Kraft gesetzt werden.

Substantielle Modifizierung“ ist definiert als ” ¨ eine Anderung des semantischen Inhalts des Dokuments und schließt bloße Format¨ Anderungen oder typographische Korrekturen aus. Zur Anwendung f¨gen Sie den Satz ‘Distribution of substantively modified versions of u this document is prohibited without the explicit permission of the copyright holder‘ (Verbreitung von substantiell modifizierten Versionen dieses Dokuments ist ohne die explizite Erlaubnis des Copyright-Inhabers untersagt) dem Lizenz-Verweis oder der Lizenz-Kopie hinzu. Open Publication License Deutsche Version LIZENZ-OPTIONEN Der/die Autor/en und/oder der Herausgeber eines unter Open Publication lizensierten Dokuments darf bestimmte Optionen durch Anh¨ngen von Regelungen an den Lizenza Verweis oder die Lizenz-Kopie w¨hlen. u u • Verhindern der Verteilung von substantiell modifizierten Versionen ohne explizite Erlaubnis des Autors / der Autoren.(Papier-) Buchform f¨r kommerzielle Zwecke ohne vorherige u Erlaubnis durch den Copyright-Inhaber ist untersagt) dem Lizenz-Verweis oder der Lizenz-Kopie hinzu. Zur Anwendung f¨gen Sie den Satz ‘Distribution of the work or derivative of the work u in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder‘(Verbreitung dieser Arbeit oder abgeleiteter Arbeiten in Teilen in Standard.C. • Verhindern jeglicher Ver¨ffentlichung dieser Arbeit oder abgeleiteter Arbeiten im o Ganzen oder in Teilen in Standard. Christoph Reeg Seite 265 .(Papier-) Buchform f¨r kommerzielle Zwecke u ohne vorherige Erlaubnis durch den Copyright-Inhaber. Diese Optionen sind empfohlener Teil der Lizenza bestimmungen und m¨ssen in abgeleiteten Arbeiten in die Lizenz eingef¨gt werden.

php-faq.php-center.und (¨ber letzteres im Zusammenspiel mit einem MySQLu Server.mysql.4 Weitere Informationsquellen Dies soll keine Linksammlung werden .org/ [8] Die FAQ zu PHP (sehr ausf¨hrlich und enth¨lt auch MySQL) u a http:// www. Band 6 a [2] Duden Fremdw¨rterbuch o [3] IBM-Lehrgangsunterlagen DB2 Familie .org/ Christoph Reeg Seite 266 .dazu gibt es einfach zu viele Webseiten uber ¨ PHP und PHP-Portale im Internet.selfhtml. An dieser Stelle werden nur die wichtigsten Seite bzw.com/ [5] Die Herstellerseite von MySQL (in deutsch) http://www.) MySQL-Unterst¨tzung u http://www.opensa. DAS Nachschlagewerk in Sachen HTML/CSS u http:// de. Portale aufgelistet.de/ [6] Die Homesite von PHP http://www. ein weiteres deutsches PHP-Portal http://www. [4] Die Herstellerseite von MySQL http://www.Datenbankdesign“ ” C. Von diesen Ausgangspunkten aus findet man fast alles.net/ [7] SELFHTML von Stefan M¨nz.php. o.Literaturverzeichnis C.mysql.de [12] Webserver mit SSL-.de [11] PHP-Homepage.sourceforge.php-homepage. PHP. s.de/ [9] Die FAQ zu MySQL (befindet sich noch im Aufbau) http://mysql-faq.3 zitierte Literatur [1] Brockhaus Enzyklop¨die.net/ [10] PHP-Center. ein deutsches PHP-Portal http://www.

. 71 Umschichten der T¨rme von Hanoi . . .3 4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Die vier Ebenen eines DBS . . . . . . . . . . 259 Christoph Reeg Seite 267 . . . . . . . . . . . . . .3 7. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 Baumdarstellung im Nested Set Modell . . . . . . . . . . . . . . . . . . . . . . . .Abbildungsverzeichnis 3. . . . . . . . . . . . . . . . . .2 7. . . . 24 Unser Baum-Beispiel . . . . . . . . . . 11 Tabellenstruktur . 12 Streifendiagramm . . . . . . . . . . . .2 3. . . . . . . . . . . . . . 68 Baumdarstellung als Summe von Mengen . . .1 Struktur eines Datenbanksystems . . . . . . . .1 3. . . . . . . . . . . . . . . .1 erzeugte Bilder: Punkt. . . . . . . . . . . . . . . 23 ER-Beispiel 2 . . . . . . Rechteck und Quadrat . . . . . . . . .1 7. . . . . . . . . . . . . . . . . . . .3 8. . . .1 4. . . . . . 116 u B. . . . . . . . . . . . . . . . . . . . . . . 22 ER-Beispiel 1 . . . . . . . . . . . . .2 4. . . . . .

. . Konventionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . String-Funktionen in SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 6. . . . . . . . . . . . . . . . . .7 6. . .2 12. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Formatierungen f¨r DATE FORMAT o u Gruppenfunktionen in SQL . . . . . . . .3 8. . . . . . . . . . . .5 6. . . . . . 32 32 43 50 51 51 51 52 53 53 Baumdarstellung mit Vater-Zeiger . . . . . . . . . . .4 Zeichenmengen . . . . . . . 69 Arithmetische Operatoren in PHP Bit-Operatoren in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 IMAP-Webmail-System . . . . . . .3 12. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vergleichsoperatoren in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . 148 12. . . . . . . . 163 u 18.9 6. . . . . . . . .1 6.1 8. Sonderzeichen bei den PCRE . . . .4 6. . . . .1 8. . . . . m¨gl. . . . . . . . . .1 Von Autos zu Objekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Logische Operatoren in PHP . . . . . . . . . . . . . . . . . . .8 6. . . . . . . . . . . . . . . .3 6. . . . . . . . .7 9.10 7. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datum-Funktionen in SQL . . . . . . . . . . . . . . . . 125 Datenbank-Realisierung der Hobbies-Mehrfachauswahl . . . . 13 u Verf¨gbare Datentypen in SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Bit-Funktionen in SQL . 146 11. . . . . . . . . . . .2 8. . . . . . . . . . . . . . . . .6 6. . . . . . . . . . . . . . . . . .Tabellenverzeichnis 1. . . . . . . . . . . . . . . . . . . . . . . . .2 6. . Verf¨gbare Vergleichsoperatoren in SQL . . . . . . . . . . . . . . . . . . . . . . 194 20. . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 12. . . . . . . . . . .2 Cache Header . . . . . 4 Beispiel f¨r Tabellenstruktur . . . . . . . . . . . . . . . . . . .5 8. . . . . . . . . . . 85 86 86 87 88 93 107 urlencoded . . . . . . . . . . . . 152 152 153 154 14. . . Logische Funktionen in SQL . . . . . . . . . . . . . 212 Christoph Reeg Seite 268 . . . . Quantifizierer . .1 PHPDOC-Schl¨sselworte . . . . . .1 3. . . . . . . . . . . . . Typen in PHP . . . . . . . . . . . . . . . . 129 11. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 9. . . . . . . . . . . . printf: Platzhalter . . . . . . . escaped characters . . . . . . . . . . . . . . . . . . . u Bedeutung der YMHSDs . . . . . . . .6 8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Optionen f¨r regul¨re Ausdr¨cke u a u . . . .1 Content-Type Typen . . . . . . . . . . u Mathematische Funktionen in SQL . . . .4 8. . . . . . . . . . .2 Typogr. . . . . . . . . .

. 212 20. . 213 Christoph Reeg Seite 269 . . . . . . . . . . . . . . . . . . . . . . . .2 IMAP-Webnews-System . . . . . . . . . . . . . 213 20.4 Mehrbenutzer-Bookmarkverwaltung .Tabellenverzeichnis Tabellenverzeichnis 20. . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Mehrbenutzer-Adreßbuch . . . . . . . . . . . .

sehr interessante Logos dabei! Und wie es immer so sch¨n heißt: Ich bedanke mich noch bei allen. Jens Hatu lak und Nikolai Stiehl mit Mutter(!). CVS und allen Programmierern. die einen Vorschlag f¨r das o u neue Logo gemacht haben. u o Dann darf ich nat¨rlich die ganzen Kritiker. Christoph Reeg Seite 270 . danken. deren Programme ich auch noch benutzt habe. u u Als erstes und wichtigstes muß ich nat¨rlich allen Programmierern von Linux. allen voran Stefan Nagelschmitt. was es jetzt hoffentlich ist. Ich hoffe. Ghostview. die ich vergessen o habe. es kommen noch ein paar dazu. die dieses Dokument erst zu dem gemacht haben.D Danksagungen Bei so einem Werk d¨rfen die Danksagungen nat¨rlich nicht fehlen. xEmacs. L TEX. XFree86. nicht vergessen. u A MySQL. Apache. Es waren viele. Ein besonderes Dankesch¨n geht an die kreativen Leser. Denn erst durch sie ist die Grundlage f¨r dieses Dokument m¨glich geworden. PHP.

continue • PHP: Variable Variablen • PHP: Typensichere Vergleiche • PHP: Warn-/Fehlermeldungen anzeigen • PHP/MySQL: Tips und Tricks (Abfragen mit IN) • PHP/MySQL: Einf¨gen mit automatischer ID u ¨ • PHP/OO: Referenzsemantik mit Ubung • PHP/OO: Ausblick PHP5 • neues Kapitel: Sessions • viel Kleinkram und Fehlerkorrekturen ¨ • ein paar neue Ubungen • zus¨tzliche PS/PDF Versionen zum ausdrucken a Christoph Reeg Seite 271 .06. Dinge.1 19. zu denen man heute keine Lust hat. break x. n¨chste Woche erst recht nicht zu a tun.2005 • neues Kapitel: Ben¨tigte Software o • Rekursion uberarbeitet ¨ • MySQL: Nested Set etwas erweitert • MySQL: IF Ausdr¨cke in MySQL u • PHP: foreach-Schleife. E.E Versionen Aufschieben ist die große Kunst.

4 27. Versionen 13.2001 • Kapitel zu regul¨ren Ausdr¨cken hinzugef¨hrt a u u • Vorwort erweitert • Literaturverzeichnis komplettiert • require(). SQL und HTML Code hat Syntaxhervorhebung • neues Kapitel uber Baumstrukturen in SQL ¨ • neues Kapitel uber PHPDOC ¨ • neues Kapitel uber das Parsen von URLs ¨ • neues Kapitel uber Objektorientierung ¨ • neues Kapitel uber XML ¨ • neues Kapitel uber Templates ¨ • PHP: Funktionen (s)printf und number format • Beispielscripte Banner.und PDF-Versionen etwas verbessert • Mailingliste f¨r neue Versionen u • Autorenvorstellung • viel Kleinkram E.05.04.2002 • PHP. SDA und G¨stebuch hinzugef¨gt a u • Kapitel uber HTTP-Header erg¨nzt a ¨ • Kapitel Tips & Tricks erstellt • HTML.2002 E.3 22.E. include() besser erkl¨rt a • verschiedene Kapitel etwas erweitert Christoph Reeg Seite 272 .06.05.2 13.2001 • Verbesserungsvorschl¨ge und Korrekturen von Markus Maier und Jens Teich umgea setzt E.

12.2000 ¨ • Ubungen zum Kapitel “Fehlersuche“ hinzugef¨gt u • ausf¨hrliche Erkl¨rung der einzelnen Datentypen hinzugef¨gt u a u • kleine Detailverbesserungen E.10.11.7 19.6 27.2000 ¨ u • Ubung “Ergebnis-Tabelle ausgeben I“ hinzugef¨gt ¨ u • Ubung “Ergebnis-Tabelle ausgeben II“ hinzugef¨gt • ORDER BY-Erkl¨rung erweitert a • mysql_num_rows und mysql_errno mit aufgenommen • Vorwort etwas uberarbeitet ¨ E.2000 • Kapitel ‘PHP & HTTP‘ erweitert • print erkl¨rt a • Beispiel zur Erkl¨rung der Tabellenstruktur hinzugef¨gt a u • Erkl¨rung zu Funktionen etwas uberarbeitet a ¨ E.2000 • Grundzustand Christoph Reeg Seite 273 .2000 E.09.9 27. Versionen 05.8 30.12.2000 • Funktion DATE FORMAT hinzugef¨gt u • kleine Fehler korrigiert E.07.5 05.E.

35 Daten einf¨gen. 47 Boolean. 14 DAYOFMONTH. 89 Attribut. 93 &. 2. 109 Argumente referenzieren. 144 Content-Length. 83 .php3. 51 Content-Disposition. 10 Christoph Reeg Seite 274 . 83 . 31 AVG. 31 create definition. 51 &&. 93 ===. 67 Bedingung. 41 Tabellen.phtml.=.php. 197 Authentifizieren. 59 a Daten ausgeben. 85 . 34 u Daten l¨schen.Index *=. 93 >. 30 CREATE TABLE. 88 break. 98 Cache-Control. 145 Content-Type. 51. 15 Datenmodellierung. 85 +=. 206 <. 83. 86 Anf¨hrungszeichen. 145 Content-Transfer-Encoding. 197 Batch-Betrieb. 52 Daten ¨ndern. 52 DAYOFYEAR. 93 >=. 261 COS. 53 CREATE DATABASE. 41 ALL. 85 –. 8 argument swapping. 50 COUNT. 144. 85 . 52 DB. 83 ::. 30 Datenmodell. 195 ALTER TABLE.. 10 Datenbank anlegen. 52 DAYOFWEEK. 51 0x. 148 CASE. 50 Alias. 85 ++. 146 Copyright. 53 Basisklasse. 87 =. 31 Data Base. 36 allgemeiner Konstruktor. 59 AND. 85 . 97. 93 <=. 142 AUTO INCREMENT. 87 0. 58 o Datenbank. 41 Spalten. 109 Argumente wiederverwenden. 109 Array. 98 CONCAT. 51. 42 BETWEEN. 27 Baumstruktur. 93 ==. 143 ABS. 88 u Apache. 10 DATE FORMAT.

15 ELSE. 51 LIKE. 50 DELETE FROM. 56 Joins. 142 Unauthorized. 145 Content-Type. 51 LEFT. 149 Location. 39 header. 93 o Gr¨ßergleich. 142 Hexadezimalzahl. 141 Cache-Control. 151 escaped. 88 Exklusiv-ODER. 93 o GROUP BY. 10 DBS. 149 Float. 31 Fremdschl¨ssel. 95 in SQL. 96 Double. 86 Last-Modified. 149 Last-Modified. 54 kartesisches Produkt. 87 HTTP-Status 200. 195. 142 WWW-Authenticate.Index Index DBMS. 29 Kommentieren. 198 Kurschlußlogik. 203 Klassenvariablen in PHP. 91 DEGREES. 201 Kleiner. 224 Expires. 47 LIMIT. 144 Content-Length. 10 DDL. 87 JavaDoc. 105 Funktionen. 96 FOREIGN KEY. 21 Destruktor. 146 Expires. 36 DO . 196. 87 MySQL. 145 Content-Transfer-Encoding. 91 Konstruktor. 142 302. . 34 Instanz. 27 DISTINCT. 102 include once. 50. 48 include(). 88 floor. 83 Eindeutigkeit. 195. 197 Instanzvariablen in PHP. 54 Klasse. 144. 142 404. 54 Outer. 161 Konstanten. 94 ELSEIF. . 105 get parent class. 58 Denormalisieren. 88 Download. 34 echo. 142 IF. 202 Klassendefinition auslagern. 105 INSERT INTO. 93 Kommentar. 1 DROP TABLE. 149 LCASE. WHILE. 77 IN. 141 401. 201 Integer. 93 Kleinergleich. 94 Equi-Join. 93. 141 Not Found. 39 Christoph Reeg Seite 275 . 89 FOR. 54 ereg. 161 Join Equi. 86 expat. 93 Gr¨ßer. 208 Gleich. 197 Klassen kommentieren. 13 define(). 148 Content-Disposition. 198 dialogorientiert. 17 u function.

51 Not Found. 200 PHP-Code-Markierungen. 203 Objektorientierte Programmierung. 53 MOD. 18 3. 55 Serverseitig. 83 PHPDoc. 51. 50 RAND(). 31 printf. 105 REVERSE. 43. 16 1. 206 PCRE. 51. 141 LOWER. 50 Schl¨ssel. 209 PHP objektorientiert. 27 MySQL Nutzer. 197 MIN. 200 OOP. 192 Open Publication License. 16 2. 45. 66 PI. 14 reference definition. 82 PHP 5.. 51 ROUND. 51. 197 Objekte in PHP. 106 private. 82 Sessions. 21 NOT. 196 protected. 85 OR. 196. 247 mysql insert id(). 87 OO. 151 a u regular expressions. 51 MAX. 135 mysql error(). 161 PHPMyAdmin.. 13. 15 public. 134 mysql fetch row().. 261 deutsch. 247 mysql num rows(). 196 Prozeßdaten. 263 englisch. 261 Operatoren. 50 MONTH. 31. 24 require. 217 SHOW. 151 Prim¨rschl¨ssel. 135 mysql fetch array(). 151 Rekursion. 51 LTRIM. 52 mysql. 192 OO in PHP. 41 Christoph Reeg Seite 276 . 13. 66 mysql close(). 69 NICHT. 133 Nested Set. 31 Referenzierung in PHP. 86 ORDER BY. 56 parent. 192 ODER. 50 preg.. 203 regul¨re Ausdr¨cke. 151 PHP. 135 mysql num fields(). 53 Mehrfach-Argumentierung. 142 NULL. 132 mysql errno(). 134 mysql field name(). 86 Normalform. 102 require once. 192 Objektorientierung. 109 Methode. 50 POW. 133 mysql connect(). 17 a u PRIMARY KEY. 58 Objekt. 20 5. 82 SELECT. 135 mysql query(). 17 u Script. 114 Relationen. 46. 33 Spalten-Alias. 37 Outer-Join.Index Index Location. 86 Oktalzahl. 35 Self-Join.. 18 4. 65 Redundanz. 196 RAND.

86 Ungleich. 1. 42 where definition. 41 Table xx doesn’t exist. 85 SUM. 93 Version. 86 YEAR. 95 XML. 51. 31 UNIX TIMESTAMP.Index Index sprintf. 52 Christoph Reeg Seite 277 . 195 static. 51 URL. 34 o Tabellen Alias. 224 XML-Parser. 206 Stil. 224 XOR. 88 Strings verbinden. 234 TRUNCATE. 59 ¨ Tabelle l¨schen. 149 USE. 157 Variable Variablen. 51 UND. 52 UPDATE. 111 Stilistisches. 30 VAR DUMP. 224 XML-Dokumente. 52 WHERE. 8 WEEK. 110 SQRT. 98 Tabelle andern. 53 SWITCH. 50 Standardkonstruktor. 21 String. 59 UPPER. 1 Webserver. 42 WHILE. 28. 194 Vergleiche mit 0. 93 UNIQUE. 111 Streifendiagramm. 50 UCASE. 92 Vererbung. 64 Templates.

Sign up to vote on this title
UsefulNot useful