PHP 4 IT–Tutorial Bill McCarty PHP 4 IT-Tutorial Übersetzung aus dem Amerikanischen von Reinhard Engel Die Deutsche Bibliothek – CIP-Einheitsaufnahme Ein Titeldatensatz für diese Publikation ist bei der Deutschen Bibliothek erhältlich ISBN 3-8266-0819-4 1. Auflage 2002 Alle Rechte, auch die der Übersetzung, vorbehalten. Kein Teil des Werkes darf in irgendeiner Form (Druck, Kopie, Mikrofilm oder einem anderen Verfahren) ohne schriftliche Genehmigung des Verlages reproduziert oder unter Verwendung elektronischer Systeme verarbeitet, vervielfältigt oder verbreitet werden. Der Verlag übernimmt keine Gewähr für die Funktion einzelner Programme oder von Teilen derselben. Insbesondere übernimmt er keinerlei Haftung für eventuelle, aus dem Gebrauch resultierende Folgeschäden. Die Wiedergabe von Gebrauchsnamen, Handelsnamen, Warenbezeichnungen usw. in diesem Werk berechtigt auch ohne besondere Kennzeichnung nicht zu der Annahme, dass solche Namen im Sinne der Warenzeichen- und Markenschutz-Gesetzgebung als frei zu betrachten wären und daher von jedermann benutzt werden dürften. Übersetzung der amerikanischen Originalausgabe: Bill McCarty PHP4: A Beginner´s Guide Text Copyright © 2001 by The McGraw-Hill Companies, California. All rights reserved including the right of reproduction in whole part or in a part in any form. Printed in Germany © Copyright 2002 by mitp-Verlag/Bonn ein Geschäftsbereich der verlag moderne industrie Buch AG & Co. KG, Landsberg All rights reserved Lektorat: Sabine Schulz Korrektorat: Friederike Daenecke Druck: Media-Print, Paderborn Umschlaggestaltung: Christian Kalkert Satz und Layout: Typographie & Computer, Jörg Gitzelmann, Krefeld 5 Inhaltsverzeichnis Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Teil I Grundlegende PHP-Programme schreiben 1 PHP-Programme erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein PHP-Skript erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . PHP-Skripts schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das PHP-Codegerüst schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Output für einen Webbrowser erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein PHP-Skript dokumentieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein PHP-Skript ausführen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein PHP-Skript heraufladen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein Skript ausführen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 1-1: Ein erstes PHP-Skript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehler in einem Skript suchen und beseitigen . . . . . . . . . . . . . . . . . . . . . . . Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 22 22 22 25 26 28 28 30 31 32 34 2 PHP-Bausteine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zahlen und Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zahlen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Literale und Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 2–1: Die Werte einer PHP-Variablen anzeigen . . . . . . . . . . . . . . . . . . . . Skalare und Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Operatoren und Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 2–2: Eine Berechnung in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 36 36 38 39 42 43 45 45 48 49 51 3 HTML-Formulare erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Grundlagen des Formularentwurfs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein Formular entwerfen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein HTML-Formular erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 3–1: Formularfelder anzeigen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Formular-Controls erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Angepasste Textfelder erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Textbereiche erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 54 54 56 61 62 62 63 6 PHP 4 IT-Tutorial Passwortfelder erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kontrollkästchen erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Optionsfelder erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Auswahllisten erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verborgene Felder erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 3–2: HTML-Formular-Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mehr über das Abschicken eines Formulars . . . . . . . . . . . . . . . . . . . . . . . . . . . . Daten mit einer Bildschaltfläche abschicken . . . . . . . . . . . . . . . . . . . . . . . . Eine RESET-Schaltfläche erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Seite mit mehreren Formularen erstellen . . . . . . . . . . . . . . . . . . . . . . Einem Skript per Link Daten zur Verfügung stellen . . . . . . . . . . . . . . . . . Projekt 3–3: Eine HTML-Seite mit mehreren Formularen . . . . . . . . . . . . . . . Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 64 65 65 66 69 73 74 74 75 76 78 81 4 Auf Daten zugreifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Daten eines Formulars empfangen und verarbeiten . . . . . . . . . . . . . . . . . . . . . . Output an den Browser senden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Werte von Variablen in Strings einbetten . . . . . . . . . . . . . . . . . . . . . . . Projekt 4–1: Die E-Mail-Adressbücher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Daten einer Umgebungsvariablen abfragen und benutzen . . . . . . . . . . . . . . . . Projekt 4–2: Umgebungsvariablen anzeigen . . . . . . . . . . . . . . . . . . . . . . . . . . . . Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 84 86 88 89 91 95 96 5 Mit skalaren Werten arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mit Konstanten und dynamischen Variablen arbeiten . . . . . . . . . . . . . . . . . . . . Mit Konstanten arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mit dynamischen Variablen arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mit Datentypen arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Automatische Typumwandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Manuelle Typumwandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 5–1: Ein einfacher Rechner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 5–2: Ein Datumsrechner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 5–3: Ein Nachrichtengenerator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 98 98 99 101 101 102 105 107 110 114 Teil II Fortgeschrittenere PHP-Programme schreiben 6 Kontrollbefehle schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mit Wahrheitswerten arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einfache if-Befehle schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 6–1: Numerische Werte testen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Komplexere if-Befehle schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . switch-, break- und default-Befehle schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . for-Befehle schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 118 122 123 125 127 130 7 while- und do while-Befehle schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 Projekt 6–2: Benutzereingaben überprüfen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 7 Mit Funktionen arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Funktion verwenden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dateien einbinden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Funktion definieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine benutzerdefinierte Funktion aufrufen . . . . . . . . . . . . . . . . . . . . . . . . . Die Ausführung einer Funktion beenden . . . . . . . . . . . . . . . . . . . . . . . . . . . Rekursive Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Standardargumente definieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . PHP-Variablen und -Referenzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Globale Variablen verwenden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lokale und statische Variablen verwenden . . . . . . . . . . . . . . . . . . . . . . . . . . Referenzen benutzen (PHP4) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 7–1: Eine Überarbeitung des Kontaktformulars . . . . . . . . . . . . . . . . . . . Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 144 145 147 148 149 149 150 152 152 153 155 157 164 8 Mit Arrays arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arrays erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein Array mit einer Zuweisung erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . Mit der array()-Funktion arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein Array elementweise durchlaufen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein sequenzielles Array elementweise durchlaufen . . . . . . . . . . . . . . . . . . . Ein sequenzielles Array durchsuchen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der break-Befehl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der continue-Befehl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein nichtsequenzielles Array elementweise durchlaufen . . . . . . . . . . . . . . . Mit Listenfunktionen arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die key()-Funktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die each()-Funktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die list()-Funktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arrays sortieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 8–1: Eine Überarbeitung des Kontaktformulars . . . . . . . . . . . . . . . . . . . Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 166 166 168 170 171 171 172 173 174 176 177 177 178 179 182 185 9 Strings verwenden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Strings erstellen und anzeigen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zusätzliche Escape-Sequenzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mit ASCII-Codes arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Strings in einfachen Anführungszeichen . . . . . . . . . . . . . . . . . . . . . . . . . . . Formatierten Output erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Strings manipulieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Länge eines Strings ermitteln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 188 188 189 190 191 195 195 8 PHP 4 IT-Tutorial Einen String beschneiden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Strings komplett in Groß- oder Kleinbuchstaben umwandeln . . . . . . . . . Strings vergleichen und durchsuchen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Strings vergleichen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Substrings suchen und extrahieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einen Substring ersetzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Reguläre Ausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 9–1: Reguläre Ausdrücke testen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196 197 198 198 200 202 203 207 212 Teil III Mit gespeicherten Daten arbeiten 10 Mit Cookies arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215 Auf Cookies zugreifen und Cookies erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . Auf ein Cookie zugreifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein Cookie erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein Cookie löschen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fortgeschrittene Cookie-Verfahren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mehrere Werte in einem Cookie speichern . . . . . . . . . . . . . . . . . . . . . . . . Den Zugriff auf ein Cookie und andere Optionen festlegen . . . . . . . . . . . Projekt 10–1: Eine Login-Seite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216 216 217 219 219 220 221 224 227 11 Mit Dateien und Verzeichnissen arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das UNIX-Dateisystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mit UNIX-Dateien arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mit UNIX-Verzeichnissen arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mit Dateien arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Besitz- und Berechtigungsfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Attribute einer Datei ermitteln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dateiberechtigungen ändern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Den Besitz einer Datei ändern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Datei öffnen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Den Abschluss einer Dateioperation prüfen . . . . . . . . . . . . . . . . . . . . . . . . Eine Datei schließen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Datei lesen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . In einer Datei navigieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . In eine Datei schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 11–1: Ein Seitenzugriffszähler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exklusiven Zugriff auf eine Datei erhalten . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 11–2: Ein verbesserter Seitenzugriffszähler . . . . . . . . . . . . . . . . . . . . . . Eine Datei kopieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Datei umbenennen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Datei löschen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 230 230 239 245 245 246 249 249 250 252 253 254 257 259 260 262 264 266 267 268 9 Mit Verzeichnissen arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das Arbeitsverzeichnis ermitteln und setzen . . . . . . . . . . . . . . . . . . . . . . . . Pfade manipulieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verzeichnisberechtigungen anzeigen und ändern . . . . . . . . . . . . . . . . . . . . Verzeichnisinhalte lesen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein Verzeichnis erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein Verzeichnis löschen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 11–3: Ein Adressbuch-Browser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 270 271 272 272 273 274 275 280 12 E-Mail senden und empfangen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281 E-Mail senden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 12–1: Skript zur Übermittlung von E-Mail-Daten . . . . . . . . . . . . . . . . E-Mail empfangen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Mailbox öffnen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ordner wechseln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Mailbox schließen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Informationen über eine Mailbox abfragen . . . . . . . . . . . . . . . . . . . . . . . . . Eine Liste von Nachrichten abfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mit Nachrichten-IDs arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Informationen über eine Nachricht abfragen . . . . . . . . . . . . . . . . . . . . . . . . Den Körper einer Nachricht abrufen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nachrichten-Header abrufen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Nachricht zum Löschen kennzeichnen . . . . . . . . . . . . . . . . . . . . . . . . Projekt 12–2: Ein E-Mail-Browser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ordner manipulieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vorhandene Ordner anzeigen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ordner erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einen Ordner umbenennen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einen Ordner löschen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nachrichten in einen Ordner kopieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nachrichten in einen Ordner verschieben . . . . . . . . . . . . . . . . . . . . . . . . . . Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 284 287 288 290 291 292 295 295 296 297 297 299 301 308 308 309 309 310 310 311 313 13 Leitfaden für relationale Datenbanken und SQL . . . . . . . . . . . . . . . . . . . . 315 Grundbegriffe relationaler Datenbanken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Struktur einer relationalen Datenbank . . . . . . . . . . . . . . . . . . . . . . . . . Warum relationale Datenbanken? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Gemeinsames Nutzen von Daten erleichtern . . . . . . . . . . . . . . . . . . . . . . . Die Unabhängigkeit von Daten gewährleisten . . . . . . . . . . . . . . . . . . . . . . . Ad-hoc-Abfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Daten organisieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datensicherheit herstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die erforderlichen Programmkenntnisse minimieren . . . . . . . . . . . . . . . . . Berechnungen effizient durchführen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Über den Einsatz eines relationalen DBMS entscheiden . . . . . . . . . . . . . . 316 316 318 319 319 319 320 320 320 321 321 10 PHP 4 IT-Tutorial Datenbanken implementieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datenbanken entwerfen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . E-R-Modellierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Datenbank normalisieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . E-R-Modelle verfeinern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine MySQL-Datenbank erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Auf Datenbankdaten zugreifen: SQL-Abfragen . . . . . . . . . . . . . . . . . . . . . . . . . Datenbankdaten ändern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sortieren, aggregieren und gruppieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ausdrücke und Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Joins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 13–1: Mit SQL arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 323 323 327 331 333 338 342 346 349 352 355 359 Teil IV Fortgeschrittene PHP-Funktionen verwenden 14 Auf relationale Datenbanken zugreifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 Mit MySQL-Datenbanken arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Verbindung zu dem MySQL-Server herstellen . . . . . . . . . . . . . . . . . . Die Datenbank auswählen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehlersuche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Unerwünschte Fehler und Warnungen unterdrücken . . . . . . . . . . . . . . . . Die MySQL-Serververbindung schließen . . . . . . . . . . . . . . . . . . . . . . . . . . UPDATE-, INSERT- und DELETE-Abfragen . . . . . . . . . . . . . . . . . . . . . . . . . Die mysql_query()-Funktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Abfragen prüfen, die keine Tabellenzeilen zurückgeben . . . . . . . . . . . . . . . . . . Mit Auto_Increment-Tabellenspalten arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . Das Ergebnis von SELECT-Abfragen verarbeiten . . . . . . . . . . . . . . . . . . . . . . . Mit Ergebnismengen arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Anzahl der Spalten in einer Ergebnismenge abfragen . . . . . . . . . . . . . Den Namen einer Ergebnismengenspalte abfragen . . . . . . . . . . . . . . . . . . Die Länge einer Ergebnismengenspalte abfragen . . . . . . . . . . . . . . . . . . . . Die MySQL-Flags einer Ergebnismengenspalte abfragen . . . . . . . . . . . . . Den MySQL-Typ einer Ergebnismengenspalte abfragen . . . . . . . . . . . . . Die MySQL-Tabelle einer Ergebnismengenspalte abfragen . . . . . . . . . . . Die komplette Struktur der Ergebnismenge abfragen . . . . . . . . . . . . . . . . Ergebnismengenzeilen nichtsequenziell abfragen . . . . . . . . . . . . . . . . . . . . Das DBMS untersuchen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Datenbanken abfragen, die von einem Server verwaltet werden . . . . Die Tabellen abfragen, die in einer Datenbank enthalten sind . . . . . . . . . Die Spalten einer Tabelle abfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364 364 366 366 367 368 369 369 370 371 373 377 378 378 379 379 380 380 381 383 384 384 385 386 11 Quotes und Magic-Quotes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Magic-Quotes („Magische Anführungszeichen“) . . . . . . . . . . . . . . . . . . . . Escaping und Unescaping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Escape-Zeichen bei HTML-Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Escape-Zeichen und URLs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Andere Datenverwaltungswerkzeuge unter PHP . . . . . . . . . . . . . . . . . . . . . . . . PostgreSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ODBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . LDAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 14–1: Ein Adressbuch-Browser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 389 390 391 392 394 394 395 396 396 398 404 15 Mit Klassen und Objekten arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405 Was heißt „objektorientiert“? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Klasse definieren und instantiieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein Objekt instantiieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einen Konstruktor definieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mit Vererbung arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Geerbte Methoden überschreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine überschriebene Methode aufrufen . . . . . . . . . . . . . . . . . . . . . . . . . . . . Objekt-Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 15–1: Mit Objekten arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406 407 408 410 411 412 414 415 416 418 421 425 16 Mit Anwendungs-Templates arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427 Einführung in Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mit einer Template arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Template-Datei erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein FastTemplate-Objekt instantiieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Template-Datei mit einer Template-Variablen verbinden . . . . . . . . . . Den Template-Variablen Werte zuweisen . . . . . . . . . . . . . . . . . . . . . . . . . . Die Template-Variable der Template-Datei parsen . . . . . . . . . . . . . . . . . . . Die Template-Variable mit dem Ergebnis ausgeben . . . . . . . . . . . . . . . . . . Eine komplette Website konstruieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 16–1: Mit Templates arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 428 429 430 430 431 431 432 432 432 434 438 17 PHP-Skripts debuggen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439 Debuggen und häufige Programmierfehler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehler verstehen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Syntaxfehler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehlermeldungen zur Laufzeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Falscher oder fehlender Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440 441 442 443 445 12 PHP 4 IT-Tutorial Die Verwaltung von Fehlermeldungen in PHP . . . . . . . . . . . . . . . . . . . . . . . . . Fehlermeldungen vermeiden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehlermeldungen unterdrücken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehlermeldungen protokollieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Kunst und die Praxis des Debuggens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Symptome reproduzieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehler lokalisieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehler verstehen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehler beheben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das Programm testen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Projekt 17–1: PHP-Fehlermeldungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446 447 448 449 451 452 453 455 455 456 457 460 Teil V Anhänge A Übungsaufgaben: Lösungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463 Kapitel 1: PHP-Programme erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kapitel 2: PHP-Bausteine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kapitel 3: HTML-Formulare erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kapitel 4: Auf Daten zugreifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kapitel 5: Mit skalaren Werten arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kapitel 6: Kontrollbefehle schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kapitel 7: Mit Funktionen arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kapitel 8: Mit Arrays arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kapitel 9: Mit Strings arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kapitel 10: Mit Cookies arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kapitel 11: Mit Dateien und Verzeichnissen arbeiten . . . . . . . . . . . . . . . . Kapitel 12: E-Mail senden und empfangen . . . . . . . . . . . . . . . . . . . . . . . . . Kapitel 13: Einführung in relationale Datenbanken und SQL . . . . . . . . . . Kapitel 14: Auf relationale Datenbanken zugreifen . . . . . . . . . . . . . . . . . . Kapitel 15: Klassen und Objekte verwenden . . . . . . . . . . . . . . . . . . . . . . . . Kapitel 16: Anwendungs-Templates verwenden . . . . . . . . . . . . . . . . . . . . Kapitel 17: PHP-Skripts debuggen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464 464 465 466 466 467 468 469 470 470 471 472 473 473 474 475 476 B PHP installieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477 Red Hat Linux 7.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Apache installieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . PHP installieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MySQL installieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . IMAP installieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MySQL konfigurieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Den Apache-Dienst starten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Installation testen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Andere Linux- und Unix-Versionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478 478 479 479 479 480 480 481 482 13 Windows NT/2000 und 95/98/ME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Apache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . IIS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . PWS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483 484 484 484 484 C PHP-Ressourcen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 485 Websites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486 Mailing-Listen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487 Newsgroups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487 D UNIX-Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 489 Grundlegende UNIX-Begriffe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verzeichnisse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pfade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Benutzerkonten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Benutzergruppen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eigentümerschaft und Berechtigungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . Grundlegende UNIX-Techniken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein- und ausloggen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einen UNIX-Befehl eingeben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ihr Passwort ändern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Angemeldete Benutzer anzeigen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Prüfen, ob ein Host aktiv ist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . E-Mail lesen und senden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das aktuelle Arbeitsverzeichnis ändern . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verzeichnisinhalte anzeigen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dateiinhalte und Befehlsausgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Datei editieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein Verzeichnis erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Datei löschen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein Verzeichnis löschen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Datei oder ein Verzeichnis kopieren . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Datei oder ein Verzeichnis umbenennen . . . . . . . . . . . . . . . . . . . . . . . Shell-Metazeichen und Name-Globbing . . . . . . . . . . . . . . . . . . . . . . . . . . . Die UNIX-Online-Dokumentation lesen . . . . . . . . . . . . . . . . . . . . . . . . . . Die Verwendung des Festplattenplatzes anzeigen . . . . . . . . . . . . . . . . . . . . Den Besitzer einer Datei festlegen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dateiberechtigungen setzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Datei suchen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Datei suchen, die einen bestimmten Text enthält . . . . . . . . . . . . . . . . Den Typ einer Datei ermitteln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Textdateien vergleichen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mit komprimierten Dateien arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mit Tarballs arbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dateien von und auf Remote-Hosts übertragen . . . . . . . . . . . . . . . . . . . . . 490 491 491 492 493 494 494 496 496 497 498 498 499 499 500 500 502 502 503 503 503 504 504 504 505 506 507 507 508 509 509 509 510 511 512 14 PHP 4 IT-Tutorial E Fluchtzeichen (Escapes) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513 F ASCII . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515 G PHP-Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519 H Sicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523 I Bedrohungen und Risiken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Gegenmaßnahmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Authentifizierung und Autorisierung von Benutzern . . . . . . . . . . . . . . . . Benutzereingaben misstrauen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kryptographische Maßnahmen einsetzen . . . . . . . . . . . . . . . . . . . . . . . . . . Server korrekt konfigurieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datenbanken sichern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ressourcen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 524 526 526 527 527 527 528 528 PHP-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Array-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ausgabekontrollfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dateisystemfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datums- und Zeitfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehlerbehandlungs- und Protokollfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . FTP-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . HTTP-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . IMAP-, POP3- und NNTP-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kalenderfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Klassen/Objekt-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mail-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mathematische Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MySQL-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . PHP-Optionen und -Informationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Programmausführungsfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . POSIX-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . POSIX-Funktionen für erweiterte reguläre Ausdrücke . . . . . . . . . . . . . . . . . . . Rechtschreibfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sitzungsverwaltungsfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . String-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . URL-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Variablen-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verschiedene Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verzeichnisfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zeichenfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 529 531 533 534 536 537 538 539 539 542 543 544 544 546 548 550 550 551 552 552 553 557 557 558 559 560 Stichwortverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561 Einleitung Einleitung PHP gehört zu den aufregendsten Programmiertechniken, die heute zur Verfügung stehen. Weil es einfach zu bedienen ist und gleichzeitig über hoch entwickelte Fähigkeiten verfügt, ist PHP schnell zu einem führenden Werkzeug für die Webentwicklung geworden. Doch im Gegensatz zu anderen beliebten Werkzeugen für die Webentwicklung – wie beispielsweise Perl – ist PHP eine komfortable Programmiersprache, die auch für Anfänger geeignet ist – selbst wenn diese vorher noch nie programmiert haben. Wenn Sie HTML kennen, aber über keine Programmiererfahrungen verfügen, fragen Sie sich vielleicht, welche zusätzlichen Möglichkeiten die Kenntnis von PHP bieten kann. Ähnlich wie mit anderen Web-Skriptsprachen können Sie mit PHP dynamische Webinhalte bereitstellen, d.h. Webinhalte, die sich automatisch von Tag zu Tag oder gar von Minute zu Minute ändern. Dynamische Inhalte bilden einen wichtigen Faktor zur Aufrechterhaltung eines permanenten Website-Verkehrs. Normalerweise kehren Besucher nicht mehr zu einer Webseite zurück, wenn sie dort dieselben Informationen wie bei ihrem letzten Besuch vorfinden. Dagegen können Websites, die häufig aktualisiert werden, einen erheblichen Verkehr auf sich ziehen. Darüber hinaus wird PHP im Gegensatz zu anderen Skriptsprachen, wie beispielsweise JavaScript, auf dem Webserver und nicht in dem Webbrowser ausgeführt. Folglich kann PHP auf Dateien, Datenbanken und andere Ressourcen zugreifen, die für JavaScript unzugänglich sind. Diese Ressourcen bilden die reichhaltigen Quellen für die dynamischen Inhalte, die Besucher anziehen. Dieses Buch soll Sie in die Programmierung und Webentwicklung mit PHP einführen. Es sollte ganz klar sein, dass dieses Buch selbst nur einen Startpunkt bildet. Die Webentwicklung ist eine anspruchsvolle Aktivität, und ein angehender Webentwickler muss über viele Fähigkeiten verfügen – das Programmieren ist nur eine davon. Ich bin mir sicher, dass dieses Buch für angehende Webentwickler ein nützlicher und freundlicher Helfer auf ihrem Weg zum PHP-Programmierer ist. Außerdem wurde sorgfältig darauf geachtet, dass das Buch die Grundlage für das weitere Studium schafft, das erforderlich ist, um PHP zu meistern. Nach dem Studium dieses Buches verfügen Sie über die Grundlagen, 15 16 PHP 4 IT-Tutorial um mehr über fortgeschrittene PHP-Funktionen und -Fähigkeiten, wie beispielsweise XML, LDAP und E-Commerce, zu lernen. Wie dieses Buch aufgebaut ist Dieses Buch beginnt mit den Grundlagen: Zunächst wird erklärt, wie PHP funktioniert, dann wird beschrieben, wie PHP-Programme erstellt werden, wobei auch kleine, aber wichtige Einzelheiten – wie beispielsweise das Heraufladen von PHP-Skripts – erläutert werden. Sie erhalten einen Überblick über die HTMLGrundlagen und werden über HTML-Formulare informiert. In siebzehn Kapiteln werden Sie Schritt für Schritt in das Programmieren im Allgemeinen und in PHP im Besonderen eingeführt, wobei jedes Kapitel Elemente enthält, die dazu dienen sollen, den Stoff fest in Ihrem Gedächtnis zu verankern und Ihr Wissen zu fördern. Zusätzlich enthält das Buch ein Kapitel (Kapitel 13), das die Grundlagen von relationalen Datenbanken erläutert. Lernziele Jedes Kapitel beginnt mit einer Reihe ausdrücklicher Lernziele, sodass Sie eine Vorstellung davon bekommen, wie das jeweilige Kapitel in das Gesamtthema einzuordnen ist. Übungsaufgaben Jedes Kapitel verfügt am Ende über eine Lernkontrolle, einen Selbsttest, der Ihnen hilft, Ihren Fortschritt zu bewerten. Die Antworten zu den Fragen dieser Tests finden Sie in Anhang A. 1-Minuten-Tests Jeder Hauptabschnitt des Buches enthält einen 1-Minuten-Test, einen Selbsttest, der Ihnen helfen soll, am Lenkrad nicht einzuschlafen. Die Antworten zu den Fragen der 1-Minuten-Tests finden Sie am unteren Rand der jeweiligen Seite. Fragen an den Experten Dieses Buch enthält viele Einschübe, die so genannten Fragen an den Experten, die dazu dienen, das Material des betreffenden Kapitels zu erweitern und vertiefen. Häufig enthalten sie fortgeschritteneres Material, das für PHP-Neulinge nicht erforderlich ist, das Ihnen aber hilft, ein Verständnis für PHP-Probleme mittleren Einleitung Schwierigkeitsgrads zu entwickeln. Diese Fragen an den Experten-Einschübe sind in einem Frage/Antwort-Format aufgebaut. Projekte Jedes Kapitel enthält ein oder mehrere Projekte, die Ihnen zeigen, wie Sie die Konzepte und Techniken anwenden können, die in dem betreffenden Kapitel erklärt wurden. Sie können diese Projekte als Basis für Ihr weiteres Studium und für Experimente verwenden. Häufig bildet ein Projekt einen guten Ausgangspunkt für ein eigenes praktisch anwendbares Programm. Keine vorherige Programmiererfahrung erforderlich Dieses Buch geht davon aus, dass Sie über HTML-Grundkenntnisse verfügen. Darüber hinaus wird kaum etwas vorausgesetzt, insbesondere nicht, dass Sie bereits programmiert haben. Deswegen wird beschrieben, wie HTML-Formulare erstellt werden, wie programmiert wird und wie PHP verwendet wird. Sie erfahren alles, was Sie wissen müssen, um mit PHP einfache, durch Datenbanken unterstützte Websites zu entwickeln. Erforderliche Software Um die Beispiele und Projekte in diesem Buch nachvollziehen zu können, benötigen Sie einen Zugang zu einem PHP-Server, der PHP, Version 4, ausführt. Mit Hilfe der Informationen in Anhang B können Sie PHP auf Ihrem PC installieren; aber als Neuling ist es für Sie jedoch wahrscheinlich bequemer, einen PHPServer zu benutzen, der von jemand anderem verwaltet wird. Anhang C nennt einige Websites, auf denen Sie Internet Service Provider (ISPs) finden können, die PHP unterstützen. Viele ISPs stellen PHP für recht geringe monatliche Gebühren zur Verfügung. Apache, PHP und MySQL finden Sie auch auf der CD zum Buch. Nicht vergessen: Code im Web Der Quellcode für alle Beispiele und Projekte in diesem Buch finden Sie auf der CD zum Buch. 17 Teil I Grundlegende PHP-Programme schreiben Kapitel 1 PHP-Programme erstellen Lernziele ● Wie ein PHP-Skript erstellt wird ● Wie PHP-Befehle geschrieben werden, die Text zu einem Webbrowser senden ● Wie ein PHP-Skript dokumentiert wird ● Wie ein PHP-Skript per FTP auf einen Server heraufgeladen wird ● Wie ein PHP-Skript ausgeführt wird 22 PHP 4 IT-Tutorial In diesem Kapitel werden Sie lernen, wie PHP-Programme erstellt und ausgeführt werden. Wenn PHP nicht auf Ihrem System installiert ist, können Sie die PHP-Beispielprogramme in diesem Kapitel nicht ausführen. Bevor Sie diese Programme ausprobieren können, sollten Sie PHP installieren und testen, indem Sie den Anweisungen in Anhang B folgen. Ein PHP-Skript erstellen Ein PHP-Skript kann sehr einfach oder ziemlich komplex sein. Doch selbst das Erstellen eines komplexen PHP-Skripts ist ziemlich unproblematisch und erfordert nur einen gewöhnlichen Texteditor. In diesem Abschnitt werden Sie lernen, wie Sie einfache PHP-Skripts erstellen können, die Text-Output an einen Webbrowser senden. Sie werden ebenfalls lernen, wie Sie Ihre Skripts dokumentieren können, sodass Sie und andere sich schnell einen Überblick über den Zweck und die Struktur der Skripts verschaffen können. PHP-Skripts schreiben Die meisten PHP-Programmierer verwenden einen gewöhnlichen Texteditor, um PHP-Skripts zu erstellen. Sie können einen beliebigen Texteditor Ihrer Wahl benutzen. Unter Microsoft Windows verwenden PHP-Programmierer häufig den Windows-Editor Notepad. Sie können auf Wunsch auch ein Textverarbeitungsprogramm wie beispielsweise Microsoft Word benutzen. Wenn Sie jedoch nicht mit Notepad, sondern mit einem anderen Werkzeug arbeiten, müssen Sie darauf achten, Ihr Skript als Text-Dokument zu speichern; andernfalls enthält die Skriptdatei Formatierungsinformationen, die der PHP-Server nicht verarbeiten kann. Wenn Sie unter UNIX oder Linux arbeiten, können Sie PHP-Skripts mit Hilfe eines Programms wie beispielsweise vi, emacs oder pico erstellen. Es spielt wirklich keine Rolle, welches Programm Sie wählen, solange Sie mit dem Programm ASCII-Textdateien erstellen können. Das PHP-Codegerüst schreiben Jedes PHP-Programm enthält zwei spezielle Zeilen, die dem PHP-Server anzeigen, dass der zwischen ihnen stehende Text aus PHP-Befehlen besteht. Diese Zeilen haben gewissermaßen die Funktion einer Klammer, die Ihr PHP-Programm zusammenhält. Wenn Sie ein PHP-Programm schreiben wollen, starten Sie zunächst den Texteditor Ihrer Wahl und geben dann die folgenden zwei Zeilen im Arbeitsbereich des Editors ein: Kapitel 1: PHP-Programme erstellen <?php ?>php 23 1 Frage an den Experten Frage: Wenn ich C-Programme schreibe, arbeite ich mit einer Interactive Development Environment (IDE, dt. Interaktive Entwicklungsumgebung), wie beispielsweise Microsoft Visual C++, die über zahlreiche spezielle Funktionen verfügt, die das Entwerfen, Codieren und Testen meiner Programme unterstützen. Gibt es auch IDEs für PHP? Antwort: Einige Texteditoren, wie beispielsweise vi, verfügen über spezielle Funktionen, um das Schreiben von PHP-Programmen zu unterstützen. Beispielsweise stellt die Funktion der Syntaxeinfärbung von vi verschiedene PHP-Programmelemente in unterschiedlichen Farben dar. Viele PHP-Programmierer sind der Ansicht, dass die Syntaxeinfärbung das Auffinden von Fehlern in Programmen erleichtert. Einige HTML-Editoren, wie beispielsweise HomeSite von Allaire, verfügen über eine Syntaxeinfärbung und andere Funktionen – beispielsweise Online-Handbücher und Funktionen zum Erstellen von Ausdrücken – zur Unterstützung von PHP-Programmierern. Doch wenn Sie gerade erst lernen, PHP-Programme zu schreiben, werden Sie wahrscheinlich mit einem gewöhnlichen Texteditor besser zurechtkommen als mit einem Editor, der mit speziellen PHP-Funktionen ausgestattet ist. Andernfalls verbringen Sie wahrscheinlich einen großen Teil Ihrer Lernzeit damit, mit der Bedienung des Werkzeugs vertraut zu werden, anstatt zu lernen, wie man PHP-Programme schreibt. Erst wenn Sie das Schreiben von PHP-Programmen besser beherrschen, sollten Sie sich mit Werkzeugen befassen, die Sie beim Arbeiten unterstützen könnten. Dann sollten Sie die Liste der PHP-Editoren prüfen, die im Web unter http:// www.itworks.demon.co.uk/phpeditors.htm angeboten wird. Dann speichern Sie Ihr Skriptgerüst als Textdatei unter einem Namen, der die folgenden Regeln erfüllt: ● Der Dateiname sollte nur aus Kleinbuchstaben, Ziffern und Bindestrichen bestehen. Insbesondere Leerzeichen und andere Sonderzeichen sind verboten. ● Die Erweiterung des Dateinamens sollte .php lauten. 24 PHP 4 IT-Tutorial Sie sollten einen aussagekräftigen Namen wählen, der die Funktion Ihres Skripts beschreibt, damit Sie auch einige Wochen oder Monate später schnell feststellen können, was das Skript tut. Bindestriche eignen sich besonders dazu, Dateinamen lesbarer zu machen, die aus mehreren Wörtern zusammengesetzt sind. Beispielsweise könnten Sie eine Datei, die ein PHP-Skript enthält, mit dem ein Lagerbestand angezeigt wird, lagerbestand-anzeigen.php nennen. Dann haben Sie auch später kein Problem herauszufinden, was das Skript tut. Frage an den Experten Frage: Die Regeln zur Benennung der Dateien scheinen ziemlich restriktiv zu sein. Kann ich andere Zeichen verwenden, um Dateien zu benennen, die PHP-Skripts enthalten? Antwort: Ja, das ist möglich. Aber wenn Sie andere Zeichen benutzen, geraten Sie wahrscheinlich in Schwierigkeiten. Beispielsweise spielt die Schreibweise bei Dateinnamen unter Microsoft Windows keine Rolle, während bei UNIX-Dateinamen Groß- und Kleinbuchstaben unterschieden werden. Außerdem schreiben die meisten Betriebssysteme Regeln für Dateinamen vor, die sich von den Regeln für Webadressen (URLs) unterscheiden. Sie können die Probleme, die auf solchen Unterschieden basieren, vermeiden, indem Sie in Dateinamen für PHP-Skripte nur Kleinbuchstaben, Ziffern und Bindestriche verwenden. 1-Minuten-Test ● Welche der folgenden Dateinamen erfüllen die Regeln für Dateinamen von PHP-Skripts? ● ● ● ● ● MyScript.php ● your_script.php ● his-script.php3 ● her-script.php Nein: enthält Großbuchstaben Nein: enthält Unterstreichungszeichen Nein: Dateierweiterung sollte .php lauten Ja Kapitel 1: PHP-Programme erstellen Output für einen Webbrowser erstellen PHP-Programme führen drei grundlegende Arten von Operationen aus: ● Sie nehmen Daten von einem Benutzer entgegen. ● Sie führen Berechnungen aus, greifen auf Daten zu, die in Dateien und Datenbanken gespeichert sind, und manipulieren diese Daten. ● Sie zeigen die Daten so an, dass ein Benutzer sie betrachten kann. Die ersten beiden Operationen sind etwas schwieriger auszuführen als die dritte. Daten für einen Benutzer anzuzeigen ist ziemlich einfach. So wie Absätze eines Textes aus Sätzen bestehen, sind PHP-Programme aus Befehlen aufgebaut. Die Regeln für die Bildung sprachlich korrekter Sätze werden als Syntax bezeichnet. Dasselbe Wort wird auch für die Regeln für die Bildung von PHP-Befehlen verwendet. Beispielsweise hat der PHP-Befehl echo, der einen Output an einen Webbrowser sendet, sodass ein Benutzer ihn lesen kann, die folgende Syntax: echo("Text, der angezeigt werden soll"); Beachten Sie, dass der Befehl mit dem Wort echo beginnt und mit einem Semikolon endet. Klammern und doppelte Anführungszeichen schließen den Textausdruck Text, der angezeigt werden soll ein, der in der Mitte des Befehls steht. Die kursive Darstellung soll ausdrücken, dass Sie fast jeden beliebigen Text anstelle dieses Ausdrucks verwenden können. Doch im Augenblick sollten Sie nur Buchstaben, Ziffern, Leerzeichen und normale Satzzeichen (Komma, Semikolon, Punkt, Fragezeichen und Ausrufezeichen) verwenden. Zusätzlich können Sie die Zeichen <>, mit denen HTML-Tags eingeschlossen werden, und das Zeichen / verwenden, mit dem das schließende Element eines HTML-TagPaars gekennzeichnet wird. Das folgende Beispiel zeigt einen PHP-Befehl, der die ersten Wörter der Präambel des Grundgesetzes ausgibt: echo("<h2>Im Bewusstsein seiner Verantwortung ...</h2>"); Das Paar der h2-Tags bewirkt, dass der Output als Level-2-HTML-Überschrift formatiert wird. 25 1 26 PHP 4 IT-Tutorial Frage an den Experten Frage: Gibt es eine Möglichkeit, spezielle Zeichen wie beispielsweise das doppelte Anführungszeichen in einen echo-Befehl einzuschließen? Antwort: Sie können in Schwierigkeiten geraten, wenn Sie spezielle Zeichen in Ihren Text einschließen wollen. Wenn Sie beispielsweise versuchen, ein doppeltes Anführungszeichen in den Text einzufügen, kommt der PHP-Server durcheinander, weil er doppelte Anführungszeichen nur am Anfang und Ende des Textes erwartet, nicht mitten in einem Text. PHP stellt spezielle Methoden zur Verfügung, um dieses Problem zu vermeiden; mehr darüber erfahren Sie in Kapitel 2. 1-Minuten-Test ● Schreiben Sie einen echo-Befehl, der den Namen Ihrer Lieblingsprogrammiersprache ausgibt. ● Schreiben Sie einen echo-Befehl, der Ihren Namen ausgibt. Ein PHP-Skript dokumentieren Zusätzlich zu aussagekräftigen Namen, die Sie Ihren PHP-Skriptdateien geben, sollten Sie in jedes Skript so genannte Kommentare einfügen. Damit können Sie einem Leser den Zweck des Skripts erläutern und andere Informationen über das Skript liefern. Beispielsweise können Sie in einem Kommentar den Dateinamen des Skripts angeben, damit der Dateiname auf Ausdrucken des Skripts erscheint. Die Syntax für einen PHP-Kommentar lautet: // Fügen Sie hier Ihren Kommentar ein Ein Kommentar beginnt mit zwei Slashes (Schrägstrichen), gefolgt von einem Leerzeichen. Der Rest der Zeile enthält Ihren Kommentar, der beliebige Zeichen oder Sonderzeichen enthalten kann. ● echo("PHP"); oder so ähnlich ● echo("Bill McCarty"); oder so ähnlich Kapitel 1: PHP-Programme erstellen Das folgende Beispiel zeigt ein einfaches PHP-Skript mit Kommentaren: <?php // beispielskript.php // Dieses Skript gibt eine Nachricht an den Benutzer aus. echo("Dies ist ein sehr einfaches Skript."); ?> Frage an den Experten Frage: Wie kann ich einen PHP-Kommentar erstellen, der sich über mehrere Zeilen erstreckt? Antwort: Eine Möglichkeit, einen mehrzeiligen PHP-Kommentar zu erstellen, besteht darin, jede Zeile mit dem //-Zeichen zu beginnen. Jedoch können Sie einen mehrzeiligen Kommentar auch auf andere Weise erstellen: /* Dies ist ein mehrzeiliger Kommentar. Er kann aus beliebig vielen Zeilen bestehen. */ Ein mehrzeiliger Kommentar beginnt mit den Zeichen /* und endet mit den Zeichen */. Zwischen /* und */ kann ein beliebiger Text mit beliebig vielen Zeilen stehen. 1-Minuten-Test ● Schreiben Sie einen PHP-Kommentar, der Ihren Namen enthält. ● Schreiben Sie einen mehrzeiligen PHP-Kommentar, der Ihre Adresse enthält. ● //Bill McCarty ● /* 123 Any Street Anytown, PA 12345 */ 27 1 28 PHP 4 IT-Tutorial Ein PHP-Skript ausführen Nachdem Sie ein PHP-Skript erstellt haben, können Sie es ausführen. Wenn Sie das PHP-Skript nicht auf dem Server erstellt haben, auf dem PHP installiert ist, müssen Sie das Skript zunächst auf einen Server heraufladen. In diesem Abschnitt werden Sie lernen, wie Sie PHP-Skripts heraufladen und ausführen können. Ein PHP-Skript heraufladen Wahrscheinlich benötigen Sie Hilfe, um Ihr PHP-Skript heraufzuladen, weil die Methode davon abhängt, wie Sie auf den Server zugreifen und wie der Systemadministrator den Server konfiguriert hat. Sie sollten deshalb den Systemadministrator Ihres Servers fragen, wie ein Skript heraufgeladen wird. Damit Sie die Antwort Ihres Systemadministrators besser verstehen können, beschreibt dieser Teilabschnitt einige übliche Situationen für das Heraufladen von Skripts. Falls Sie per Telnet oder SSH einen Fernzugriff auf einen UNIX- oder LinuxServer durchführen, müssen Sie das Skript möglicherweise überhaupt nicht heraufladen. Vielleicht müssen Sie nur das Skript in dem passenden Verzeichnis erstellen, das Ihr Systemadministrator festgelegt hat. Wenn Sie mit einem Microsoft-Windows-Server arbeiten, der sich in demselben lokalen Netzwerk wie Ihre Workstation befindet, hat Ihr Systemadministrator möglicherweise auf dem Server ein Unterverzeichnis für Sie freigegeben. In diesem Fall kann das Heraufladen eines PHP-Skripts einfach darin bestehen, die Skriptdatei auf den Server zu kopieren, indem Sie die Datei per Drag-and-Drop in das zur Verfügung gestellte Unterverzeichnis einfügen. Falls sich der Windows-, UNIX- oder Linux-Server nicht in Ihrem lokalen Netzwerk befindet, werden Sie wahrscheinlich ein Programm wie beispielsweise FTP verwenden, um Ihr Skript heraufzuladen. Um ein Skript per FTP heraufzuladen, bitten Sie Ihren Systemadministrator um die folgenden Informationen: ● den Host-Namen des Servers ● Ihre Benutzer-ID und Ihr Passwort, um sich per FTP einzuloggen ● das Verzeichnis, in dem Ihre PHP-Skripts gespeichert werden sollten ● den URL (Uniform Ressource Locator), mit dem Sie auf die Skripts zugreifen sollen Mit einem grafischen FTP-Client können Sie das Heraufladen eines Skripts vereinfachen. Software-Archive, wie beispielsweise http://www.tucows.com, bieten diverse Freeware-, Shareware- und kommerzielle FTP-Clients an. Der WS_FTP-Client ist ein weit verbreiteter FTP-Client, der auch zum Heraufladen Kapitel 1: PHP-Programme erstellen von Skripts geeignet ist. Wenn Sie einen grafischen FTP-Client verwenden, können Sie eine Datei heraufladen, indem Sie den Anweisungen folgen, die mit dem Client geliefert wurden. Wenn Sie mit Befehlszeilenprogrammen vertraut sind, können Sie die FTPClients verwenden, die mit Microsoft Windows, UNIX oder Linux ausgeliefert werden. Die Clients funktionieren auf allen Plattformen mehr oder weniger auf die gleiche Weise, sodass für alle Plattformen dieselben Anweisungen gelten. Gehen Sie folgendermaßen vor, um eine Datei heraufzuladen: 1. Wenn Sie Windows verwenden, müssen Sie ein MS-DOS-Fenster öffnen. 2. Gehen Sie mit dem Befehl cd in das Verzeichnis, das Ihr Skript enthält. 3. Geben Sie den folgenden Befehl ftp host ein, wobei host der Host-Name des PHP-Servers ist. 4. Geben Sie als Anwort auf die Aufforderung, Ihre Benutzer-ID einzugeben, die Benutzer-ID ein, die Sie von Ihrem Systemadministrator erhalten haben. 5. Geben Sie als Anwort auf die Aufforderung, Ihr Passwort einzugeben, das Passwort ein, das Sie von Ihrem Systemadministrator erhalten haben. 6. Gehen Sie mit dem cd-Befehl in das Verzeichnis, in das Ihr Skript heraufgeladen werden soll. 7. Geben Sie den Befehl put script ein, wobei script für den Namen der Datei steht, die das Skript enthält. 8. Geben Sie den Befehl quit ein. Die folgende FTP-Beispielsitzung wurde mit einem Linux-Client und -Server ausgeführt. Wenn Sie auf einer anderen Plattform arbeiten, sieht der Output etwas anders aus. cd /home/bmccarty/scripts $ ftp ftp.osborne.com Connected to ftp.osborne.com. 220 ftp.osborne.com FTP server (Version wu-2.6.0(1) Wed Jul 26 15:29:19 PDT 2001) ready. Name (ftp:bmccarty): bmccarty 331 Password required for bmccarty. Password: xxxxxxxx 230 User bmccarty logged in. Remote system type ist UNIX. 29 1 30 PHP 4 IT-Tutorial Using binary mode to transfer files. ftp> cd public_html 250 CWD command successful. ftp> put test-script.php local: test-script.php remote: test-script.php 200 PORT command successful. 150 Opening BINARY mode data connection for test-script.php. 226 Transfer complete. 34 bytes sent in 0.000446 secs (74 Kbytes/sec) ftp> quit 221-You have transferred 34 bytes in 1 files. 221-Total traffic for this session was 498 bytes in 1 transfers. 221-Thank you for using the FTP service on ftp.osborne.com. 221 Goodbye. $ Frage an den Experten Frage: Gibt es neben Windows-File-Shares und FTP andere Methoden, um Skripts heraufzuladen? Antwort: Ja, es gibt eine Reihe anderer Methoden. Manchmal konfigurieren Systemadministratoren von UNIX- und Linux-Systemen ihre Systeme so, dass Sie Skripts mit Hilfe des Network-File-Systems (NFS) heraufladen können. Einige Systemadministratoren stellen spezielle Webseiten zur Verfügung, über die Sie Skripts heraufladen können. Wenn ein Server den Secure-Shell-Service (SSH) anbietet, können Sie Skripts mit dem scp-Programm heraufladen. Dies ist eine besonders gute Methode, weil sie Ihre Sitzung und die Daten, die Sie übertragen, vor Lauschern im Netzwerk schützt. Beispielsweise werden bei FTP-Transfers Ihre Benutzer-ID und Ihr Passwort als Klartext anstatt in verschlüsselter Form über das Netzwerk übertragen, was zu Sicherheitsverletzungen kann. Ein Skript ausführen Nachdem Sie eine Skriptdatei heraufgeladen haben, können Sie auf sie zugreifen. Starten Sie Ihren Webbrowser, und öffnen Sie den URL, der mit dem Skript verbunden ist. Der URL sollte aus dem URL bestehen, den Ihr Systemadministrator angegeben hat, gefolgt von einem Slash (/), gefolgt von dem Namen der Skript- Kapitel 1: PHP-Programme erstellen datei. Wenn der URL, der von dem Systemadministrator angegeben wurde, bereits mit einem Slash endet, dürfen Sie vor dem Namen Ihres Skripts keinen weiteren Slash eingeben. Nehmen wir beispielsweise an, dass Sie auf ein heraufgeladenes Skript namens test-script.php zugreifen wollen. Wenn Ihr Systemadministrator das Verzeichnis, das Ihre PHP-Skripts enthält, durch den URL http:// www.osborne.com/~bmccarty (ohne einen Slash am Ende) oder durch http://www.osborne.com/~bmccarty/ (mit einem Slash am Ende) bezeichnet hat, können Sie mit dem URL http://www.osborne.com/~bmccarty/ test-script.php auf Ihr Skript zugreifen. Wenn Sie den URL Ihres Skripts korrekt eingetippt haben und Ihr Skript keine Fehler enthält, sollten Sie den Output Ihres Skripts sehen. Glückwunsch – Sie sind jetzt ein PHP-Programmierer! Projekt 1-1: Ein erstes PHP-Skript p-1-1.php In diesem Projekt werden Sie ein einfaches PHP-Skript erstellen und ausführen. Um das Projekt durchführen zu können, müssen Sie Zugriff auf einen Server haben, der PHP und das Heraufladen von Dateien per FTP unterstützt. Projektziele ● Ein PHP-Skript erstellen ● Das PHP-Skript auf einen Server heraufladen ● Das PHP-Skript ausführen Schritt für Schritt 1. Erstellen Sie mit einem Texteditor ein einfaches PHP-Skript, das TextOutput an einen Webbrowser sendet. Speichern Sie das Skript unter dem Dateinamen p-1-1.php. Falls Sie anfänglich mit einem fertigen Skript arbeiten wollen, können Sie das folgende Skript verwenden: <?php // Projekt 1-1 echo("PHP ist eine großartige Programmiersprache, nicht wahr?"); ?> 2. Laden Sie die Skriptdatei per FTP in das passende Verzeichnis Ihres Servers herauf. 31 1 32 PHP 4 IT-Tutorial 3. Ändern Sie – falls erforderlich – die Berechtigungen der Skriptdatei, sodass der Webserver die Datei ausführen kann. 4. Greifen Sie mit einem Webbrowser auf den URL der Skriptdatei zu. Wenn Sie das vorgefertigte Skript aus Schritt 1 verwendet haben, sollte das Fenster Ihres Webbrowsers etwa folgendermaßen aussehen: Abbildung 1.1 Der Output von p-1-1.php Fehler in einem Skript suchen und beseitigen Manchmal wird statt der Ausgabe des Skripts eine der folgenden Informationen angezeigt: ● der Text Ihres Skripts statt der Ausgabe des Skripts ● ein Dialogfeld, das Sie fragt, ob Sie die Skriptdatei herunterladen wollen ● eine Nachricht, die anzeigt, dass das Skript nicht existiert ● eine Nachricht, die anzeigt, dass Ihr Webbrowser nicht über die Berechtigung verfügt, auf das Skript zuzugreifen ● eine Nachricht, die anzeigt, dass Ihr Skript einen Fehler enthält Beim Anzeigen eines PHP-Skripts können mehrere Dinge schief gehen, selbst wenn das Skript korrekt ist. Wenn Sie den Text Ihres Skripts oder ein Dialogfeld sehen, das Sie fragt, ob Sie die Skriptdatei herunterladen wollen, ist es wahrscheinlich, dass die Dateierweiterung der Skriptdatei falsch ist oder dass der PHP-Server nicht funktioniert. Obwohl PHP-Skriptdateien im Allgemeinen die Dateierweiterung .php haben sollten, kann ein Systemadministrator einen PHPServer so konfigurieren, dass er eine andere Dateierweiterung erfordert. Deshalb sollten Sie – falls bei Ihrem Skript eines dieser beiden Symptome auftritt – Ihren Systemadministrator fragen. Wenn eine Nachricht anzeigt, dass das Skript nicht existiert, haben Sie wahrscheinlich den URL falsch eingegeben. Prüfen Sie, ob Sie den URL richtig eingegeben haben, den Ihr Systemadministrator genannt hat, und ob Sie den Namen Ihrer Skriptdatei korrekt mit diesem URL verbunden haben (mit oder ohne Kapitel 1: PHP-Programme erstellen Slash – je nachdem, ob der Systemadministrator den URL ohne oder bereits mit einem Slash angegeben hat). Wenn eine Nachricht anzeigt, dass Ihr Webbrowser nicht die Berechtigung hat, auf das Skript zuzugreifen, müssen Sie möglicherweise die Berechtigungen der Skriptdatei ändern. Konsultieren Sie zu diesem Zweck Ihren Systemadministrator. Wenn eine Nachricht anzeigt, dass Ihr Skript einen Fehler enthält, prüfen Sie, ob eines der folgenden Probleme vorliegt: ● ein Tippfehler, wie beispielsweise ein Schreibfehler des Wortes ecko ● ein falsches – beispielsweise ein fehlendes oder falsch platziertes – Satzzeichen (Klammer, doppeltes Anführungszeichen oder Semikolon) ● fehlende oder falsch geschriebene Klammern zur Eingrenzung des PHPCodes, <?php und ?> ● ein fehlendes oder falsch geschriebenes Kommentarzeichen (//) Das folgende Beispiel zeigt ein Skript, das einen typischen Fehler enthält. Wo steckt er? <?php // Dieses Skript enthält einen Syntaxfehler. echo("Hallo, World-Wide Web!); ?> Bei diesem Skript fehlen die schließenden doppelten Anführungszeichen, die den Textausdruck umgeben müssen. Wenn Sie versuchen, dieses Skript auszuführen, erhalten Sie eine Fehlermeldung der folgenden Art: Abbildung 1.2 PHP-Fehlermeldung Die Fehlermeldung versucht, Sie auf die Quelle des Fehlers hinzuweisen, indem sie die Zeilennummer angibt, in der der Fehler aufgetreten ist. Beachten 33 1 34 PHP 4 IT-Tutorial Sie jedoch, dass die Nachricht auf die Zeile 5 verweist, während der Fehler in der Zeile 3 liegt. Da die schließenden doppelten Anführungszeichen fehlen, sucht der PHP-Server diese fehlenden Anführungszeichen, bis er das Ende des Skripts erreicht hat. Deshalb kann der PHP-Server die Position des Fehlers nicht zeilengenau ermitteln. Das bedeutet, dass Sie sich nicht unbedingt auf den PHP-Server verlassen können, um einen Fehler genau zu lokalisieren; Sie sollten deshalb die Zeilennummer, die der Server angibt, nur als Hinweis verwenden, um die wahrscheinliche Position des Fehlers einzugrenzen. Näheres über die Lösung von Problemen in PHP-Skripts finden Sie in Kapitel 17. 1-Minuten-Test ● Finden Sie die drei Syntaxfehler in dem folgenden PHP-Skript: <?php4 /* Dieses Skcript enthält einen Syntaxfehler. echo("Hello, World-Wide Web!") ?> 9Übungsaufgaben 1. Welches Windows-Programm wird häufig verwendet, um PHP-Skripts zu erstellen? 2. Wie sollte die erste Zeile eines PHP-Skripts lauten? 3. Welche Zeichen sollten verwendet werden, um eine Datei zu benennen, die ein PHP-Skript enthält? 4. Wie sollte die Dateierweiterung einer Datei lauten, die ein PHP-Skript enthält? 5. Welcher PHP-Befehl wird verwendet, um Text-Output zu einem Webbrowser zu senden? 6. Welches Programm wird häufig benutzt, um ein PHP-Skript auf einen Server heraufzuladen? ● Die erste Zeile sollte <?php statt <?php4 lauten. ● Der Kommentar sollte mit // statt mit /* beginnen. ● Der echo-Befehl sollte mit einem Semikolon enden. Doch da dies die letzte Zeile des Skripts ist, funktioniert das Skript korrekt, obwohl das Semikolon fehlt. Kapitel 2 PHP-Bausteine Lernziele ● Wie Zahlen und Strings geschrieben werden ● Wie mit Anführungszeichen und Fluchtzeichen spezielle Stringwerte festgelegt werden ● Den Unterschied zwischen Literalen und Variablen verstehen ● Wie mit Arrays mehrere Werte gespeichert werden können ● Wie Werte mit Operatoren zu Ausdrücken kombiniert werden ● Wie mit Funktionen gemeinsame Operationen durchgeführt werden können 36 PHP 4 IT-Tutorial In diesem Kapitel lernen Sie, wie Sie die Bestandteile erstellen können, aus denen PHP-Programme bestehen. In den Kapiteln 3 und 4 lernen Sie, wie Sie diese Bestandteile zu kompletten Programmen zusammensetzen können. Zahlen und Strings Computerprogramme manipulieren Daten, die Informationen repräsentieren. PHP-Programme verwenden zwei Hauptarten von Daten: Zahlen und Strings. Zahlen bestehen hauptsächlich aus Ziffern, während Strings beliebige Zeichen einschließlich Ziffern, Buchstaben und spezieller Symbole enthalten können. Die Entscheidung, wie die Daten gespeichert werden sollen, ist eine wichtige Programmierentscheidung. Üblicherweise werden Daten als Zahlen gespeichert, wenn die Daten in mathematischen Operationen verwendet werden sollen, weil Zahlen auf eine Weise gespeichert werden, die Berechnungen erleichtert. Strings werden dagegen auf eine Weise gespeichert, die Menschen das Verstehen der Daten erleichtert. Sie sollten Daten als Strings speichern, wenn es sich um nichtnumerische Daten handelt oder wenn Menschen in der Lage sein sollen, die Daten einzugeben oder anzuschauen. Sie können Zahlen als eine Methode betrachten, um Daten in einem Computer, d.h. in einem internen Format zu speichern; und Sie können Strings als eine Methode betrachten, Daten außerhalb eines Computers, d.h. in einem externen Format zu speichern. Zahlen PHP verfügt über zwei Arten von Zahlen: Integer (Ganzzahlen) und Doubles (Double-Zahlen). Ganzzahlen repräsentieren ganze Zahlen, die zum Zählen benutzt werden, sowie die Null und negative Zahlen. Der Terminus Integer hat in PHP also im Wesentlichen dieselbe Bedeutung wie in der Mathematik. Beispielsweise könnte die Zahl 100 in PHP als Integer repräsentiert werden. Im Gegensatz zu den Integern repräsentieren Doubles numerische Werte, die Dezimalstellen enthalten können, wie beispielsweise 2.5. Doubles sind mit den reellen Zahlen in der Mathematik vergleichbar. Manchmal werden Double-Zahlen auch als Fließkommazahlen bezeichnet. Achtung Die deutsche Schreibweise von Zahlen – Dezimalkomma statt Dezimalpunkt sowie Tausendertrennpunkt statt Tausendertrennkomma – wird in PHP nicht unterstützt. Kapitel 2: PHP-Bausteine Weil PHP Zahlen in Computern speichert, die über einen beschränkten Speicherplatz verfügen, unterscheiden sich Ganzzahlen und Double-Zahlen in PHP von ihren mathematischen Entsprechungen dadurch, dass ihre Genauigkeit begrenzt ist. Integer werden im Allgemeinen als 32-Bit-Werte gespeichert, was ihren Wertebereich auf –2,147,483,648 bis 2,147,483,647 (einschließlich) beschränkt. Jedoch speichern einige Computer PHP-Ganzzahlen kompakter, was den Bereich der möglichen Werte weiter einschränkt. Doubles werden im Allgemeinen in dem Standard-IEEE-64-Format gespeichert, das 64 Bits zur Verfügung stellt. In diesem Format können Sie Werte als Doubles speichern, die bis zu 1,8 x 10308 groß sind und die grob über 14 Dezimalstellen oder signifikante Stellen der Genauigkeit verfügen. PHP-Zahlen zu schreiben ist einfach. Eine PHP-Ganzzahl wird angegeben, indem die Ziffern geschrieben werden, die den Wert repräsentieren. Wenn der Wert negativ ist, wird unmittelbar links vor die Zahl ein Minuszeichen gesetzt. Eine PHP-Ganzzahl darf keine Leerzeichen und kein Komma enthalten. Die folgende Tabelle zeigt Beispiele für gültige und ungültige PHP-Ganzzahlen: -3 Gültig 0 Gültig 5 Gültig 2.5 Ungültig: enthält eine Nachkommastelle 2.0 Ungültig: enthält eine Nachkommastelle, owohl diese null ist 1,024 Ungültig: enthält ein Komma - 7 Ungültig: enthält zwischen dem Minuszeichen und der Ziffer ein Leerzeichen 2147483648 Ungültig: zu groß Eine PHP-Double-Zahl wird als eine Folge von Ziffern geschrieben, die an der geeigneten Stelle einen Dezimalpunkt enthält. Wie bei PHP-Ganzzahlen wird bei negativen Werten unmittelbar links vor die Zahl ein Minuszeichen gesetzt. Wie bei PHP-Ganzzahlen auch darf ein PHP-Double-Wert keine Leerzeichen oder Kommas enthalten. Die folgende Tabelle zeigt Beispiele für gültige und ungültige PHP-Double-Zahlen: -2.5 Gültig 0.0 Gültig 3.125 Gültig 2 Ungültig: Dezimalpunkt fehlt Sehr große oder sehr kleine Double-Zahlen können mittels eines speziellen Formats geschrieben werden, das folgendermaßen aussieht: 2.3e4. Die Zahl nach 37 2 38 PHP 4 IT-Tutorial dem Buchstaben e gibt die Zehnerpotenz an, mit der der Rest der Zahl multipliziert wird. Beispielsweise hat die Double-Zahl 2.3e4 den Wert 2.3 x 104, und die Double-Zahl –1.1e–10 hat den Wert –1.1 x 10–10. Strings Im Gegensatz zu Ganzzahlen und Double-Zahlen, die hauptsächlich aus Ziffern bestehen, können Strings beliebige Zeichen enthalten. Deshalb eignen sich Strings dazu, Daten zu speichern, die nicht für Berechnungen benötigt werden, wie beispielsweise Namen und Adressen. Strings können auch zum Speichern numerischer Daten verwendet werden. Die Integer- und Double-Repräsentationen werden im Allgemeinen nur innerhalb von Computern verwendet, während Daten im Allgemeinen in Form von Strings in Computer eingegeben und von Computern angezeigt werden. Nehmen wir beispielsweise an, dass ein Programm eine Temperaturangabe von Fahrenheit in Celsius umwandelt. Der Benutzer des Programms gibt die Temperatur als String-Wert ein. Das Programm wandelt den String-Wert in einen DoubleWert um, führt eine Berechnung aus und wandelt das Ergebnis in einen String um, der als Antwort angezeigt wird. Der Grund für diese scheinbar komplizierte Vorgehensweise besteht darin, dass Computer Berechnungen mit Ganzzahlen und Double-Zahlen effizient ausführen; es geht schneller, Daten aus der Stringform in eine numerische Form und zurück umzuwandeln, als die Berechnungen mit Daten in Stringform auszuführen. Ein String wird in PHP angegeben, indem die Zeichen, aus denen der String besteht, in doppelte Anführungszeichen eingeschlossen werden. Beispielsweise lautet der String, der den Namen des Physikers repräsentiert, der die Relativitätstheorie begründet hat, "Albert Einstein". Wie bereits erwähnt, kann ein String numerische Daten wie beispielsweise "3.14159" enthalten. In Kapitel 5 lernen Sie, wie Sie Strings, die numerische Daten enthalten, in Ganzzahlen und Double-Zahlen umwandeln können. In PHP ist es einfach, spezielle Zeichen – wie beispielsweise Zeilenvorschübe und Wagenrückläufe – in Strings einzuschließen, indem so genannte Fluchtsequenzen (Escape-Sequenzen) in den String eingefügt werden, die diese speziellen Zeichen repräsentieren. In PHP werden die folgenden Fluchtsequenzen verwendet: \n Zeilenvorschub (line feed) \r Wagenrücklauf (carriage return) \t Horizontaler Tabulator \\ Backslash \$ Dollarzeichen \“ doppeltes Anführungszeichen Kapitel 2: PHP-Bausteine Das folgende Beispiel zeigt einen String, der einen Wagenrücklauf, gefolgt von einem Zeilenvorschub, enthält: "Hello, world!\r\n". Beachten Sie, dass jede Fluchtsequenz mit einem Backslash beginnt. Um einen Backslash in einen String einzuschließen, müssen Sie die passende Fluchtsequenz verwenden, die aus zwei Backslashes besteht. 1-Minuten-Test ● Welche Datenrepräsentation wäre für die Speicherung des durchschnittlichen Treibstoffverbrauchs eines Autos in Litern pro Kilometer am geeignetsten? ● Welche Datenrepräsentation wäre für die Speicherung der Kapitelzahl eines Buches am geeignetsten? ● Welche Datenrepräsentation wäre für die Speicherung einer Telefonnummer am geeignetsten? Frage an den Experten Frage: Was kann man machen, wenn man ein doppeltes Anführungszeichen in einen String einschließen will? Ist dies ohne eine Fluchtsequenz möglich? Antwort: Wenn man einfach ein doppeltes Anführungszeichen in einen String einfügen würde, würde PHP durcheinander kommen, weil es das doppelte Anführungszeichen als das Ende des Strings auffassen würde. Um ein doppeltes Anführungszeichen in einen String einzufügen, schließen Sie den gesamten String in einfache Anführungszeichen ein. Beispiel: 'Er sagte: "Hallo.“'. Strings in einfachen Anführungszeichen und Strings in doppelten Anführungszeichen verhalten sich etwas unterschiedlich. In Kapitel 9 erfahren Sie mehr über Strings. Literale und Variablen Die Arten von Werten, die Sie bis jetzt kennen gelernt haben, werden als Literale bezeichnet. Häufig ist es bequem, wie in der Algebra einem Wert einen Namen zu geben. Ein benannter Wert wird als Variable bezeichnet, weil es möglich ist, ● double, weil der Wert unter Umständen einen Bruchteil enthält (z.B. 6.5 Liter auf 100 km) ● integer, weil der Wert eine ganze Zahl ist ● String, weil der Wert nicht für Berechnungen benutzt wird und Sonderzeichen wie beispielsweise Bindestriche, Leerzeichen oder Klammern enthalten kann 39 2 40 PHP 4 IT-Tutorial den Wert zu ändern, der mit dem Namen verbunden ist. Im Gegensatz dazu ist der Wert eines Literals unveränderlich. Man kann eine Variable auch mit einem namentlich gekennzeichneten Ablagefach vergleichen. Der Wert einer Variable wird durch ein Literal festgelegt, das auf ein Stück Papier geschrieben und dann in das Fach gelegt wird. Dieses Stück Papier kann jederzeit durch ein anderes Stück Papier mit einem neuen Wert für die Variable ersetzt werden. In PHP gibt es einige Regeln für die Namen von Variablen, damit PHP Variablen von Zahlen, Strings und anderen Programmelementen unterscheiden kann. Gültige PHP-Variablennamen sollten folgendermaßen aufgebaut werden: 1. Beginnen Sie mit einem Dollarzeichen ($). 2. Fügen Sie nach dem Dollarzeichen einen (Groß- oder Klein-)Buchstaben oder ein Unterstreichungszeichen (_) ein. 3. Fügen Sie danach beliebig viele Buchstaben, Ziffern oder Unterstreichungszeichen ein. Wählen Sie einen Namen, der die Funktion der Variablen deutlich zum Ausdruck bringt, machen Sie den Variablennamen jedoch nicht zu lang, damit es nicht unbequem wird, den Namen einzutippen. Die folgende Liste zeigt einige Beispiele für gültige und ungültige Variablennamen: $length Gültig $x Gültig, aber nicht sehr aussagekräftig y Ungültig: beginnt nicht mit dem Dollarzeichen $1side Ungültig: nach dem Dollarzeichen folgt kein Buchstabe oder Unterstreichungszeichen $a+b Ungültig: enthält ein Pluszeichen; es sind nur Buchstaben, Ziffern und Unterstreichungszeichen erlaubt Sie können in Variablennamen zwar Groß- und Kleinbuchstaben verwenden, diese werden aber unterschieden. Eine Variable namens $A ist also nicht mit der Variablen namens $a identisch. Mit einem so genannten Zuweisungsbefehl oder kurz einer Zuweisung wird eine Variable mit einem Wert verbunden. Ein einfaches Beispiel ist: $temperature = 72.3; Auf den Namen der Variablen folgt ein Gleichheitszeichen (=), das den Befehl als Zuweisungsbefehl kennzeichnet. Das Gleichheitszeichen wird von dem Wert gefolgt, der der Variablen zugewiesen werden soll. In unserem Beispiel wird der Wert durch ein Double-Literal, 72.3, angegeben. Das Semikolon (;) markiert das Ende des Befehls. Kapitel 2: PHP-Bausteine 41 In dem vorangegangenen Beispiel wurde einer Variablen ein Literalwert zugewiesen. Man kann einer Variablen mit einem Zuweisungsbefehl auch den Wert einer anderen Variablen zuweisen. Ein Beispiel: $winner = $highest_score; Hier ersetzt der Wert der Variablen $highest_score den Wert der Variablen $winner. Weiter unten in diesem Kapitel erfahren Sie, wie Sie komplexere Zuweisungsbefehle schreiben können. Variablen können – wie Literale – einen Integer-, Double- oder String-Wert haben. Die Art dieses Variablenwertes wird als der Typ der Variablen bezeichnet. Der Typ einer Variablen kann sich ändern, wenn der Variablen ein Wert zugewiesen wird, der einen anderen Typ als der aktuelle Wert der Variablen hat. Beispielsweise gibt der Zuweisungsbefehl $x = 1; der Variablen $x den Typ Integer. Wenn danach der Zuweisungsbefehl $x = 1.5; ausgeführt wird, wandelt sich der Typ der Variablen $x in Double. In vielen Programmiersprachen kann der Typ einer Variablen nicht geändert werden. Falls Sie in einer solchen Sprache programmiert haben, wirkt diese Eigenschaft von PHP anfangs möglicherweise irritierend auf Sie. Aber wenn Sie sich an diese Eigenschaft gewöhnt haben, werden Sie sie wahrscheinlich sehr bequem finden. 1-Minuten-Test ● Wählen Sie einen geeigneten Namen für eine Variable, die die Entfernung zur Sonne speichert. ● Schreiben Sie einen Zuweisungsbefehl, der einer Variablen namens $pi den Wert 3.14159 zuweist. ● $entfernung_zur_sonne; oder etwas Ähnliches ● $pi = 3.14159; 2 42 PHP 4 IT-Tutorial Frage an den Experten Frage: Was ist der Unterschied zwischen PHP-Zuweisungsbefehlen und mathematischen Gleichungen? Antwort: Obwohl sowohl PHP-Zuweisungsbefehle als auch mathematische Gleichungen das Gleichheitszeichen verwenden, unterscheiden sie sich grundsätzlich, weil eine Zuweisung nicht dasselbe wie Gleichheit ist. Die Zuweisung ist eine Operation, die einen Wert durch einen anderen ersetzt. Die Gleichheit ist dagegen eine Beziehung zwischen zwei Werten. Wenn zwei Werte gleich sind, bleiben sie für immer gleich. Man kann jedoch einer Variablen erst einen Wert und später einen unterschiedlichen Wert zuweisen. Deshalb ist die Gleichheit dauerhaft, eine Zuweisung dagegen nicht. Projekt 2–1: Die Werte einer PHP-Variablen anzeigen p-2-1.php In diesem Projekt werden Sie ein einfaches PHP-Skript erstellen und ausführen, das die Verwendung von Literalen, Variablen und Zuweisungsbefehlen zeigt. Projektziele ● Ein PHP-Skript erstellen, das mehrere Zuweisungsbefehle enthält, und die Befehle anzeigen ● Das Skript heraufladen und ausführen Schritt für Schritt 1. Erstellen Sie mit einem Texteditor eine Datei mit dem folgenden PHPSkript: <?php // Projekt 2–1 $integer_value = 1; $double_value = 1.2345678e6; $string_value = "Dies ist ein String."; echo("<H2>Projekt 2–1</H2>"); echo("<BR>Integer-Wert: "); echo $integer_value; echo("<BR>Double-Wert: "); echo($double_value); Kapitel 2: PHP-Bausteine 43 echo("<BR>String-Wert: "); echo($string_value); ?> 2. Laden Sie Ihre Skriptdatei in das passende Verzeichnis Ihres Servers herauf. 3. Greifen Sie mit einem Webbrowser auf den URL zu, der mit Ihrer Skriptdatei verbunden ist. Das Fenster Ihres Webbrowsers sollte etwa wie folgt aussehen: Abbildung 2.1 Der Output von p-2–1.php Skalare und Arrays Die meisten Käufer finden es bequem, Eier im Dutzend statt einzeln zu kaufen. Auf ähnliche Weise ist es häufig bequem, mehrere Werte in einer Variablen zu speichern. Eine derartige Variable wird als Array bezeichnet, und die einzelnen Werte werden als Elemente des Arrays bezeichnet. Variablen, die nur über einen einzigen Wert verfügen, werden als Skalare bezeichnet. Damit auf jedes Element eines Arrays einzeln zugegriffen werden kann, ist jedes Element mit einem Schlüssel verbunden. Man könnte den Namen eines Arrays mit einem Familiennamen seiner Elemente vergleichen. Die Schlüssel, die mit den einzelnen Elementen verbunden sind, entsprächen dann den Vornamen der Elemente. Die Kombination aus dem Array-Namen (Familiennamen) und einem Schlüsselwert (einem Vornamen) identifiziert ein Element des Arrays. Um ein Array zu erstellen, weisen Sie einem Array-Element einen Wert und einen Schlüssel zu. Beispielsweise erstellt der Zuweisungsbefehl $kurs[1] = "Geometrie"; 2 44 PHP 4 IT-Tutorial ein Array namens $kurs und ein Element mit dem Wert "Geometrie", der durch den Schlüssel 1 identifiziert wird. Um einen zweiten Wert in dem Array zu speichern, könnten Sie den folgenden Zuweisungsbefehl verwenden: $kurs[2] = "Buchhaltung"; Um auf ein Element eines Arrays zuzugreifen, geben Sie den Namen des Arrays und den Wert des Schlüssels an. Beispielsweise weist der Zuweisungsbefehl $mathe = $kurs[1]; der skalaren Variablen $mathe den Wert "Geometrie" zu. Die Schlüssel, mit denen die Elemente eines Arrays identifiziert werden, müssen nicht aus aufeinander folgenden Zahlen, ja nicht einmal aus Zahlen bestehen. Beispielsweise wird mit den folgenden Zuweisungsbefehlen ein Array erstellt, in dem das Lieblingseis verschiedener Personen gespeichert wird: $lieblingseis["Bill"] = "Vanille"; $lieblingseis["Sara"] = "Erdbeer"; Das Array speichert die Tatsachen, dass Bill Vanilleeis und Sara Erdbeereis bevorzugt. Mit Hilfe eines solchen Arrays ist es einfach, das Lieblingseis einer Person festzustellen, wenn deren Vorname bekannt ist. Der Zugriff auf die Elemente eines Arrays mit nichtnumerischen Schlüsseln erfolgt genau wie bei Array-Elementen mit numerischen Schlüsseln. Beispielsweise setzt der Zuweisungsbefehl $eis_des_tages = $lieblingseis["Bill"]; den Wert von $eis_des_tages auf "Vanille". 1-Minuten-Test ● Schreiben Sie Zuweisungsbefehle, die ein Array namens $groesse erstellen, das die Werte klein, mittel und groß mit den Schlüsseln 1, 2 bzw. 3 verbindet. ● $groesse[1] = "klein"; $groesse[2] = "mittel"; $groesse[3] = "groß"; Kapitel 2: PHP-Bausteine ● Schreiben Sie Zuweisungsbefehle, die ein Array namens $bundesland erstellen, mit dem Sie den vollständigen Namen von Bundesländern mittels einer Abkürzung aus drei Buchstaben abrufen können. Um die Aufgabe abzukürzen, wählen Sie nur die folgenden drei Bundesländer bzw. Abkürzungen: Nordrhein-Westfalen, NRW; Bayern, BAY; Hessen, HES. Operatoren und Funktionen Um Berechnungen durchführen zu können, verfügt PHP über ein Reihe nützlicher Operatoren und Funktionen. Wenn man Literale und Variablen mit Operatoren und Funktionen kombiniert, werden so genannte Ausdrücke gebildet. Operatoren PHP verfügt über die gebräuchlichen arithmetischen Operatoren: + Addition - Subtraktion * Multiplikation / Division Vielleicht ist es für Sie ungewohnt, die Multiplikation durch ein Sternchen (*) zu repräsentieren; jedoch ist dies in Programmiersprachen üblich, weil dadurch die Verwirrung vermieden wird, die entstehen könnte, wenn der Buchstabe x zur Repräsentation der Multiplikation verwendet werden würde. Die folgenden einfachen Beispiele zeigen, wie Operatoren verwendet werden, um Berechnungen durchzuführen und Variablen Werte zuzuweisen: $gewinn = $umsatz - $kosten; $flaeche = $hoehe * $breite; $umfang = 3.14159 * $durchmesser; $steuersatz = $steuer / $versteuerbares_einkommen; Die Variablen oder Literale, die mit einem Operator verbunden werden, werden als Operanden bezeichnet. Beispielsweise sind in dem ersten Beispielbefehl die Variablen $umsatz und $kosten die Operanden des Subtraktionsoperators. ● $bundesland["NRW"] = "Nordrhein-Westfalen"; $bundesland["BAY"] = "Bayern"; $bundesland["HES"] = "Hessen"; 45 2 46 PHP 4 IT-Tutorial Der Divisionsoperator verfügt über eine interessante Eigenschaft: Er gibt einen Integer-Wert zurück, wenn seine beiden Operanden Ganzzahlen sind und das Ergebnis eine Ganzzahl ist; andernfalls gibt er einen Fließkommawert zurück. Beispielsweise weist der Zuweisungsbefehl $x = 10 / 3; der Variablen $x den Fließkommawert 3.3333333333333 zu, obwohl beide Operanden des Divisionsoperators Ganzzahlen sind. Zusätzlich zu diesen gebräuchlichen arithmetischen Operatoren verfügt PHP über mehrere weniger gebräuchliche Operatoren: % Modulus ++ Inkrement -- Dekrement . Verkettung (Verknüpfung, Konkatenation) Der Modulusoperator führt wie der Divisionsoperator eine Division aus; jedoch gibt der Modulusoperator den Rest statt des Quotienten zurück. Beispielsweise ergibt die Division von 10 durch 3 den Quotienten 3 und den Rest 1. Der Zuweisungsbefehl $x = 10 % 3; weist $x den Wert 1 zu. Beim Programmieren werden häufig Operationen verwendet, bei denen ein Wert um eine Einheit vergrößert oder verkleinert wird. Um solche Operationen zu vereinfachen, enthält PHP Operatoren, die diese Operationen ausführen. Der Inkrement-Operator erhöht den Wert einer Variablen um eine Einheit, und der Dekrement-Operator verringert den Wert einer Variablen um eine Einheit. Die Operatoren werden folgendermaßen verwendet: ++$x; --$y; Beachten Sie, dass für diese Operatoren nur ein einziger Operand erforderlich ist, während die meisten Operatoren zwei Operanden erfordern. Der erste Befehl addiert eins zum Wert von $x, und der zweite Befehl subtrahiert eins vom Wert von $y. Diese Operatoren können auch in Zuweisungsbefehlen verwendet werden. Ein Beispiel: $x = ++$y; Dieser Befehl addiert eins zum Wert von $y und weist $x den resultierenden Wert zu. Kapitel 2: PHP-Bausteine 47 Frage an den Experten Frage: Was passiert, wenn man einen Inkrement- oder Dekrement-Operator hinter seinen Operanden stellt? Antwort: Wenn man einen Inkrement- oder Dekrement-Operator hinter statt vor seinen Operanden stellt, wird eine etwas andere Wirkung erzielt. Betrachten Sie das folgende Beispiel: $x = $y--; Dieser Befehl subtrahiert eins von dem Wert von $y, aber er weist $x den ursprünglichen, nicht verringerten Wert von $y zu. Wenn man einen Inkrement- oder Dekrement-Operator vor eine Variable setzt, spricht man von einem Prä-Inkrement oder Prä-Dekrement; wenn man einen Inkrement- oder Dekrement-Operator hinter eine Variable setzt, spricht man von einem Post-Inkrement oder Post-Dekrement. Zusätzlich zu diesen numerischen Operatoren verfügt PHP über einen Stringverkettungsoperator, der manchmal als Cat-Operator oder Join-Operator bezeichnet wird, weil er die Funktion hat, Strings zu verbinden. Betrachten Sie beispielsweise die folgenden Zuweisungsbefehle: $vorname = "Bill"; $nachname = "McCarty"; $name = $vorname . " " . $nachname; Die ersten beiden Zuweisungsbefehle weisen skalaren Variablen Stringwerte zu. Der letzte Zuweisungsbefehl verwendet den Join-Operator, um den Vornamen mit dem Nachnamen zu verknüpfen und dazwischen ein Leerzeichen einzufügen. Dadurch wird der Variablen $name der Wert "Bill McCarty" zugewiesen. Wie in der Mathematik führt PHP Multiplikations- und Divisionsoperatoren vor Additions- und Subtraktionsoperatoren aus. Diese Funktion wird als Vorrang (precedence) bezeichnet. Wegen des Vorrangs weist der Befehl $x = 1 + 2 * 3; 2 48 PHP 4 IT-Tutorial der Variablen $x den Wert 7 zu, obwohl der Additionsoperator vor dem Multiplikationsoperator steht. Mit Klammern kann der Vorrang der Operatoren in einem Ausdruck geändert werden. Beispielsweise weist der Befehl $x = (1 + 2) * 3; der Variablen $x den Wert 9 zu, weil der in Klammern stehende Teil des Ausdrucks wie in der Algebra zuerst ausgewertet wird. Frage an den Experten Frage: Verfügt PHP noch über andere Operatoren? Antwort: Ja, PHP verfügt neben den gerade beschriebenen noch über viele andere Operatoren. Insbesondere enthält es Vergleichsoperatoren und logische Operatoren (siehe Kapitel 6). Funktionen Zusätzlich zu den Operatoren verfügt PHP über Funktionen, die nützliche Berechnungen und Aufgaben ausführen. Einige Beispiele: abs(x) gibt den absoluten Wert von x zurück ceil(x) gibt den auf die nächste Ganzzahl aufgerundeten Wert von x zurück floor(x) gibt den auf die nächste Ganzzahl abgerundeten Wert von x zurück max(x,y,...) gibt den größten Wert in einer Menge von Werten zurück min(x,y,...) gibt den kleinsten Wert in einer Menge von Werten zurück pow(x,n) gibt den Wert der n-ten Potenz der Zahl x zurück strftime(f) gibt das aktuelle Datum in dem durch f definierten Format zurück sqrt(x) gibt die Quadratwurzel von x zurück Zusätzlich zu diesen Funktionen enthält PHP viele weitere Funktionen. Beschreibungen dieser und anderer gebräuchlicher PHP-Funktionen finden Sie in Anhang I. Die meisten Funktionen erfordern einen oder mehrere Eingabewerte, die als Argumente bezeichnet werden. Beispielsweise erfordert die Funktion sqrt ein Argument, das den Wert angibt, dessen Quadratwurzel berechnet werden soll. Einige Funktionen, wie beispielsweise min und max, haben eine unbegrenzte Anzahl von Argumenten. Einige Funktionen haben überhaupt keine Argumente. Um eine Funktion korrekt einsetzen zu können, müssen Sie die folgenden Aspekte kennen: Kapitel 2: PHP-Bausteine ● den Namen der Funktion ● was die Funktion tut und gegebenenfalls welchen Wert sie zurückgibt ● wie viele Argumente die Funktion erfordert ● was jedes Argument bedeutet Das folgende einfache Beispiel verwendet eine Funktion, um die Länge der Seiten eines Quadrats zu berechnen, dessen Fläche bekannt ist: $laenge = sqrt($flaeche); Beachten Sie, wie das Argument der Funktion in Klammern eingeschlossen wird und wie die Funktion und ihr Argument in ähnlicher Weise wie eine Variable oder ein Literal verwendet werden. Das folgende Beispiel zeigt, wie die maxFunktion verwendet wird, die mehrere Argumente hat: $gewinner = max($punktzahl1, $punktzahl2, $punktzahl3); Beachten Sie, wie die Argumente durch Kommas getrennt werden. 1-Minuten-Test ● Schreiben Sie einen PHP-Befehl, der die Variablen $normaler_lohn und $zusatz_lohn addiert und das Ergebnis der Variablen $gesamt_lohn zuweist. ● Schreiben Sie einen PHP-Befehl, der das Quadrat von $x in $y speichert. Projekt 2–2: Eine Berechnung in PHP p-2-2.php In diesem Projekt werden Sie ein einfaches PHP-Skript erstellen und ausführen, das die Fläche eines Kreises mit einem gegebenen Radius berechnet. Projektziele ● Ein PHP-Skript erstellen, das die Fläche eines Kreises berechnet ● Ein PHP-Skript heraufladen und ausführen ● $gesamt_lohn = $normaler_lohn + $zusatz_lohn; ● $y = $x * $x; oder $y = pow($x, 2); 49 2 50 PHP 4 IT-Tutorial Schritt für Schritt 1. Erstellen Sie mit einem Texteditor eine Datei, die das folgende PHP-Skript enthält: <?php // Projekt 2–2 // Die Fläche eines Kreises mit einem gegebenen Radius // berechnen echo("<H2>Projekt 2–2</H2>"); $radius = 2.0; $pi = 3.14159; $flaeche = $pi * $radius * $radius; echo("Radius = "); echo($radius); echo("<BR>Fläche = "); echo($flaeche); ?> 2. Laden Sie Ihre Skriptdatei in das passende Verzeichnis Ihres Server herauf. 3. Greifen Sie mit einem Webbrowser auf den URL zu, der mit Ihrer Skriptdatei verbunden ist. Das Fenster Ihres Webbrowsers sollte etwa wie folgt aussehen: Abbildung 2.2 Der Output von p-2–2.php Kapitel 2: PHP-Bausteine 9Übungsaufgaben 1. Schreiben Sie ein PHP-Literal, das den Wert 12,000 hat. 2. Schreiben Sie ein PHP-Literal, das den Wert 10.39 hat. 3. Schreiben Sie ein PHP-Literal, das den Namen Ihres Lieblingsautos enthält. 4. Schreiben Sie den Namen einer PHP-Variablen, mit der Sie den aktuellen Mehrwersteuersatz speichern können. 5. Schreiben Sie PHP-Befehle, die ein Array erstellen, das den Vornamen jedes Mitglieds Ihrer Familie mit seinem Geburtsjahr verbindet. 6. Schreiben Sie mit Hilfe der Formel U = 2 x π x R einen PHP-Befehl, der aus dem Radius eines Kreises dessen Umfang berechnet. Benutzen Sie für π den Näherungswert 3.14159. 7. Schreiben Sie einen PHP-Befehl, der den absoluten Wert von $entfernung berechnet und das Ergebnis in $netto_entfernung speichert. 51 2 Kapitel 3 HTML-Formulare erstellen Lernziele ● Wie bedienungsfreundliche und effiziente HTML-Formulare gestaltet werden ● Wie HTML-Formulare mit Texteingabe- und Benutzerauswahlfeldern erstellt werden ● Wie PHP-Programme geschrieben werden, die auf Daten in HTML-Formularen zugreifen 54 PHP 4 IT-Tutorial Die meisten PHP-Programme verwenden HTML-Formulare, um Benutzerdaten abzufragen und das Ergebnis von Berechnungen anzuzeigen. In diesem Kapitel lernen Sie, wie Sie HTML-Formulare erstellen können, mit deren Hilfe PHP-Programme mit dem Benutzer interagieren können. Grundlagen des Formularentwurfs Einige erfahrene Programmierer sind der Ansicht, dass sie sofort und intuitiv wissen, wie ein beliebiges HTML-Formular aussehen und funktionieren sollte. Anstatt ein HTML-Formular zunächst zu entwerfen, beginnen solche Programmierer einfach damit, das Formular zu erstellen (zu programmieren). Häufig entlarvt das Ergebnis die Behauptung dieser Programmierer, über ein intuitives Wissen zu verfügen, als fromme Wunschvorstellung. Auf diese Weise entstehen viele schlechte Formulare. Sowohl unerfahrene als auch erfahrene Programmierer gehen nur dann professionell vor, wenn sie zunächst einen Entwurf des Formulars anfertigen, bevor es erstellt (programmiert) wird. Während des Entwurfs werden zunächst alternative Möglichkeiten erwogen, die Komponenten des Formulars anzuordnen, um die bestmögliche Struktur zu finden. Wenn man keine Alternativen entwickelt und bewertet hat, gibt es keinen Grund anzunehmen, dass eine Formularstruktur besser als andere mögliche Strukturen ist. Deshalb sind qualitativ minderwertige Formulare häufig die Folge, wenn die Entwurfsphase übersprungen wird. Ein Formular entwerfen Eine gute Methode, ein Formular zu entwerfen, besteht darin, Papier und Bleistift zu benutzen. Falls Sie eine Tafel haben, ist diese sogar noch besser geeignet. Wenn Sie lieber mit automatisierten Werkzeugen arbeiten, können Sie auch einen WYSIWYG-HTML-Editor verwenden. Diese genannten Entwurfsmethoden haben eine wichtige Eigenschaft gemeinsam: Es ist einfach, den aktuellen Entwurf ganz oder teilweise zu löschen und von vorn anzufangen. Forschungen über den Designprozess haben ergeben, dass erfahrene Designer häufiger neu beginnen als unerfahrene Designer. Unerfahrene Designer legen sich tendenziell häufiger auf den ersten Entwurf fest und versäumen es, potenziell bessere Alternativen zu erwägen. Beim Entwerfen eines HTML-Formulars müssen Sie hauptsächlich die folgenden Aufgaben lösen: Sie müssen die HTML-Controls (HTML-Steuerelemente) auswählen, die in dem Formular verwendet werden sollen, Sie müssen die Position der Controls in dem Formular festlegen, und Sie müssen geeignete Bezeichnungen für die Controls auswählen. Das Entwerfen ist jedoch kein Schritt-für-Schritt-Prozess, dem man sklavisch folgen muss, sondern eher ein Kapitel 3: HTML-Formulare erstellen 55 „opportunistischer Prozess“. Dies bedeutet, dass der beste Weg, den nächsten Entwurfsschritt auszuführen, darin besteht, das zu tun, was am ehesten einen Schritt weiter in Richtung auf das Ziel führt. Die folgenen grundlegenden Richtlinien können Ihnen beim Entwerfen von HTML-Formularen helfen: ● Wählen Sie die Controls, die der Art der abgefragten bzw. dargestellten Daten und der Interaktion mit dem Benutzer angemessen sind. Im folgenden Abschnitt werden alle HTML-Controls erklärt, um Sie bei dieser Auswahl zu unterstützen. ● Bezeichnen Sie jedes Control so, dass der Benutzer seine Funktion versteht. ● Richten Sie – soweit es möglich ist – Bezeichnungen (Labels) und Controls linksbündig aus. Das Layout eines guten Formulars ähnelt einer Zeitung, die aus einer Reihe von Spalten besteht, in denen alle visuellen Elemente die gleiche Ausrichtung haben wie die Elemente, die darüber oder darunter stehen. Sie können diese Art des Layouts mit Hilfe von HTML-Tabellen oder des br-Tags erzielen. ● Gruppieren Sie zusammengehörige Controls, und trennen Sie Gruppen optisch durch Leerräume (Whitespace) voneinander. ● Die Reihenfolge der Controls auf dem Formular sollte der Reihenfolge entsprechen, in der der Benutzer sie bearbeitet. Andernfalls wird der Benutzer gezwungen, Zeit mit der Navigation von Control zu Control zu verschwenden. Vergessen Sie nicht, dass es sich hier nur um Richtlinien, nicht um Regeln handelt! Deshalb können Sie sich – falls erforderlich – darüber hinwegsetzen, wenn Sie der begründeten Auffassung sind, dass das Ergebnis dadurch besser wird als beim Befolgen der Richtlinien. Beispielsweise können die Richtlinien in bestimmten Situationen widersprüchliche Anweisungen geben. In solchen Fällen müssen Sie sich für die eine oder die andere Richtlinie entscheiden. Um den besten Entwurf herauszufinden, ist es häufig hilfreich, einen Benutzer um seine Meinung zu bitten. Wenn kein Benutzer greifbar ist, können Sie auch den Rat eines anderen Programmierers einholen. Notfalls können Sie versuchen, sich selbst, so gut es geht, in die Lage eines Benutzers des Formulars zu versetzen. Fragen Sie den Benutzer oder seinen Vertreter, ob das Formular klar, bedienungsfreundlich und effizient ist. Wenn diese Eigenschaften erfüllt sind, können Sie zur nächsten Phase übergehen und das eigentliche HTML-Formular erstellen. 3 56 PHP 4 IT-Tutorial Ein HTML-Formular erstellen Im Gegensatz zu dem opportunistischen Entwurfsprozess ist das Erstellen eines HTML-Formulars anhand des fertigen Entwurfs ein geradliniger Prozess. Zunächst erstellen Sie das grundlegende HTML-Gerüst, das die Controls Ihres Formluars aufnehmen soll. Dann fügen Sie die Controls in dieses Gerüst ein. Insbesondere muss ein HTML-Formular eine SUBMIT-Schaltfläche enthalten, mit der der Benutzer die Daten des Formulars an den Server schicken kann. Weil eine einzelne HTML-Seite mehrere Formulare enthalten kann, können Sie die mittleren Schritte dieses Prozesses mehrere Male wiederholen. Die folgenden Unterabschnitte beschreiben ausführlich, wie ein HTML-Formular erstellt wird. Die HTML-Struktur erstellen Die HTML-Struktur, in die Sie ein Formular einbetten, unterscheidet sich nicht von der HTML-Struktur, mit der eine gewöhnliche HTML-Seite erstellt wird. Das folgende Beispiel zeigt eine typische Struktur: <html> <head> <title>Titel der Seite</title> </head> <body> Inhalt der Seite oder des Formulars </body> </html> Im Body (Körper) einer HTML-Seite, die ein Formular enthält, können Sie jedes gebräuchliche HTML-Tag verwenden. Das Formular selbst wird mit dem form-Tag beschrieben, das die folgende grundlegende Form hat: <form method="method" action="url"> Das method-Attribut des form-Tags kann einen von zwei Werten annehmen: GET oder POST. Im Moment sollten Sie immer den Wert POST angeben. Das action-Attribut gibt den URL des PHP-Skripts an, das die Daten verarbeitet, die mit Hilfe des Formulars erhoben werden. Der URL kann vollständig (also mit Protokoll, Host-Name und Pfad) oder partiell (also relativ zur Position der aktuellen Seite) angegeben werden. Die Controls des Formulars werden zwischen dem form-Tag und dem zugehörigen /form-Tag eingefügt. Kapitel 3: HTML-Formulare erstellen 57 Frage an den Experten Frage: Wann sollte ich, wenn ich ein HTML-Formular erstelle, dem method-Attribut den Wert GET, und wann den Wert POST zuweisen? Antwort: Als Anfänger ist es am besten, grundsätzlich die POSTMethode zu verwenden, weil die Wahl zwischen der GET- und der POSTMethode recht kompliziert ist. Als Faustregel verwenden viele Programmierer GET für Formulare, die eine Suche oder Abfrage durchführen, und POST für Formulare, die eine Datenbank oder Datei aktualisieren. Die GET-Methode hat zwei Nachteile: Sie beschränkt die Menge der Daten, die zu dem Verarbeitungsskript gesendet werden können, und sie überträgt Daten, indem sie codierte Strings an den URL des Verarbeitungsskripts anhängt. Auf diese Weise können Daten, die per GET übertragen werden, von dem Benutzer betrachtet werden. Ein Vorteil der GETMethode besteht darin, dass der Benutzer das Ergebnis einer Abfrage oder Suche, die mit GET arbeitet, mit einem Lesezeichen versehen kann, was bei der POST-Methode nicht möglich ist. Natürlich können Benutzer die Seite mit einem Lesezeichen versehen, die ein Formular mit der POSTMethode enthält; nur das Ergebnis kann nicht mit einem Lesezeichen versehen werden. Controls einfügen Dieser Unterabschnitt beschreibt zwei grundlegende Controls, die Sie häufig verwenden werden: das Textfeld und die SUBMIT-Schaltfläche. Im nächsten Abschnitt erfahren Sie mehr über die Controls, die Sie beim Erstellen von HTML-Formularen verwenden können. In ein Textfeld kann der Benutzer Informationen eintippen, die an ein PHPSkript gesendet werden können. Textfelder werden häufig dazu verwendet, Daten wie beispielsweise den Namen des Benutzers, seine postalische Anschrift oder seine E-Mail-Adresse zu erheben. Das HTML-Tag, um ein Textfeld zu erstellen, hat die folgende grundlegende Form: <input type="TEXT" name="text"> Das name-Attribut weist dem Textfeld einen Namen zu, mit dem ein PHPSkript auf Inhalt des Feldes zugreifen kann. Der Name für ein Control muss innerhalb des Formulars eindeutig sein und den Regeln für die Benennung von PHP-Variablen folgen, außer dass der Name nicht mit einem Dollarzeichen beginnen darf. Das heißt, dass der Name mit einem Buchstaben beginnen und 3 58 PHP 4 IT-Tutorial außer Buchstaben, Ziffern und Unterstreichungszeichen keine andere Zeichen enthalten sollte. Insbesondere sollte der Name keine Leerzeichen enthalten. HTML verfügt nicht über ein /input-Tag, sodass Sie nicht versuchen sollten, ein input-Tag wie andere Tag-Paare mit einem solchen Tag abzuschließen. Mit einer SUBMIT-Schaltfläche kann der Benutzer den Inhalt eines Formulars an den Server schicken. Jedes HTML-Formular muss über eine SUBMIT-Schaltfläche verfügen. Das HTML-Tag, um eine SUBMIT-Schaltfläche zu erstellen, hat die folgende grundlegende Form: <input type="SUBMIT" value="text"> Das value-Attribut gibt die Beschriftung (engl. caption) der SUBMIT-Schaltfläche an. Das folgende Beispiel zeigt ein komplettes HTML-Formular, das Textfelder enthält, mit denen der Name des Benutzers und seine E-Mail-Adresse abgefragt werden: <html> <head> <title>Namen und E-Mail-Adresse eines Benutzers abfragen</ title> </head> <body> <form method="POST" action="phpinfo.php"> <h3>Namen und E-Mail-Adresse eines Benutzers abfragen </h3> <br>Name: <br><input type="TEXT" name="benutzername"> <br>E-Mail-Adresse: <br><input type="TEXT" name="e_mail_adresse"> <br> <br><input type="SUBMIT" value="Daten abschicken"> </form> </body> </html> Beachten Sie, wie die Labels (Bezeichnungen) und Controls sowie die Namen der Textfeld-Controls mit Hilfe von br-Tags linksbündig ausgerichtet werden. Wenn der Benutzer auf die SUBMIT-Schaltfläche klickt, werden die Daten, die der Benutzer eingegeben hat, an das Skript phpinfo.php gesendet. Die folgende Abbildung zeigt das HTML-Formular: Kapitel 3: HTML-Formulare erstellen 59 3 Abbildung 3.1 HTML-Formular Mit mehreren Formularen arbeiten Sie können auch mehrere Formulare in den Body einer HTML-Seite einfügen. In diesem Fall müssen Sie vor dem <form>-Tag des folgenden Formulars ein </ form>-Tag einfügen. Der Browser des Benutzers kommt durcheinander, wenn sich die Formulare auf einer Seite überlappen. Das folgende einfache Beispiel zeigt eine Seite, die mehrere Formulare enthält: <html> <head> <title>Namen und E-Mail-Adresse eines Benutzers abfragen</ title> </head> <body> <form method="POST" action="phpinfo.php"> <h3>Namen und E-Mail-Adresse eines Benutzers abfragen</h3> <br>Name: <br><input type="TEXT" name="benutzername"> <br>E-Mail-Adresse: <br><input type="TEXT" name="e_mail_adresse"> <br> <br><input type="SUBMIT" value="Daten abschicken"> </form> <form method="POST" action="phpinfo.php"> <h3>Telefonnummer und Faxnummer des Benutzers abfragen</h3> <br>Telefon: 60 PHP 4 IT-Tutorial <br><input type="TEXT" name="telefon"> <br>Fax: <br><input type="TEXT" name="fax"> <br> <br><input type="SUBMIT" value="Daten abschicken"> </form> </body> </html> Wenn der Benutzer auf die SUBMIT-Schaltfläche klickt, werden die Inhalte der Felder des Formulars, das die angeklickte Schaltfläche enthält, an den Server gesendet. Das bedeutet, dass der Server entweder einen Namen und eine E-MailAdresse oder eine Telefon- und eine Faxnummer, aber nicht alle vier Felder auf einmal empfängt. Frage an den Experten Frage: Was kann ich machen, wenn meine HTML-Kenntnisse schwach oder eingerostet sind? Wo kann ich Hilfe bekommen, um meine HTML-Fähigkeiten zu verbessern, sodass ich Formulare erstellen kann? Antwort: Um die Grundlagen von HTML zu lernen oder aufzufrischen, empfehle ich Ihnen das Buch HTML 4 für Dummies von Ed Tittel, Natanya Pitts und Chelsea Valentine (MITP-Verlag, 2. Auflage 2001). 1-Minuten-Test ● Welche Attribute müssen in dem form-Tag angegeben werden? ● Welches Control muss jedes HTML-Formular enthalten? ● Mit welchem HTML-Tag wird ein Textfeld erstellt? ● method, action ● SUBMIT-Schaltfläche ● input Kapitel 3: HTML-Formulare erstellen 61 Projekt 3–1: Formularfelder anzeigen In diesem Projekt lernen Sie, wie Sie die Daten anzeigen können, die von einem HTML-Formular an sein Verarbeitungsskript übertragen werden. Sie werden feststellen, dass diese Fähigkeit nützlich ist, wenn Sie Probleme in p-3–1.php einem HTML-Formular und/oder in einem Verarbeitungsskript beheben p-3–1.html müssen. Projektziele ● das Erstellen eines PHP-Skripts und eines HTML-Formular üben ● das Ergebnis einer Übertragung eines HTML-Formulars anzeigen können Schritt für Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen p-3– 1.php, und laden Sie diese Datei auf Ihren PHP-Server herauf: <?php // Datei p-3–1.php phpinfo() ?> 2. Speichern Sie die folgende HTML-Seite unter dem Dateinamen p-3– 1.html, und laden Sie diese Datei auf Ihren PHP-Server in dasselbe Verzeichnis wie die Datei p-3–1.php herauf: <html> <head> <title>Namen und E-Mail-Adresse eines Benutzers abfragen</title> </head> <body> <!-- Datei p-3–1.html --> <form method="POST" action="p-3–1.php"> <h3>Namen und E-Mail-Adresse eines Benutzers abfragen</ h3> <br>Name: <br><input type="TEXT" name="benutzername"> <br>E-Mail-Adresse: <br><input type="TEXT" name="e_mail_adresse"> <br> <br><input type="SUBMIT" value="Daten abschicken"> </form> 3 62 PHP 4 IT-Tutorial </body> </html> 3. Geben Sie den URL des HTML-Formulars in das Adressfeld Ihres Webbrowsers ein. Geben Sie einen Benutzernamen und eine E-Mail-Adresse ein, und klicken Sie auf die SUBMIT-Schaltfläche. 4. Wenn das Verarbeitungsskript p-3–1.php ausgeführt wird, zeigt es einen umfangreichen Bericht über den Status des PHP-Servers an. In dem Abschnitt PHP Variablen finden Sie Informationen über die beiden Textfeld-Controls, benutzername und e_mail_adresse (siehe die folgende Abbildung). Beachten Sie die Werte, die von dem Benutzer des Formulars eingegeben wurden. Abbildung 3.2 Output der phpinfo()-Funktion Formular-Controls erstellen In dem vorangegangenen Abschnitt haben Sie gelernt, wie die Controls der Textfelder und der SUBMIT-Schaltfläche erstellt werden. In diesem und dem nächsten Abschnitt erweitern Sie Ihr Control-Repertoire und lernen alle verfügbaren Controls kennen. Angepasste Textfelder erstellen Im vorangegangenen Abschnitt wurde die grundlegende Syntax für das Erstellen eines Textfelds vorgestellt. Doch gibt es in HTML mehrere zusätzliche Attribute, Kapitel 3: HTML-Formulare erstellen 63 mit denen Sie das Aussehen und das Verhalten eines Textfelds verändern können. Die komplette Syntax für das Erstellen eines Textfelds lautet: <input type="TEXT" name="text" size="zahl" maxlength="zahl" value="text"> Die Attribute type und name sind erforderlich, die restlichen Attribute sind optional. Das size-Attribut legt die sichtbare Größe des Textfelds als Anzahl von Zeichen fest. Das maxlength-Attribut legt die Anzahl der Zeichen fest, die der Benutzer eintippen darf. Der Wert von maxlength kann größer als der Wert von size sein. In diesem Fall wird der Inhalt nach rechts verschoben, wenn der Benutzer die von size festgelegte Anzahl von Zeichen eingegeben hat. Das value-Attribut legt einen Standardwert fest, der anfänglich in dem Textfeld angezeigt wird. Tipp Es ist wichtig, dass Sie mit dem Aussehen und dem Verhalten des Textfelds und anderer HTML-Formular-Controls vertraut sind. Das Projekt am Ende dieses Abschnitts gibt Ihnen die Möglichkeit, diese Controls zu erstellen und mit ihnen zu arbeiten. Textbereiche erstellen Wie mit einem Textfeld auch kann ein Benutzer mit einem Textbereich Text eingeben. Jedoch kann der Benutzer bei einem Textbereich mehrere Textzeilen eingeben, während er bei einem Textfeld auf eine einzelne Zeile beschränkt ist. Die Syntax für das Erstellen eines Textbereiches lautet: <textarea name="text" row="zahl" cols="zahl" wrap="wrap"> Die Attribute name und rows sind erforderlich. Die Attribute cols und wrap sind optional. Das rows-Attribut legt die Anzahl der Textzeilen fest, die in dem Textbereich sichtbar sind. Weil ein Textbereich verschoben wird, wenn er voll ist, kann der Benutzer zusätzliche Zeilen eingeben. Das cols-Attribut legt die Anzahl der Textspalten fest, die in dem Textbereich sichtbar sind. Weil ein Textbereich verschoben oder umbrochen wird, wenn er voll ist, kann der Benutzer längere Zeilen eingeben. Das wrap-Attribut legt fest, wie der Text in dem Textbereich umbrochen wird. Es kann die folgenden Werte annehmen: 3 64 PHP 4 IT-Tutorial Wert Beschreibung off Der Textumbruch ist deaktiviert. Die Benutzer können Zeilenumbrüche eingeben, um einen Zeilenumbruch zu erzwingen. virtual Die Zeilen werden umbrochen angezeigt, aber die Zeilenumbrüche werden nicht an den Server übertragen. physical Der Textumbruch ist aktiviert. soft wie virtual hard wie physical Ein textarea-Tag sollte mit einem /textarea-Tag kombiniert werden. Der gesamte Text, der zwischen diesen Tags angegeben wird, wird als anfänglicher Inhalt des TEXTAREA-Controls angezeigt. Passwortfelder erstellen Wenn der Benutzer bei einer Anwendung ein Passwort eingeben soll, könnten Sie für diesen Zweck ein Textfeld erstellen. Doch dabei können andere Personen die Eingabe mitlesen, wenn der Benutzer das Passwort eingibt, was möglicherweise zu Sicherheitsverletzungen führt. Deshalb sollten Sie für die Eingabe vertraulicher Informationen anstelle eines Textfeldes ein Passwortfeld verwenden. Ein Passwortfeld hat dieselbe Syntax wie ein Textfeld, wobei jedoch dem type-Attribut der Wert PASSWORD anstelle des Wertes TEXT zugewiesen wird: <input type="PASSWORD" name="text" size="zahl" maxlength="zahl" value="text"> Die Attribute eines Passwortfelds haben dieselbe Bedeutung wie die Attribute eines Textfeldes. Kontrollkästchen erstellen Für Daten, die nur einen von zwei Werten annehmen können, wie beispielsweise an oder aus, ist das Kontrollkästchen (engl. check box) geeignet. Beispielsweise können Sie damit einen Benutzer wählen lassen, ob er eine Expresslieferung bestellter Waren wünscht oder nicht. Wenn das entsprechende Kontrollkästchen aktiviert (markiert) ist, werden die Waren per Express geliefert, andernfalls erfolgt der Versand auf normalem Wege. Die Syntax für ein Kontrollkästchen lautet: <input type="CHECKBOX" name="text" checked value="text"> Das type-Attribut ist erforderlich. Die Attribute name, checked und value sind optional. Wenn das checked-Attribut angegeben wird, ist das Kontrollkäst- Kapitel 3: HTML-Formulare erstellen 65 chen standardmäßig aktiviert, andernfalls ist das Kontrollkästchen anfangs nicht aktiviert. Das value-Attribut legt den Wert fest, der an den Server gesendet wird, wenn das Kontrollkästchen aktiviert ist. Wenn dieses Attribut nicht angegeben ist, wird der Wert on gesendet. Optionsfelder erstellen Ein Optionsfeld (engl. radio button) kann – wie ein Kontrollkästchen – nur einen von zwei Werten annehmen. Jedoch werden Optionsfelder zu Gruppen zusammengefasst, wobei zu jedem Zeitpunkt nur ein Optionsfeld in einer Gruppe aktiviert sein kann und die anderen deaktiviert sein müssen. Optionsfelder eignen sich dazu, den Benutzer eine Option aus einer Gruppe sich gegenseitig ausschließender Alternativen wählen zu lassen. Beispielsweise können Sie einen Satz aus drei Optionsfeldern verwenden, um den Benutzer die Art einer Geschenkverpackung wählen zu lassen: keine, einfach oder ausgefallen. Nur eins der drei Optionsfelder kann aktiviert werden. Zusammen bieten die Optionsfelder dem Benutzer eine Drei-Wege-Wahl. Die Syntax für ein Optionsfeld lautet: <input type="RADIO" name="text" checked value="text"> Beachten Sie, dass Optionsfelder dieselbe Syntax wie Kontrollkästchen verwenden, außer dass das type-Attribut den Wert RADIO statt CHECKBOX hat. Die Attribute eines Optionsfelds haben dieselbe Bedeutung wie bei einem Kontrollkästchen. Jedoch ist das name-Attribut bei Optionsfeldern erforderlich, während es bei Kontrollkästchen optional ist. Alle Mitglieder eines Satzes von Kontrollkästchen verwenden für das name-Attribut denselben Wert. Auswahllisten erstellen Eine Auswahlliste (engl. select) ist ein verschiebbares Menü, aus dem der Benutzer eine oder mehrere Optionen auswählen kann. Beispielsweise könnten Pizzabeläge in einer Auswahlliste präsentiert werden, sodass ein Benutzer jede gewünschte Kombination von Belägen wählen könnte. Die Syntax für eine Auswahlliste lautet: <select name="text" multiple size="zahl">Hier stehen die option-Tags mit den Optionen</select> Das select-Tag bildet mit dem /select-Tag ein Paar, das zusammen eine Reihe von option-Tags einschließt. Bei einem select-Tag ist nur das name-Attribut erforderlich. Das multipleAttribut legt fest, dass der Benutzer mehrere Optionen wählen kann, indem er 3 66 PHP 4 IT-Tutorial die (Strg)-Taste gedrückt hält und die Optionen anklickt. Ohne das multipleAttribut kann der Benutzer nur eine einzige Option wählen. Wenn Sie das multiple-Attribut verwenden, sollten Sie dem Control in dem name-Attribut einen Array-Namen zuweisen. Beispielsweise sollten Sie einer Auswahlliste, mit deren Hilfe der Benutzer mehrere Beilagen wählen kann, den Namen beilagen[] statt beilagen zuweisen. Eine Auswahlliste, aus der nur eine einzige Option ausgewählt werden kann, verhält sich wie ein Satz von Optionsfeldern, aber – wie Sie in dem Projekt am Ende dieses Abschnitts sehen werden – das Aussehen einer Auswahlliste unterscheidet sich von dem eines Satzes von Optionsfeldern. Das size-Attribut legt die Anzahl der sichtbaren Optionen fest. Mit einer Pulldown-Schaltfläche oder einer Scroll-Leiste kann der Benutzer die Auswahlliste manipulieren, um auf die restlichen Optionen zuzugreifen und diese auszuwählen. Wie bereits erklärt wurde, bietet eine Auswahlliste eine oder mehrere Optionen an. Um eine Option für eine Auswahlliste zu erstellen, wird die folgende Syntax verwendet: <option selected value="text">Optionsinhalt</option> Das option-Tag bildet mit dem /option-Tag ein Paar. Der Text zwischen diesen Tags wird als Optionsinhalt bezeichnet. Der Optionsinhalt wird in dem Auswahllisten-Control angezeigt. Viele HTML-Programmierer lassen das /optionTag weg. In diesem Fall umfasst der Optionstext die folgende Option oder das /select-Tag. Diese Art der Verwendung ist möglicherweise jedoch nicht mit künftigen Versionen des HTML-Standards kompatibel. Beide Attribute eines option-Tags sind optional. Falls das value-Attribut angegeben wird, wird sein Wert an den Server gesendet, wenn die zugehörige Option ausgewählt wird; andernfalls werden die Optionsinhalte an den Server gesendet. Das selected-Attribut legt fest, dass die entsprechende Option anfänglich ausgewählt ist; andernfalls ist es anfangs nicht ausgewählt. Verborgene Felder erstellen Manchmal ist es nützlich, so genannte verborgene Felder erstellen zu können. Die Werte von verborgenen Feldern werden zusammen mit den Werten der anderen Controls an den Server übertragen. Der Benutzer kann jedoch die Werte verborgener Felder weder sehen noch manipulieren. Verborgene Felder werden häufig verwendet, wenn eine Reihe von Formularen benutzt wird. Beispielsweise könnte es sein, dass Daten, die der Benutzer in dem ersten von mehreren Formularen eingegeben hat, in späteren Formularen noch benötigt werden. Anstatt dem Benutzer zuzumuten, die Daten in jedes Formular einzugeben, können die Daten in einem verborgenen Feld gespeichert Kapitel 3: HTML-Formulare erstellen 67 werden, das von dem Skript erstellt und initialisiert wird, das das erste Formular verarbeitet. Dies erspart dem Benutzer einige Mühe und verhindert einige mögliche Fehler, die beispielsweise daher rühren könnten, dass der Benutzer die Daten nicht einheitlich in die folgenden Formulare eingibt. Um ein verborgenes Feld zu erstellen, wird die folgende Syntax verwendet: <input type="HIDDEN" name="text" value="text"> Nur die Attribute type und name sind erforderlich; jedoch das Control ist ohne das value-Attribut recht nutzlos, dessen Wert automatisch an den Server gesendet wird, wenn das Formular abgeschickt wird. Frage an den Experten Frage: Ich habe HTML-Formulare gesehen, die es einem Benutzer erlauben, Inhalte einer Datei an einen Server zu senden. Wie wird dies gemacht? Antwort: Sie können den Benutzer eine Datei auswählen und deren Inhalt an den Server senden lassen, indem Sie ein Datei-Control (engl. file control) erstellen. Die Syntax lautet: <input type="FILE" name="name" accept="mime_typ" value="text"> Nur das type-Attribut ist erforderlich; jedoch wird im Allgemeinen auch das name-Attribut angegeben. Das value-Attribut legt einen Standarddateinamen fest. Das accept-Attribut gibt das Format des Dateiinhalts an. Es können mehrere Formate aufgeführt werden. In diesem Fall müssen benachbarte Formate durch ein Komma voneinander getrennt werden. Das Format wird mit Hilfe eines MIME-Codes (Multipurpose Internet Mail Extensions) angegeben. Die folgende Tabelle beschreibt die gebräuchlichsten Formate: MIME-Typ Datentyp Dateierweiterungen application/ msexcel Microsoft Excel xls application/ msword Microsoft Wort doc, dot application/ octet-stream Binär exe 3 68 PHP 4 IT-Tutorial MIME-Typ Datentyp Dateierweiterungen application/pdf Adobe Acrobat pdf application/ postscript Postscript ai, eps, ps application/ppt Microsoft PowerPoint ppt application/zip ZIP-komprimierte Daten zip audio/midi Musical Instrument Digital Interface (MIDI) mid, midi audio/x-wav Windows Audio Format (WAV) wav image/gif Compuserve Graphics Interchange Format (GIF) gif image/jpeg Joint Photographics Expert Group (JPEG) jpeg, jpg, jpe image/TIFF Tagged Image Format (TIF) tif, tiff text/HTML HTML htm, html text/plain einfacher Text txt text/richtext Rich Text Format (RTF) rtf video/mpeg Video mpg, mpv, mpe, mpeg video/quicktime Video qt, mov video/x-msvideo Video avi Das method-Attribut des einschließenden form-Tags muss den Wert POST haben. Außerdem sollte das form-Tag über ein enctype-Attribut mit dem Wert multipart/form-data verfügen. Die Syntax, die Sie verwenden sollten, hat die folgende Form: <form method="POST" enctype="multipart/form-data" action="url"> Möglicherweise unterstützt die Konfiguration Ihres Servers nicht alle MIME-Typen. Fragen Sie den Administrator Ihres Servers danach, ob der Typ, den Sie verwenden wollen, korrekt unterstützt wird. Kapitel 3: HTML-Formulare erstellen 1-Minuten-Test ● Schreiben Sie HTML-Code, der ein Textfeld erstellt, das 40 Zeichen breit ist und die Eingabe von maximal 80 Zeichen zulässt. ● Schreiben Sie HTML-Code, der einen Textbereich erstellt, der 80 Spalten breit und 10 Zeilen hoch ist sowie den Textumbruch voll unterstützt. ● Schreiben Sie HTML-Code, der ein anfänglich aktiviertes Kontrollkästchen erstellt und der den Wert "a la mode" an den Server überträgt. ● Schreiben Sie HTML-Code, der ein Paar von Optionsfeldern erstellt, mit dem Sie den Wert "wahr" oder den Wert "falsch" auswählen können. Projekt 3–2: HTML-Formular-Controls In diesem Projekt erstellen Sie ein HTML-Formular, das die verschiedenen p-3–2.php Controls enthält. Sie werden in der Lage sein, die Controls zu manipulieren p-3–2.html und die Daten zu betrachten, die an ein Verarbeitungsskript gesendet werden, das mit dem Formular verbunden ist. Dieses Projekt ist wichtig, um sich ein solides Verständnis aller HTML-Formular-Controls – einschließlich ihres Aussehens und Verhaltens – zu erarbeiten. Projektziele ● Erfahrung im Erstellen von HTML-Formular-Controls erwerben ● Das Aussehen und Verhalten von Formular-Controls demonstrieren ● Eine Möglichkeit zur Verfügung stellen, um mit den Attributen und Werten experimentieren zu können, die mit den HTML-Tags verbunden sind, mit denen Formular-Controls definiert werden Schritt für Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen p-3–2.php, und laden Sie diese Datei auf Ihren PHP-Server herauf: <?php // Datei p-3–2.php ● ● ● ● <input type="TEXT" name="xxxx" size="40" maxlength="80"> <textarea name="xxxx" cols="80" row="10" wrap="physical"></textarea> <input type="CHECKBOX" name="xxxx" checked value="a la mode"> <input type="RADIO" name="xxxx" value="wahr"> und <input type="RADIO" name="xxxx" value="falsch"> 69 3 70 PHP 4 IT-Tutorial phpinfo() ?> 2. Speichern Sie die folgende HTML-Seite unter dem Dateinamen p-3–2.html, und laden Sie diese Datei auf Ihren PHP-Server in dasselbe Verzeichnis wie die Datei p-3–2.php herauf: <html> <head> <title>Formular-Controls</title> </head> <body> <!-- Datei p-3–2.html --> <form method="POST" action="p-3–2.php"> <h3>Formular-Controls</h3> <br>Textfeld: <br><input type="TEXT" name="textbox"> <br> <br>Passwortfeld: <br><input type="PASSWORD" name="passwortfeld"> <br> <br>Textbereich: <br> <textarea name="textarea" rows="5" cols="40" wrap="physical"> Geben Sie hier Ihre Adresse ein. </textarea> <br> <br>Kontrollkästchen:<br> <input type="CHECKBOX" name="fruehstueck"> Frühstück<br> <input type="CHECKBOX" name="mittagessen" checked> Mittagessen<br> <input type="CHECKBOX" name="abendessen" checked> Abendessen<br> <br>Optionsfelder:<br> <input type="RADIO" name="radiobutton" value="franzoesisch" checked>Französisch<br> <input type="RADIO" name="radiobutton" value="italienisch">Italienisch<br> <input type="RADIO" name="radiobutton" value="russisch">Russisch<br> <br> Auswahlliste:<br> <select multiple name="auswahl[]"> Kapitel 3: HTML-Formulare erstellen <option selected value="kaese">Käse</option> <option value="extra">Extra Käse</option> <option selected value="pepperoni">Pepperoni</option> <option value="wurst">Wurst</option> <option value="salami">Salami</option> <option value="pilze">Pilze</option> </select> <br> <input type="HIDDEN" name="schatz" value="wertvoll"> <br> <br><input type="SUBMIT" value="Daten senden"> </form> </body> </html> 3. Geben Sie den URL des HTML-Formulars in das Adressfeld Ihres Webbrowsers ein. Die Anzeige Ihres Browsers sollte so ähnlich aussehen wie Abbildung 3.1. Betrachten Sie die Formular-Controls. Achten Sie dabei besonders auf ihr Aussehen. Experimentieren Sie mit den Controls, um sich mit ihren verschiedenen Verhaltensmöglichkeiten vertraut zu machen. Wenn Sie mit den eingegebenen Werten zufrieden sind, klicken Sie auf die SUBMIT-Schaltfläche (DATEN SENDEN), um die Daten des Formulars an den Server zu senden. 4. Wenn das Verarbeitungsskript p-3–2.php ausgeführt wird, zeigt es einen umfangreichen Bericht über den Status des PHP-Servers an. In dem Abschnitt PHP-Variablen finden Sie Informationen über die Werte der Formularvariablen (siehe Abbildung 3.2). 5. Nachdem Sie untersucht haben, wie der ursprüngliche HTML-Code funktioniert, sollten Sie ihn ändern, um herauszufinden, was die verschiedenen Attribute und Werte bewirken. Beispielsweise können Sie das multiple-Attribut der Auswahlliste entfernen und versuchen, mehrere Pizzabeläge zu wählen. Damit die Änderungen des HTML-Codes in Ihrem Browser angezeigt werden, sollten Sie die Seite aktualisieren, nachdem Sie sie geändert und heraufgeladen haben. 71 3 72 PHP 4 IT-Tutorial Abbildung 3.3 HTML-Formular-Controls Kapitel 3: HTML-Formulare erstellen 73 3 Abbildung 3.4 Die Werte der Felder, die von dem HTML-Formular an den Server gesendet wurden Mehr über das Abschicken eines Formulars In den vorangegangenen Abschnitten dieses Kapitels haben Sie gelernt, wie HTML-Formulare erstellt werden, die Daten an einen Server senden können. In diesem Abschnitt werden Sie mehr darüber erfahren, wie Formulare übertragen werden. Insbesondere lernen Sie, wie Sie anstelle einer SUBMIT-Schaltfläche ein Bild verwenden können, wie Sie eine RESET-Schaltfläche erstellen können, wie Sie eine Seite mit mehreren Formularen erstellen können und wie Sie Informationen an ein Skript übertragen können, indem Sie den URL des Skripts verwenden. 74 PHP 4 IT-Tutorial Daten mit einer Bildschaltfläche abschicken Eine SUBMIT-Schaltfläche sieht langweilig und gewöhnlich aus. Wenn das Aussehen einer Seite wichtig ist, sollten Sie anstelle einer SUBMIT-Schaltfläche ein Bild verwenden. Ein solches Bild wird manchmal auch als Bildschaltfläche (engl. image button) bezeichnet. Wenn ein Benutzer auf eine Bildschaltfläche klickt, werden die Formulardaten so wie beim Anklicken einer SUBMIT-Schaltfläche an den Server gesendet. Die Syntax für eine Bildschaltfläche lautet: <input type="IMAGE" src="url" name="text" align="align"> Die Attribute type und src sind erforderlich; die anderen Attribute sind optional. Das src-Attribut gibt den URL der Datei an, die das Bild enthält, das angezeigt werden soll. Das name-Attribut weist der Bildschaltfläche einen Namen zu. Das align-Attribut legt die Ausrichtung der Bildschaltfläche relativ zum umgebenden Text fest. Es kann einen der Werte top, middle oder bottom (oben, mittig oder unten) annehmen. Tipp Das Projekt am Ende dieses Abschnitts enthält eine Bildschaltfläche. Sie sollten dieses Projekt auf jeden Fall bearbeiten, damit Sie mit dem Aussehen und Verhalten von Bildschaltflächen vertraut werden. Eine RESET-Schaltfläche erstellen Manchmal ist es für den Benutzer hilfreich, wenn er auf eine Schaltfläche klicken kann, die die Informationen eines Formulars löscht. Eine solche Schaltfläche wird als RESET-Schaltfläche bezeichnet. Die Syntax für eine RESET-Schaltfläche lautet: <input type="RESET" value="text"> Nur das type-Attribut ist erforderlich. Das optionale value-Attribut legt den Text fest, der auf der RESET-Schaltfläche angezeigt werden soll. Wenn das valueAttribut ausgelassen wird, erhält die Schaltfläche die Beschriftung Reset. Kapitel 3: HTML-Formulare erstellen 75 Eine Seite mit mehreren Formularen erstellen Wie bereits erwähnt wurde, können Sie in eine einzelne HTML-Seite mehr als ein Formular einfügen. Jedes Formular muss über eine separate SUBMIT- oder Bildschaltfläche verfügen. Eine RESET-Schaltfläche innerhalb eines Formulars gilt nur für das betreffende Formular. Das folgende Beispiel zeigt eine Seite mit mehreren Formularen: <html> <head> <title>Eine Seite mit mehreren Formularen</title> </head> <body> <!-- Das erste Formular --> <form method="POST" action="kunden-formular-verarbeiten.php"> <br>Kundenname: <br><input type="TEXT" name="kunden_name"> <br><input type="SUBMIT" value="Kundendaten senden"> </form> <!-- Das zweite Formular --> <form method="POST" action="lieferanten-formular-verarbeiten.php"> <br>Lieferantenname: <br><input type="TEXT" name="lieferanten_name"> <br><input type="SUBMIT" value="Lieferantendaten senden"> </form> </body> </html> Die Seite enthält zwei Formulare, die dazu dienen, Kunden- bzw. Lieferanteninformationen zu übertragen. Jedes Formular verfügt über eine eigene SUBMITSchaltfläche. Je nachdem, welche SUBMIT-Schaltfläche angeklickt wird, wird ein Kundenname oder ein Lieferantenname zur Weiterverarbeitung an den Server gesendet. In diesem Beispiel verfügt jedes Formular über ein eignes Verarbeitungsskript. Die Daten aus den beiden Formularen könnten jedoch auch mit einem einzigen Skript verarbeitet werden. Ein solches Skript könnte anhand der empfangenen Felder und Werte ermitteln, ob es mit einem Kunden- oder einem Lieferantenformular arbeitet. 3 76 PHP 4 IT-Tutorial Einem Skript per Link Daten zur Verfügung stellen Neben der Möglichkeit, Formulardaten mit Formularfeldern an ein Skript zu übertragen, können Sie Daten auch mit Hilfe des URLs des Skripts übertragen, das in dem action-Attribut des form-Tags angegeben ist. Zu diesem Zweck setzen Sie ein Fragezeichen (?) hinter den URL und fügen dann eine Reihe von Name-Wert-Paaren der folgenden Form ein: name1=wert1&name2=wert2&name3=wert3 Das Beispiel enthält nur drei Name-Wert-Paare. Sie können jedoch so viele Paare hinzufügen, wie der Browser des Benutzers zulässt. Der resultierende URL wird als Abfragestring (engl. query string) bezeichnet. Er darf keine Leerzeichen enthalten. Wenn Sie ein Leerzeichen in einen Abfragestring einfügen wollen, müssen Sie stattdessen ein Pluszeichen (+) übertragen. Das folgende Beispiel zeigt einen Abfragestring, der den Namen das Autors codiert: http://www.osborne.com/search.cgi?author=Bill+McCarty Frage an den Experten Frage: Was passiert, wenn ich spezielle Zeichen, wie beispielsweise ein Fragezeichen, ein Gleichheitszeichen oder ein kaufmännisches Und-Zeichen per URL an ein Skript senden will? Führt dies nicht zu Verwirrung? Antwort: Ja – damit die Daten korrekt übertragen werden können, muss ein Abfragestring URL-codiert (engl. URL encoded) werden. Um einen Abfragestring zu URL-codieren, werden spezielle Zeichen durch ihre Hexadezimalwerte ersetzt, denen ein Prozentzeichen (%) vorangestellt wird. Einzelheiten darüber können Sie dem Request for Comment (RFC) 1738 entnehmen, der unter www.rfc.net verfügbar ist. Tabelle 3.1 zeigt einige der gebräuchlichsten Sonderzeichen und ihre URL-codierten Formen. Beispielsweise hat der String "happy birthday!" die URL-codierte Form %22happy birthday%21 %22. Kapitel 3: HTML-Formulare erstellen Sonderzeichen URL-codierte Form . %2e ? %3e ^ %5e ~ %7e + %2b , %2c / %2f : %3a ; %3b < %3c = %3d > %3d [ %5b \ %5c ] %5d _ %5f { %7b | %7c } %7d Tab %09 Leerzeichen %20 ! %21 „ %22 # %23 $ %24 % %25 & %26 ‘ %27 ( %28 ) %29 @ %40 ‘ %60 Tabelle 3.1 URL-codierte Formen gebräuchlicher Sonderzeichen 77 3 78 PHP 4 IT-Tutorial 1-Minuten-Test ● Schreiben Sie HTML-Code, der eine Bildschaltfläche mit dem Namen Los! erstellt. ● Schreiben Sie HTML-Code, der eine RESET-Schaltfläche mit der Aufschrift Neu anfangen erstellt. ● Schreiben Sie einen Abfragestring, der die Variable farbe und den Wert rot an den Server unter www.mitp.com/test sendet. Projekt 3–3: Eine HTML-Seite mit mehreren Formularen p-3–3.php p-3–3.html p-3–3.gif In diesem Projekt werden Sie eine HTML-Seite erstellen, die zwei Formulare enthält. Das eine Formular verfügt über eine SUBMIT-Schaltfläche, das andere über eine Bildschaltfläche. Beide Formulare enthalten eine RESET-Schaltfläche. Die Werte der action-Attribute der Formulare enthalten URL-codierte Abfragestrings, die an den Server gesendet werden, wenn das jeweilige Formular abgeschickt wird. Projektziele ● Erfahrungen im Erstellen und Anwenden von Seiten mit mehreren Formularen vermitteln ● Das Aussehen und Verhalten von Bild- und RESET-Schaltflächen demonstrieren ● Abfragestrings demonstrieren Schritt für Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen p-3–3.php, und laden Sie diese Datei auf Ihren PHP-Server herauf: <?php // Datei p-3–3.php phpinfo() ?> ● <input type="IMAGE" src="xxx" name="Los!"> ● <input type="RESET" value="Neu anfangen"> ● http://www.mitp.com/test?farbe=rot Kapitel 3: HTML-Formulare erstellen 79 2. Speichern Sie die folgende HTML-Seite unter dem Dateinamen p-3 – 3.html , und laden Sie diese Datei auf Ihren PHP-Server in dasselbe Verzeichnis wie die Datei p-3–3.php herauf: <html> <head> <title>Mehr über das Abschicken von Formularen</title> </head> <body> <!-- Datei p-3–3.html --> <h3>Mehr über das Abschicken von Formularen</h3> <form method="POST" action="p-3–3.php?kapitel=3&projekt=3"> <br>Kundenname: <br><input type="TEXT" name="kunden_name"> <br> <br><input type="RESET" value="Formular löschen"> <br> <br><input type="SUBMIT" value="Daten senden"> </form> <hr> <form method="POST" action="p-3–3.php"> <br>Lieferantenname: <br><input type="TEXT" name="lieferanten_name"> <br> <br><input type="RESET" value="Formular löschen"> <br> <br><input type="IMAGE" src="p-3–3.gif"> </form> </body> </html> Laden Sie dann die Datei p-3–3.gif von der Website dieses Buches herunter, und laden Sie sie auf Ihren PHP-Server in dasselbe Verzeichnis wie das PHP-Skript und die HTML-Datei herauf. 3. Geben Sie den URL des HTML-Formulars in das Adressfeld Ihres Webbrowsers ein. Die Anzeige Ihres Browsers sollte Abbildung 3.3 ähneln. Füllen Sie die beiden Textfelder aus, und klicken Sie dann auf eine der RESET-Schaltflächen (FORMULAR LÖSCHEN). Beachten Sie, dass die RESET-Schaltfläche nur die Felder des Formulars löscht, das die Schaltfläche enthält. 3 80 PHP 4 IT-Tutorial Abbildung 3.5 Seite mit mehreren Formularen 4. Klicken Sie auf die SUBMIT-Schaltfläche (DATEN SENDEN). Die Anzeige Ihres Browsers sollte Abbildung 3.4 ähneln. 5. Beachten Sie, wie die Name-Wert-Paare in dem Abfragestring zusammen mit dem Wert des Textfeldes in der Liste der PHP-Variablen angezeigt werden. 6. Klicken Sie auf die ZURÜCK-Schaltfläche Ihres Browsers, um zu dem HTML-Formular zurückzukehren. Klicken Sie dann auf die Bildschaltfläche. Beachten Sie, wie sich die Anzeige des Browsers von der Anzeige in Abbildung 3.4 unterscheidet. Können Sie sehen, wie ein PHP-Skript mehrere Formulare verarbeiten könnte, indem es die Variablen und ihre Werte abfragt? Kapitel 3: HTML-Formulare erstellen 81 3 Abbildung 3.6 Die Werte der Felder, die von der Mehr-Formular-Seite an den Server gesendet wurden 9Übungsaufgaben 1. Schreiben Sie ein HTML-form-Tag, das seine Daten an ein Skript sendet, das sich unter http://www.mitp.de/cgi-bin/test befindet. 2. Schreiben Sie HTML-Code, der ein mehrzeiliges Control namens adresse zur Texteingabe erstellt. Das Control sollte fünf Zeilen à 80 Zeichen aufnehmen können. 3. Schreiben Sie HTML-Code, der ein Pulldown-Menü namens farbe erstellt, das die subtraktiven Primärfaben rot, gelb und blau enthält. Lassen Sie nur die Wahl einer Option zu, und legen Sie rot als Standardwahl fest. 4. Schreiben Sie HTML-Code, der einen Satz von Optionsfeldern namens size erstellt, mit dem der Benutzer einen der Werte klein, mittel oder groß wählen kann. 5. Schreiben Sie HTML-Code, der ein Formular erstellt, das seine Daten an www.dev.null sendet. Das Formular sollte ein verborgenes Feld namens skript enthalten, das den Wert menu hat. Kapitel 4 Auf Daten zugreifen Lernziele ● Auf skalare Daten zuzugreifen, die von einem HTMLFormular an ein PHP-Programm übertragen werden ● Wie mit dem PHP-echo-Befehl Output an den Browser gesendet werden kann ● Wie Strings konstruiert werden, die Werte von PHP-Variablen enthalten ● Wie man auf die Werte von Umgebungsvariablen zugreifen kann 84 PHP 4 IT-Tutorial Die meisten PHP-Programme verwenden HTML-Formulare, um Eingabedaten zu erheben. In diesem Kapitel lernen Sie, wie Sie auf Daten zugreifen können, die von einem HTML-Formular an ein PHP-Programm übertragen werden. Außerdem erfahren Sie, wie Sie auf Daten zugreifen können, die in client- oder serverseitigen Umgebungsvariablen gespeichert sind. Umgebungsvariablen speichern nützliche Informationen über Browser, Webserver und PHP. Daten eines Formulars empfangen und verarbeiten Weil PHP als Skriptsprache für das Web entwickelt wurde, ist es in PHP einfach, auf Variablen zuzugreifen, die von HTML-Formularen übertragen werden. Im vorangegangen Kapitel haben Sie gelernt, wie HTML-Formulare erstellt werden. Das folgende Beispiel zeigt ein einfaches HTML-Formular, das ein Textfeld enthält: <html> <head> <title>Ein einfaches HTML-Formular</title> </head> <body> <form method="POST" action="phpinfo.php"> <br>Geben Sie einige Daten ein: <br><input type="TEXT" name="daten"> <br><br><input type="SUBMIT"> </form> </body> </html> Das name-Attribut des input-Tags weist dem Textfeld den Namen daten zu. Wenn Sie ein Skript namens phpinfo.php erstellen, das die phpinfo()-Funktion ausführt und es in demselben Ordner wie das Formular speichern, zeigt das Skript nach dem Absenden des Formulars einen Bericht über den Status des PHP-Anwendungsservers an. Im Abschnitt PHP Variables zeigt der Statusbericht die Werte der Formularvariablen (siehe Abbildung 4.1). Kapitel 4: Auf Daten zugreifen 85 4 Abbildung 4.1 Ein PHP-Statusbericht mit den Werten der Formularvariablen daten Der Statusbericht verfügt über zwei Spalten. Der Name der Variablen des Formular-Controls, daten, wird in der linken Spalte angezeigt, wo er in den Text _POST["daten"] eingebettet ist. Der Wert der Variablen, d.h. der Text, den der Benutzer eingetippt hat, wird in der rechten Spalte angezeigt. In Abbildung 4.1 lautet dieser Text meine Eingabe. Frage an den Experten Frage: Das Konstrukt HTTP_POST_VARS["daten"] sieht verdächtig nach einer Array-Referenz aus. Was geht hier vor? Antwort: Wenn Ihnen die eckigen Klammern aufgefallen sind und Sie sich daran erinnert haben, dass diese zu PHP-Arrays gehören, dann folgen Sie dem Text sehr aufmerksam. Wenn nicht, haben Sie mehr von diesem Kapitel, wenn Sie schnell noch einmal den Abschnitt Skalare und Arrays in Kapitel 2 überfliegen. Wenn ein Formular abgeschickt wird, werden die Namen und Werte von Variablen, die in dem Formular enthalten sind, in das Array _POST eingefügt. Die Schlüssel der Array-Elemente bestehen aus den Namen der Formularvariablen; die Werte der Array-Elemente bestehen aus den Werten der Variablen. Wenn Sie wollen, können Sie mit Hilfe des Arrays _POST auf die Formularvariablen zugreifen; Sie werden jedoch bald eine bequemere Methode für diesen Zweck kennen lernen. 86 PHP 4 IT-Tutorial Output an den Browser senden Natürlich dürfen Sie nicht erwarten, dass der Benutzer einen PHP-Statusbericht liest, um die Werte von Variablen zu erfahren. Darüber hinaus geht es beim Programmieren darum, Werte zu manipulieren und nicht nur anzuzeigen. In diesem Unterabschnitt lernen Sie, wie Sie mit dem echo-Befehl Output an den Browser senden können. Im nächsten Unterabschnitt werden Sie lernen, wie Sie Strings konstruieren können, in die die Werte von Variablen eingebettet sind. Durch eine Kombination dieser Verfahren können Sie die Werte von PHP-Variablen in einem Formular anzeigen, das der Benutzer sofort entziffern kann. In späteren Kapiteln lernen Sie, wie Sie die Werte von Variablen manipulieren können, sodass Sie nützliche PHP-Programme erstellen können. Mit dem echo-Befehl können Sie Output an den Browser senden. Der Befehl hat verschiedene Formen. Die vielleicht nützlichste Form lautet: echo string_ausdruck; Diese Form besteht nur aus dem Schlüsselwort echo, gefolgt von einem Stringausdruck und einem Semikolon, das den Befehl abschließt. In dieser Form sendet der Befehl einfach den Wert von string_ausdruck an den Browser. Beispielsweise sendet der Befehl echo "<br><b>Daten sind Klasse!</b>"; den Text "Daten sind Klasse!" an den Browser. Beachten Sie, dass der Text HTML-Tags enthält, die die Formatierung des Textes beeinflussen und dafür sorgen, dass er in einer neuen Zeile in fetter Schrift angezeigt wird. Der Nutzen dieser Form des echo-Befehls basiert auf den vielen Arten, wie ein Stringausdruck geschrieben werden kann. Eine der nützlichsten Methoden verwendet den Verkettungsoperator, um zwei Stringausdrücke zu verknüpfen. Betrachten Sie beispielsweise den folgenden echo-Befehl: echo "Daten sind " . "Klasse!"; Der Verkettungsoperator, der durch einen Punkt (.) repräsentiert wird, hängt den zweiten Stringausdruck an den ersten an und erzeugt damit dasselbe Ergebnis wie der folgende Befehl: echo "Daten sind Klasse!"; Kapitel 4: Auf Daten zugreifen 87 Der echo-Befehl ist etwas seltsam, weil er einer Funktion ähnelt, aber keine ist. Beispielsweise können Sie den Stringausdruck, der für echo erforderlich ist, in Klammern einschließen: echo("Daten sind Klasse!"); Wenn Sie wollen, können Sie mehrere Stringausdrücke zur Verfügung stellen, die jeweils durch ein Komma voneinander getrennt werden: echo "Daten sind", "Klasse!"; Sie dürfen jedoch nicht Klammern und Kommas gleichzeitig verwenden, wie dies bei echten Funktionen erlaubt ist: echo("Daten sind", "Klasse!"); // Syntaxfehler Darüber hinaus muss der Ausdruck, der hinter echo steht, kein Stringausdruck sein, solange PHP den Ausdruck in einen String umwandeln kann. Beispielsweise ist auch die folgende Konstruktion zulässig: echo "eins plus eins ist "; echo 2; Frage an den Experten Frage: Angenommen, dass mein PHP-Programm HTML-Tags ausgibt, die dazu führen, dass mein Programm mit HTML-Code vermischt wird. Gibt es in diesem Fall eine bequemere Weise, um echo-Befehle zu schreiben? Antwort: Ja, die gibt es. Anstatt <? echo "mein Output"; ?> zu schreiben, können Sie auch einfach schreiben: <?= "mein Output" ?> PHP interpretiert das Gleichheitszeichen als Abkürzung für echo, solange das Gleichheitszeichen unmittelbar hinter dem <? steht. Beachten Sie jedoch, dass diese Funktion nur zur Verfügung steht, wenn PHP mit der short_tags-Konfigurationsoption kompiliert oder konfiguriert wurde. Wenn Sie <?= nicht verwenden können, bitten Sie Ihren Systemadministrator, diese Option einzurichten. 4 88 PHP 4 IT-Tutorial Die Werte von Variablen in Strings einbetten Um die Werte von Variablen an den Browser senden zu können, müssen Sie nur noch lernen, wie Sie die Werte von Variablen in Stringausdrücke einbetten können. Das folgende Beispiel zeigt ein einfaches Skript, das einen solchen Stringausdruck enthält: <?php $radius = 2; $pi = 3.14159; $flaeche = $pi * $radius * $radius; echo "Die Fläche ist $flaeche."; ?> Wenn Sie den Namen einer Variablen, wie beispielsweise $flaeche, in einen String einbetten, ersetzt PHP den Namen der Variablen durch ihren Wert. Wenn Sie das Beispielskript ausführen, wird der folgende Output angezeigt: Die Fläche ist 12.56636. Wenn Sie nicht den Wert, sondern den Namen einer Variablen ausgeben wollen, müssen Sie nur einen Backslash (\) vor den Namen der Variablen setzen. Betrachten Sie das folgende Beispiel: <?php $radius = 2; $pi = 3.14159; $flaeche = $pi * $radius * $radius; echo "Der Wert von \$flaeche ist $flaeche."; ?> Der Output dieses Skripts lautet: Der Wert von $flaeche ist 12.56636. Kapitel 4: Auf Daten zugreifen 1-Minuten-Test ● Schreiben Sie einen echo-Befehl, der den Text "PHP ist eine leistungsfähige Programmiersprache." ausgibt. ● Schreiben Sie einen echo-Befehl, der den Wert der Variablen $umfang ausgibt. ● Schreiben Sie einen echo-Befehl, der den Namen der Variablen $root, dann ein Gleichheitszeichen und dann den Wert der Variablen ausgibt. Projekt 4–1: Die E-Mail-Adressbücher In diesem Projekt werden Sie PHP-Befehle schreiben, die auf Daten zugreifen, die mit einem HTML-Formular erhoben werden. Außerdem werden Sie PHPp-4–1.php p-4–1.html Befehle schreiben, die HTML-Daten an den Browser des Benutzers senden. Dieses Projekt ist das erste in einer Reihe von Projekten, die zu einer PHPAnwendung ausgebaut werden, die ein Adressbuch zur Verfügung stellt, das über das Web zugänglich ist. Mehr über das Adressbuch und seine Fähigkeiten werden Sie im weiteren Verlauf der Arbeit an dieser Anwendung erfahren. Projektziele ● Zeigen, wie PHP-Strings geschrieben werden, die Daten enthalten, die mit einem HTML-Formular erhoben wurden ● Zeigen, wie mit dem echo-Befehl von PHP Daten an den Browser des Benutzers gesendet werden können Schritt für Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen p-4–1.html, und laden Sie diese Datei auf Ihren PHP-Server herauf: <html> <head> <title>Projekt 4–1</title> </head> <body> <!-- Datei p-4–1.html --> ● echo "PHP ist eine leistungsfähige Programmiersprache."; ● echo "Der Wert ist $umfang."; oder ähnlich ● echo "\$root=$root"; 89 4 90 PHP 4 IT-Tutorial <form method="POST" action="p-4–1.php"> <H2>Adressliste</H2> <br>Spitzname: <br><input type="TEXT" name="spitzname"> <br> <br>Kompletter Name: <br><input type="TEXT" name="kompletter_name"> <br> <br>Notiz: <br><textarea name="notiz" rows="4" cols="40" wrap="PHYSICAL"> </textarea> <br> <br> <input type="SUBMIT"> </form> </body> 2. Speichern Sie das folgende PHP-Skript unter dem Dateinamen p-4–1.php, und laden Sie diese Datei auf Ihren PHP-Server in dasselbe Verzeichnis wie die Datei p-4–1.html: <?php // Datei p-4–1.php echo "<br>Spitzname = $spitzname"; echo "<br>Kompletter Name = $kompletter_name"; echo "<br>Notiz = $notiz"; ?> 3. Geben Sie den URL der HTML-Datei, die Sie zuvor heraufgeladen haben, in das Adressfeld Ihres Webbrowsers ein. Die Anzeige des Browsers sollte der Abbildung 4.2 ähneln. Geben Sie einen Spitznamen, den kompletten Namen und eine Notiz ein. Klicken Sie dann auf die SUBMIT-Schaltfläche (ANFRAGE SENDEN). 4. Wenn das Verarbeitungsskript ausgeführt wird, greift es auf die Werte der drei Formularvariablen zu und sendet die Namen und Werte der Variablen an den Browser des Benutzers (siehe Abbildung 4.3). Kapitel 4: Auf Daten zugreifen 91 4 Abbildung 4.2 Das HTML-Formular Abbildung 4.3 Die Ausgabe des PHP-Skripts Daten einer Umgebungsvariablen abfragen und benutzen Wenn Sie mit UNIX oder MS-DOS vertraut sind, wissen Sie wahrscheinlich, was Umgebungsvariablen sind. Umgebungsvariablen werden verwendet, um Optionen und Parameter zu speichern, die die Anwendungsumgebung konfigurieren. Anwendungen können auf die Werte von Umgebungsvariablen zugreifen und ihr Verhalten entsprechend anpassen. Beispielsweise wird unter MS-DOS 92 PHP 4 IT-Tutorial der Suchpfad für Programme in einer Umgebungsvariablen namens PATH gespeichert. Im Allgemeinen werden Befehle des Betriebssystems dazu verwendet, Umgebungsvariablen zu definieren und deren Werte festzulegen. Es gibt jedoch auch Anwendungen, die die Werte von Umgebungsvariablen manipulieren. Sowohl der Apache-Webserver als auch der PHP-Anwendungsserver verwenden Umgebungsvariablen, um Statusinformationen zu präsentieren. Tabelle 4.1 zeigt einige der wichtigsten Umgebungsvariablen, die von Apache und PHP verwendet werden. Neben Apache stellen auch zahlreiche andere Webserver einige oder die meisten dieser Umgebungsvariablen zur Verfügung. Umgebungsvariable Beschreibung CONTENT_LENGTH Die Länge des Körpers der Anfrage in Bytes CONTENT_TYPE Der MIME-Typ der Daten in dem Körper der Anfrage. DOCUMENT_ROOT Der Pfad, der das Stammverzeichnis des Dokument-Verzeichnisbaums des Webservers angibt GATEWAY_INTERFACE Die Version des CGI-Protokolls (Common Gateway Interface), das von dem Webserver verwendet wird HTTP_ACCEPT Der Inhalt des HTTP Accept:-Headers HTTP_ACCEPT_CHARSET Der Inhalt des HTTP Accept-Charset:-Headers, der die Zeichensätze festlegt, die von dem Client verstanden werden HTTP_ACCEPT_ENCODING Der Inhalt des HTTP Accept-Encoding:-Headers, der die Der Inhaltstypen festlegt, die von dem Client verstanden werden. HTTP_ACCEPT_LANGUAGE Der Inhalt des HTTP Accept-Language:-Headers, der die Sprachen festlegt, die von dem Client bevorzugt werden HTTP_CONNECTION Der Inhalt des HTTP Connection:-Headers, der die Optionen anzeigt, die von dem Client angefordert wurden HTTP_HOST Der Inhalt des HTTP Host:-Headers, der den Host-Namen anzeigt, den der Client verwendet hat, um seine Anforderung zu erstellen HTTP_REFERER Der URL der Webseite, die den Client-Browser zur aktuellen Seite geschickt hat HTTP_USER_AGENT Der Inhalt des HTTP User-Agent:-Headers, der den Client-Browser und dessen Version anzeigt PATH Der Ausführungspfad der Server-Umgebung QUERY_STRING Der Abfragestring, der – falls überhaupt – die Anfrage begleitet hat REMOTE_ADDR Die IP-Adresse des Clients Tabelle 4.1 Wichtige PHP-Umgebungsvariablen Kapitel 4: Auf Daten zugreifen Umgebungsvariable Beschreibung HTTP_HOST Der Host-Name des Clients REMOTE_PORT Die Client-Port-Adresse, von der die Anfrage gesendet wurde REQUEST_METHOD Die HTTP-Anfragemethode, die verwendet wurde – beispielsweise GET, POST, PUT oder HEAD REQUEST_URI Der URI, der dazu verwendet wurde, um auf die aktuelle Seite zuzugreifen. Der URI besteht aus einem URL und einem optionalen Abfragestring. SCRIPT_FILENAME Der Absolute Pfadname des aktuellen Skripts SCRIPT_NAME Der URL des aktuellen Skripts SERVER_ADMIN Die E-Mail-Adresse des Administrators des Webservers SERVER_NAME Der Host-Name des Webservers, der die Anfrage bearbeitet SERVER_PORT Der Port, der von dem Webserver zur Kommunikation verwendet wird SERVER_PROTOCOL Der Name und die Version des Protokolls, durch das die Anfrage gestellt wurde SERVER_SIGNATURE Der String, der die Version des Webservers und den Namen des Hosts angibt, der die Anfrage verarbeitet SERVER_SOFTWARE Der String, der das Webserver-Programm und dessen Version angibt Tabelle 4.1 Wichtige PHP-Umgebungsvariablen Viele dieser Variablen beschreiben Eigenschaften der HTTP-Anforderung, die die Ausführung des PHP-Programms ausgelöst hat. Mit der phpinfo()-Funktion können Sie alle Umgebungsvariablen anzeigen, die für PHP-Programme zur Verfügung stehen, und den Output betrachten. Abbildung 4.4 zeigt einen Teil des phpinfo()-Statusberichts, der mehrere Umgebungsvariablen aufführt. Der Zugriff auf eine Umgebungsvariable erfolgt genauso wie der Zugriff auf andere PHP-Variablen. Setzen Sie einfach ein Dollarzeichen ($) vor den Namen der Umgebungsvariablen, so dass der Name der PHP-Syntax entspricht. Beispielsweise sendet der folgende echo-Befehl die IP-Adresse des Clients an den Browser: echo "Der Client hat die IP-Adresse $REMOTE_ADDR."; 93 4 94 PHP 4 IT-Tutorial Frage an den Experten Frage: Viele Informationen in Tabelle 4.1 scheinen ziemlich obskur zu sein. Wozu sind diese Umgebungsvariablen gut? Antwort: Wenn Sie das HTTP-Protokoll nicht im Detail kennen, haben Sie wahrscheinlich für diese Umgebungsvariablen keine große Verwendung. Ein wichtiger gebräuchlicher Einsatzzweck ist jedoch die Authentifizierung des Clients. Mit Hilfe der Umgebungsvariablen REMOTE_ADDR können Sie die IP-Adresse des Clients ermitteln. In einem der folgenden Kapitel lernen Sie, wie Sie den Wert einer Variablen testen und das Verhalten eines Skripts in Abhängigkeit von diesem Wert ändern können. Beispielsweise können Sie mit dieser Technik Anfragen ausschließen, die nicht von IP-Adressen stammen, die zu einem definierten Satz von Adressen gehören – beispielsweise solche Adressen, die zu einem bestimmten Netzwerk gehören. Auf diese Weise können Sie eine Anwendung widerstandsfähiger gegen Hacker-Angriffe machen. Umgebungsvariablen werden häufig auch dafür verwendet, die Begrenzungen bestimmter Browser zu umgehen. Die Umgebungsvariable HTTP_USER_AGENT gibt den Client-Browser und dessen Version an. Ein PHP-Skript kann den Wert dieser Umgebungsvariablen testen und dann nur den Output senden, den die aktuelle Version des verwendeten Browsers verarbeiten kann. Abbildung 4.4 Der Output von phpinfo() mit mehreren Umgebungsvariablen Kapitel 4: Auf Daten zugreifen 95 1-Minuten-Test ● Wie lautet der Name der PHP-Variablen, die den Host-Namen des Webservers enthält? ● Wie lautet der Name der PHP-Variablen, die den Host-Namen des Clients enthält? 4 Projekt 4–2: Umgebungsvariablen anzeigen p-4–2.php In diesem Projekt werden Sie die Werte mehrerer PHP-Umgebungsvariablen anzeigen. Projektziele ● Demonstrieren, wie Umgebungsvariablen angezeigt werden ● Demonstrieren, wie mit dem echo-Befehl Output an den Browser gesendet wird Schritt für Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen p-4–2.php, und laden Sie diese Datei auf Ihren PHP-Server herauf: <?php // Datei p-4–2.php echo "<pre>"; echo "<br><b>Browser :</b> echo "<br><b>Host :</b> echo "<br><b>Quell-URL :</b> echo "<br><b>Remote-Host :</b> echo "<br><b>Remote-Adresse:</b> echo "<br><b>Remote-Port :</b> echo "</pre>"; ?> $HTTP_USER_AGENT"; $HTTP_HOST"; $REQUEST_URI"; $SERVER_NAME"; $REMOTE_ADDR"; $REMOTE_PORT"; 2. Geben Sie den URL des PHP-Skripts in das Adressfeld Ihres Webbrowsers ein. Wenn das Verarbeitungsskript ausgeführt wird, zeigt es die Werte der angegebenen Umgebungsvariablen an (siehe Abbildung 4.5). ● $SERVER_NAME ● $HTTP_HOST 96 PHP 4 IT-Tutorial Abbildung 4.5 Die Umgebungsvariablen, die von p-4–2.php angezeigt werden 9Übungsaufgaben 1. Welche PHP-Variable sollte verwendet werden, um auf die Daten eines Controls zuzugreifen, das durch das HTML-Tag <input type="TEXT" name="farbe"> definiert wird? 2. Schreiben Sie einen PHP-Befehl, der den Wert der Variablen $x an den Browser sendet. 3. Schreiben Sie einen PHP-Befehl, der den Namen der Variablen $y an den Browser sendet. 4. Schreiben Sie einen PHP-Befehl, der den URL der referenzierenden Seite an den Browser sendet. Kapitel 5 Mit skalaren Werten arbeiten Lernziele ● Wie Konstanten definiert und verwender werden ● Wie dynamische Variablen verwendet werden ● Wie Werte aus einem Typ in einen anderen umgewandelt werden 98 PHP 4 IT-Tutorial In Kapitel 2 haben Sie skalare Werte und Arrays kennen gelernt. Während ein Array über mehrere verbundene Werte verfügt, hat ein Skalar nur einen Wert. In diesem Kapitel werden Sie mehr über skalare Werte und das Arbeiten mit ihnen erfahren. Mit Konstanten und dynamischen Variablen arbeiten In den folgenden Unterabschnitten werden Konstanten und dynamische Variablen erklärt. Man kann nützliche und ausgefeilte PHP-Programme schreiben, ohne Konstanten oder dynamische Variablen zu verwenden. Während Programme durch den Einsatz von Konstanten lesbarer werden können, können dynamische Variablen das Gegenteil bewirken. Deswegen sollten dynamische Variablen im Allgemeinen nicht verwendet werden, und schon gar nicht von angehenden PHP-Programmierern. Doch selbst wenn Sie selbst auf dynamische Variablen verzichten, müssen Sie möglicherweise mit PHP-Programmen anderer Programmierer arbeiten, die diese Art von Variablen gern einsetzen; deshalb müssen Sie auch das Arbeiten mit dynamischen Variablen beherrschen, egal, ob Sie diese in Ihren Programmen verwenden oder nicht. Mit Konstanten arbeiten Eine Konstante ist einfach ein Wert, der konstant ist, oder – anders ausgedrückt – ein Wert, der sich nicht ändert. In diesem Sinne sind Konstanten das Gegenteil von Variablen, weil sich der Wert einer Variablen während der Ausführung eines Programms ändern kann. Wenn Sie wollen, können Sie eine Konstante als Readonly-Variable auffassen. Ein Konstante wird mit der define()-Funktion definiert. Betrachten Sie das folgende Beispiel: define("PI", 3.14159); Dieser Befehl definiert die Konstante PI und weist ihr den Wert 3.14159 zu. Nachdem eine Konstante definiert wurde, kann sie in einem Ausdruck verwendet werden. Beispielsweise können Sie die Fläche eines Kreises folgendermaßen berechnen: $flaeche = PI * $radius * $radius; Beachten Sie, dass Referenzen einer Konstante nicht mit einem Dollarzeichen beginnen. Dadurch können Konstanten leicht von Variablen unterschieden wer- Kapitel 5: Mit skalaren Werten arbeiten 99 den. Viele Programmierer verwenden für die Namen von Konstanten nur Großbuchstaben, sodass Konstanten noch leichter identifiziert werden können. Mit einer verwandten Funktion, defined(), können Sie feststellen, ob die angegebene Konstante definiert wurde. Beispielsweise können Sie mit dem folgenden PHP-Befehl feststellen, ob die Konstante PI definiert wurde: echo defined("PI"); Beachten Sie, dass der Name, der getestet werden soll, in doppelte Anführungszeichen eingeschlossen wird. Die defined()-Funktion gibt den Wert eins zurück, wenn die angegebene Konstante definiert wurde; andernfalls gibt sie null zurück. In unserem Beispiel gibt der echo-Befehl den Rückgabewert aus. Aber mit den PHPBefehlen, die in Kapitel 6 beschrieben werden, können Sie den Rückgabewert testen. Konstanten können Programme nicht nur lesbarer machen, sondern auch die Änderung von Programmen vereinfachen. Nehmen Sie beispielsweise an, dass Sie ein Programm geschrieben haben, das viele Berechnungen enthält, die den Wert 3.14159 verwenden, und dass Sie später entdeckt haben, dass Sie den genaueren Wert 3.1415926535898 hätten verwenden sollen. Es kann ziemlich zeitaufwändig sein, jedes Vorkommen des ursprünglichen Wertes zu finden und zu ändern. Aber wenn Sie eine Konstante definiert hätten, um den Wert zu repräsentieren, würde die Zahl 3.14159 nur einmal in dem Programm erscheinen. Ein einziges Vorkommen zu ändern, wäre einfach und trivial. Einige Programmierer sind der Auffassung, dass Ausdrücke nur zwei numerische Werte enthalten sollten: null und eins. Alle anderen Werte sollten als Konstanten repräsentiert werden, um die Lesbarkeit zu verbessern und Änderungen zu vereinfachen. Der Wert π wird in manchen Berechnungen ziemlich häufig verwendet. Zur Vereinfachung der Arbeit stellt PHP eine Funktion zur Verfügung, die besser ist, als eine Konstante mit dem Wert von π zu definieren: Die Funktion pi() gibt den Wert mit einer Genauigkeit von 14 signifikanten Stellen zurück. Mit dieser Funktion können Sie die Fläche eines Kreises mit dem folgenden Ausdruck berechnen: $flaeche = pi() * $radius * $radius; Mit dynamischen Variablen arbeiten Während Konstanten das Verstehen und Ändern von Programmen vereinfachen können, können dynamische Variablen das Gegenteil bewirken. Das folgende Beispiel zeigt ein einfaches Beispiel einer dynamischen Variablen namens $$movie: $steps = 39; $movie = "steps"; echo $$movie; 5 100 PHP 4 IT-Tutorial Eine dynamische Variable wird mit einem Paar Dollarzeichen ($$) benannt und ist mit einer gewöhnlichen Variable verbunden, die einen ähnlichen Namen mit nur einem einzigen Dollarzeichen hat. In unserem Beispiel heißt die dynamische Variable $$movie und ist mit der normalen Variablen $movie verbunden. Der Wert der normalen Variablen enthält (ohne Dollarzeichen) den Namen einer zweiten normalen Variablen. In unserem Beispiel ist die zweite normale Variable $steps. Der Wert dieser zweiten normalen Variablen ist der Wert der dynamischen Variablen. In unserem Beispiel ist der Wert 39. Programmierer sagen, dass eine dynamische Variable ihren Wert indirekt referenziert. Anders ausgedrückt: Eine dynamische Variable enthält keinen Wert, sondern den Ort, an dem der Wert gefunden werden kann, d.h. den Namen einer anderen Variablen. 1-Minuten-Test ● Schreiben Sie einen Befehl, der eine Konstante namens SEITEN definiert und ihr den Wert 4 zuweist. ● Schreiben Sie einen Befehl, der eine Konstante namens GRUSS definiert und ihr den Wert "Hallo" zuweist. ● Schreiben Sie einen Befehl, der den Wert der dynamischen Variablen der normalen Variablen $taube ausgibt. Frage an den Experten Frage: Dynamische Variablen scheinen verwirrend zu sein. Wozu sollte ein Programmierer sie verwenden? Antwort: Wenn Sie dynamische Variablen verwirrend finden, sollten Sie nicht verzweifeln; sie sind verwirrend. Manchmal kann die Größe eines Programms durch eine oder mehrere dynamische Variablen verringert werden. Aber Programmierer machen häufig Fehler, die dazu führen, dass dynamische Variablen falsche oder unerwartete Werte referenzieren. Denken Sie daran, dass es im Allgemeinen wichtiger ist, ein korrektes anstatt ein kurzes Programm zu schreiben. Wenn Sie eine Möglichkeit sehen, mehrere Codezeilen mit Hilfe einer dynamischen Variablen einzusparen, sollten Sie sich gründlich überlegen, ob der zu erwartende Nutzen eine Änderung des Programms rechtfertigt. ● define("SEITEN", 4); ● define("GRUSS", "Hallo"); ● echo $$taube; Kapitel 5: Mit skalaren Werten arbeiten 101 Mit Datentypen arbeiten PHP gehört zu den so genannten dynamically typed programming languages, den Programmiersprachen mit dynamischen Datentypen. Eine Konsequenz dieser Eigenschaft ist die Tatsache, dass der Datentyp (oder kurz Typ) von Variablen nicht angegeben werden muss. PHP bestimmt den Typ einer Variablen anhand des Typs des letzten Wertes, der der Variablen zugewiesen wurde. Jedoch befreit die dynamische Typzuweisung in PHP Sie nicht von den Problemen der Typisierung. Sie müssen mit den unterstützten Datentypen vertraut sein und wissen, was passiert, wenn in Ausdrücken zwei oder mehr Typen gemischt werden. Automatische Typumwandlung Betrachten Sie das folgende kurze PHP-Skript: $x = $y = $z = echo 1; 2.5; $x + $y; $z; Die Zuweisung, die einen Wert in $z speichert, ist interessant, weil ihr rechter Ausdruck einen integer- und einen double-Operand enthält. Welchen Wert würden Sie als Output erwarten? Die richtige Antwort ist 3.5, ein double-Wert. Wenn in einem arithmetischen Ausdruck Typen gemischt werden, führt PHP eine automatische Typumwandlung durch. Falls einer der Operanden double ist, behandelt PHP die anderen Operanden ebenfalls als double, führt die Berechnung aus und gibt das Ergebnis als double zurück. Wenn alle Operanden eines Ausdruck Ganzzahlen sind, führt PHP die Berechnung aus und gibt das Ergebnis als integer zurück. Es ist wichtig zu verstehen, dass bei der Typumwandlung die Typen der Operanden eines Ausdruck nicht ändert werden, sondern die Operanden einfach nur so behandelt werden, als hätten sie einen anderen Typ. In unserem Beispiel bleibt $x ein integer, obwohl PHP diese Variable zum Zweck der Berechnung als double behandelt. Strings können ebenfalls einer Typumwandlung unterworfen werden. Betrachten Sie das folgende Beispiel: $x = 1; $y = $x + "1 mehr"; echo $y; 5 102 PHP 4 IT-Tutorial Hier wird das Wort mehr in dem Textstring ignoriert. Der ausgegebene Wert beträgt zwei – die Summe des Wertes von $x und des numerischen Wertes des Textstrings, der eins beträgt. Der numerische Wert und der Typ eines Strings werden anhand der folgenden Regeln bestimmt: 1. Wenn der String mit einem numerischen Wert beginnt, hat der String diesen numerischen Wert; andernfalls beträgt der Wert des Strings null. 2. Wenn ein Dezimalpunkt oder Exponent (e oder E) mit dem numerischen Wert verbunden ist, hat der resultierende Wert den Typ double; andernfalls ist der Typ des resultierenden Wertes integer. Manuelle Typumwandlung Wenn Sie wollen, können Sie die Typumwandlung manuell steuern oder den Typ einer Variablen manuell ändern. Zu diesem Zweck müssen Sie eine bestimmte Operation, das so genannte Type-Casting oder kurz Casting, ausführen. Das folgende Beispiel zeigt ein Casting eines Datentyps: $x = $y = $z = echo 1; 2.5; $x + (integer) $y; $z; Das Type-Casting, (integer), hat zur Folge, dass $y als Ganzzahl mit dem Wert 2 (anstatt 2.5) behandelt wird, sodass $z der Wert 3 zugewiesen wird. Die folgende Tabelle zeigt anderen Type-Casts, die Sie verwenden können: Cast Ergebnis: Casting in… (int) (integer) integer (real) (double) (float) double (string) string (array) array (object) object Daneben gibt es mehrere Funktionen, die noch eine andere Möglichkeit zur Verfügung stellen, eine Variable als Variable eines angegebenen Typs zu behandeln. Das folgende Beispiel zeigt eine dieser Funktionen in Aktion: Kapitel 5: Mit skalaren Werten arbeiten $x = $y = echo echo 103 1.5; intval($x); $x; $y; Die Funktion intval() wandelt den Wert von $x (1.5) in den Wert 1 um, sodass $y der Wert 1 zugewiesen wird. Die folgende Tabelle gibt einen Überblick über diese Umwandlungsfunktionen: Funktion Operation: Behandelt Argument als Typ… doubleval() double intval() integer strval() string Der Typ eines Operanden wird weder durch die implizite Typumwandlung noch durch ein Type-Casting geändert. Beide Mechanismen haben zur Folge, dass Operanden so behandelt werden, als hätten sie einen anderen Typ. Mit der settype()-Funktion ist es jedoch auch möglich, den Typ einer Variablen zu ändern. Das folgende Beispiel zeigt diese Funktion in Aktion: $x = 1.5; settype($x, "integer"); echo $x; Der ausgegebene Wert von $x ist eins, weil der Dezimalanteil verloren geht, wenn ein double-Wert mit settype() in einen integer-Wert umgewandelt wird. Sie hätten dasselbe Ergebnis auch mit der folgenden Zuweisung erzielen können, die ein Type-Casting verwendet: $x = (integer) $x; Die möglichen Werte für das zweite Argument von settype(), dem Argument, das den gewünschten Typ festlegt, lauten: ● "integer" ● "double" ● "string" ● "array" ● "object" 5 104 PHP 4 IT-Tutorial Eine verwandte Funktion, gettype(), gibt einen String zurück, der den Typ der angegebenen Variablen anzeigt. Das folgende Skript gibt den String "integer" zurück, der den Typ der Variablen $x anzeigt: $x = 1; echo gettype($x); Frage an den Experten Frage: Als ich PHP-Programme anderer Programmierer gelesen habe, ist mir der Operator += aufgefallen. Was bewirkt dieser Operator? Antwort: Der +=-Operator ist einfach eine Kurzform für eine Zuweisung, die einen +-Operator enthält. Die folgenden beiden Zuweisungen, eine in Kurzfom und eine in normaler Form, haben dasselbe Ergebnis: $x += 1; $x = $x + 1; Bei einer abgekürzten Zuweisung muss eine Variable, in diesem Beispiel $x, nur auf einer Seite der Zuweisung geschrieben werden. Die folgende Tabelle fasst die Kurzformen der arithmetischen und StringZuweisungsoperatoren in PHP zusammen. Sie zeigt ein Beispiel für den Gebrauch jedes Operators sowie die entsprechende Zuweisung: Kurzform der Zuweisung Gewöhnliche Zuweisung x += y x = x + y x -= y x = x - y x /= y x = x / y x *= y x = x * y x %= y x = x % y x .= y x = x . y Kapitel 5: Mit skalaren Werten arbeiten 105 1-Minuten-Test ● Welchen Typ hat das Ergebnis, wenn ein double-Wert und ein integerWert multipliziert werden? ● Schreiben Sie einen Ausdruck, der ein Type-Casting des Wertes der Variablen $x in den Typ double auführt. ● Welchen Wert und Typ hat der Ausdruck 1.5 + "me"? Projekt 5–1: Ein einfacher Rechner p-5–1.php In diesem Projekt werden Sie ein kleines PHP-Programm schreiben und ausführen, das als einfacher Rechner dient. Der Rechner addiert zwei Zahlen, die von dem Benutzer eingegeben werden, und zeigt die Summe an. Projektziele ● Demonstrieren, wie Zahlen, die als Text eingegeben werden, in arithmetischen Ausdrücken verwendet werden können ● Demonstrieren, wie PHP-Befehle in einem Formular Daten verarbeiten können, die in das Formular eingegeben wurden Schritt für Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen p-5–1.php, und laden Sie diese Datei auf Ihren PHP-Server herauf: <html> <head> <title>Projekt 5–1</title> </head> <body> <!-- Datei p-5–1.php --> <form method="POST" action="p-5–1.php"> <table> <tr> <td><input type="TEXT" name="op1" value="<? echo $op1 ?>"></td> </tr> ● double ● (double) $x ● 1.5, double 5 106 PHP 4 IT-Tutorial <tr> <td align="CENTER">+</td> </tr> <tr> <td><input type="TEXT" name="op2" value="<? echo $op2 ?>"></td> </tr> <tr> <td align="CENTER"><input type="SUBMIT" value="="></td> </tr> <tr> <td><input type="TEXT" name="ergebnis" value="<? echo $op1 + $op2 ?>" disabled></td> </tr> </table> </form> </body> </html> 2. Nehmen Sie sich Zeit, um das PHP-Skript zu studieren. Achten Sie dabei insbesondere auf die Art und Weise, wie die Werte der HTML-Attribute mit PHP-echo-Befehlen generiert werden. 3. Geben Sie den URL der Datei, die Sie zuvor heraufgeladen haben, in das Adressfeld Ihres Webbrowsers ein. Die Anzeige des Browsers sollte der Abbildung 5.1. ähneln. 4. Geben Sie für die beiden Operanden Werte ein. (Möglicherweise müssen Sie zunächst den Inhalt der Eingabefelder löschen.) Klicken Sie dann auf die SUBMIT-Schaltfläche, die ein Gleichheitszeichen zeigt. Wenn das Verarbeitungsskript ausgeführt wird, greift es auf die Werte der beiden Formularvariablen zu, die die Operanden repräsentieren, berechnet dann deren Summe und weist die Summe als Wert dem value-Attribut des Textfeldes ergebnis zu. Abbildung 5.2 zeigt das Ergebnis. Kapitel 5: Mit skalaren Werten arbeiten 107 5 Abbildung 5.1 Das Formular nach dem Aufruf des Skripts. Abbildung 5.2 Das Formular nach dem Absenden der Daten – in den Feldern werden jetzt die eingegebenen Zahlen und deren Summe angezeigt. Projekt 5–2: Ein Datumsrechner p-5–2.php In diesem Projekt werden Sie ein PHP-Programm schreiben und ausführen, das Berechnungen mit Datumsangaben ausführt. Bei diesem Programm kann der Benutzer ein Datum und ein Offset (in Tagen) eingeben. Das Programm berechnet dann das resultierende Datum und zeigt das Ergebnis an. 108 PHP 4 IT-Tutorial Projektziel ● Demonstrieren, wie Datumsangaben als Text eingegeben, in numerische Form umgewandelt und in arithmetischen Ausdrücken verwendet werden können Schritt für Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen p-5–2.php, und laden Sie diese Datei auf Ihren PHP-Server herauf. <html> <head> <title>Projekt 5–2</title> </head> <body> <!-- Datei p-5–2.php --> <form method="POST" action="p-5–2.php"> <table> <tr> Datum:<br> <td><input type="TEXT" name="datum" value="<?php echo $datum ?>"></td> </tr> <tr> <td align="CENTER">+</td> </tr> <tr> <td><input type="TEXT" name="offset" value="<?php echo $offset ?>"></td> </tr> <tr> <td align="CENTER"><input type="SUBMIT" value="="></td> </tr> <tr> <td><input type="TEXT" name="ergebnis" value=" <?php echo date ("Y-m-d", (strtotime($datum)+60*60*24*($offset))) ?>" disabled></td> </tr> Kapitel 5: Mit skalaren Werten arbeiten 109 </table> </form> </body> </html> 2. Nehmen Sie sich Zeit, um das PHP-Skript zu studieren. Achten Sie dabei insbesondere auf die Art und Weise, wie der Wert des value-Attributs des Textfeldes ergebnis berechnet wird. Der Teilausdruck 60*60*24 repräsentiert die Anzahl der Sekunden eines Tages. Die Funktion strtotime() übernimmt ein Datum als Argument und gibt die Anzahl der Sekunden zurück, die seit dem 1. Januar 1970 um 00:00:00 Uhr GMT vergangen sind, dem Zeitpunkt, der als die UNIX-Epoche bezeichnet wird. Wenn das Datum und die Zeit als Anzahl der Sekunden repräsentiert werden, die seit der UNIX-Epoche vergangen sind, wird dies als UNIX-Zeit bezeichnet. Die Funktion date() hat zwei Argumente. Sie formatiert das Datum, das in dem zweiten Argument enthalten ist, nach Maßgabe des Strings, der als erstes Argument übergeben wird. Der String "Y-m-d" hat zur Folge, dass die Funktion eine vierstellige Jahreszahl, einen Bindestrich, eine zweistellige Monatszahl, einen weiteren Bindestrich und dann eine zweistellige Tageszahl zurückgibt. 3. Geben Sie den URL des Skripts, das Sie zuvor heraufgeladen haben, in das Adressfeld Ihres Webbrowsers ein. Nach dem Aufruf des Skripts – in den Feldern werden (noch) Fehlermeldungen angezeigt – geben Sie ein Datum und einen Offsetwert ein. Die Anzeige des Browsers sollte jetzt der Abbildung 5.3. ähneln. Abbildung 5.3 Das Formular nach der Eingabe eines Datums und eines Offsetwerts. 5 110 PHP 4 IT-Tutorial 4. Klicken Sie dann auf die SUBMIT-Schaltfläche, die ein Gleichheitszeichen zeigt. Wenn das Verarbeitungsskript ausgeführt wird, greift es auf die Werte der beiden Formularvariablen zu, die das Datum und den Offsetwert repräsentieren, berechnet dann deren Summe und weist die Summe als Wert dem value-Attribut des Textfeldes ergebnis zu. Abbildung 5.4 zeigt das Ergebnis. Abbildung 5.4 Das Formular nach dem Absenden der Daten – jetzt wird auch das Ergebnis angezeigt. Projekt 5–3: Ein Nachrichtengenerator p-5–3.php p-5–3.html In diesem Projekt werden Sie ein PHP-Programm schreiben, das eine lustige Nachricht generiert. Bei diesem Programm kann der Benutzer einige Textstrings eingeben. Das Programm setzt die Strings dann zu einer Geschichte zusammen. Projektziel ● Demonstrieren, wie mit Textstrings HTML-Text definiert werden kann Schritt für Schritt 1. Speichern Sie die folgende HTML-Seite unter dem Dateinamen p-5–3.html, und laden Sie diese Datei auf Ihren PHP-Server herauf: <html> <head> <title>Projekt 5–3</title> </head> Kapitel 5: Mit skalaren Werten arbeiten 111 <body> <!-- Datei p-5–3.html --> <form method="POST" action="p-5–3.php"> <table> <tr> <td align="RIGHT">Vorname des Benutzers:</td> <td><input type="TEXT" name="benutzer"></td> </tr> <tr> <td align="RIGHT">Große Stadt:</td> <td><input type="TEXT" name="stadt"></td> </tr> <tr> <td align="RIGHT">Lieblingseis:</td> <td><input type="TEXT" name="eis"></td> </tr> <tr> <td align="RIGHT">Berühmter Popstar:</td> <td><input type="TEXT" name="star"></td> </tr> <tr> <td align="RIGHT">Großer Strom:</td> <td><input type="TEXT" name="strom"></td> </tr> <tr> <td></td> <td><input type="SUBMIT"></td> </tr> </table> </form> </body> </html> 5 112 PHP 4 IT-Tutorial 2. Speichern Sie das folgende PHP-Skript unter dem Dateinamen p-5–3.php, und laden Sie diese Datei auf Ihren PHP-Server in dasselbe Verzeichnis wie die Datei p-5–3.html herauf: <html> <head> <title>Projekt 5–3</title> </head> <body> <!-- Datei p-5–3.php --> <center><h1>Prominentenklatsch</h1></center> <center><?php echo date("Y-m-d") ?></center> <center><h2>EILNACHRICHT!!!</h2></center> <hr> <?php echo $stadt ?>: <p> Gestern Abend wurde der Popstar <?php echo $star ?> mit einer unbekannten Begleiterin gesehen. Die beiden teilten sich ein <?php echo $eis ?> im <?php echo $strom ?>Club, einem beliebten Treffpunkt der Reichen und Berühmten in <?php echo $stadt ?>. Vertrauliche Quellen teilen uns mit, dass die geheimnisvolle Begleiterin <?php echo $benutzer ?> ist, die früher häufig zusammen mit dem letztjährigen Bambi-Gewinner gesehen wurde.... </body> </html> 3. Studieren Sie das HTML-Formular und insbesondere die Formularvariablen, die in ihm definiert werden. Schauen Sie sich dann in dem PHPSkript die Stellen an, an denen die Werte der Formularvariablen verwendet werden, um HTML-Text zu generieren. 4. Geben Sie den URL der HTML-Datei in das Adressfeld Ihres Webbrowsers ein. Geben Sie in jedem Feld einen Wert ein. Die Anzeige des Browsers sollte Abbildung 5.5 ähneln (natürlich werden Ihre Werte anders lauten als die in der Abbildung). Klicken Sie auf die SUBMIT-Schaltfläche (ANFRAGE SENDEN). Kapitel 5: Mit skalaren Werten arbeiten 113 5 Abbildung 5.5 Das HTML-Formular zur Eingabe der Werte 5. Wenn das Verarbeitungsskript ausgeführt wird, greift es auf die Werte der Formularvariablen zu und fügt diese in den HTML-Text ein, der an den Browser gesendet wird. Abbildung 5.6 zeigt ein typisches Ergebnis. Abbildung 5.6 Das Ergebnis des PHP-Skripts – die generierte Nachricht 114 PHP 4 IT-Tutorial 9Übungsaufgaben 1. Schreiben Sie einen Befehl, der eine Konstante namens speed definiert, die den Wert 186.282 hat. 2. Schreiben Sie einen Befehl, der einen Wert ausgibt, der anzeigt, ob eine Konstane namens LAENGE definiert ist. 3. Wenn $cat den Wert "Spot" und $pet den Wert "cat" hat, wie lautet dann der Name einer dynamischen Variablen, die den Wert "Spot" hat? 4. Welchen Typ hat das Ergebnis, wenn zwei integer-Werte dividiert werden? 5. Welchen Typ hat das Ergebnis, wenn ein integer-Wert mit einem doubleWert multipliziert wird? 6. Schreiben Sie einen Befehl, der den Typ der Variablen $cost in integer ändert. Teil II Fortgeschrittenere PHP-Programme schreiben Kapitel 6 Kontrollbefehle schreiben Lernziele ● Wie Wahrheitswerte (true/false) definiert und verwendet werden ● Wie if-Befehle und verwandte Anweisungen geschrieben und verwendet werden ● Wie switch-Befehle und verwandte Anweisungen geschrieben und verwendet werden ● Wie Schleifenbefehle – einschließlich while-, do while- und for-Befehle – geschrieben und verwendet werden 118 PHP 4 IT-Tutorial Die meisten nützlichen Programme verhalten sich nicht bei jeder Ausführung genau gleich, sondern treffen bei ihrem Ablauf Entscheidungen, die – abhängig von den Umständen – zu unterschiedlichen Aktionen führen. Beispielsweise verwendet ein Programm zur Berechnung der Einkommenssteuer nicht für jeden Steuerzahler denselben Steuersatz. In diesem Kapitel lernen Sie, wie Sie den Ablauf von Programmen mit so genannten Steuer- oder Kontrollbefehlen steuern können. Mit Wahrheitswerten arbeiten PHP-Programme treffen Entscheidungen, indem sie Bedingungsausdrücke auswerten und je nach Ergebnis unterschiedliche Aktionen ausführen. Bedingungsausdrücke sind Ausdrücke, die einen von zwei Werten annehmen können: true oder false (dt. wahr oder falsch). Im Gedenken an George Boole, den Mathematiker, der diese Ausdrücke untersucht hat, werden werden Bedingungsausdrücke manchmal auch als boolesche Ausdrücke bezeichnet. Die Konstante true hat den Wert 1, und die Konstante false hat den Wert 0. Mit der Konstante true oder der Konstante false kann man einen Bedingungsausdruck bilden. Es ist jedoch nützlicher, zu diesem Zweck einen so genannten relationalen Operator zu verwenden, um zwei numerische Werte zu vergleichen. Betrachten Sie das folgende Beispiel: $a < 1 Dieser Bedingungsausdruck verwendet den Operator <, der im Wesentlichen dieselbe Bedeutung wie in der Algebra hat. Der Ausdruck hat dann und nur dann den Wert true, wenn der Wert von $a kleiner als eins ist; in all anderen Fällen hat er den Wert false. PHP stellt mehrere relationale Operatoren zur Verfügung, die in Tabelle 6.1 zusammengefasst werden. Operator Beschreibung a<b true, wenn der Wert von a kleiner als der Wert von b ist a>b true, wenn der Wert von a größer als der Wert von b ist a<=b true, wenn der Wert von a kleiner als oder gleich dem Wert von b ist a>=b true, wenn der Wert von a größer als oder gleich dem Wert von b ist a==b true, wenn der Wert von a gleich dem Wert von b ist a!=b true, wenn der Wert von a nicht gleich dem Wert von b ist Tabelle 6.1 Die relationalen Operatoren von PHP Kapitel 6: Kontrollbefehle schreiben Operator Beschreibung a===b true, wenn a und b identisch sind, d.h. wenn a denselben Typ wie b hat und der Wert von a gleich dem Wert von b ist a!==b true, wenn a und b nicht identisch sind, d.h. wenn a einen anderen Typ als b hat und/oder der Wert von a nicht gleich dem Wert von b ist 119 Tabelle 6.1 Die relationalen Operatoren von PHP In PHP können Sie nicht nur numerische Werte, sondern auch Strings mit relationalen Operatoren vergleichen; jedoch werden Strings, die in einem Bedingungsausdruck verwendet werden, vor der Auswertung des Ausdrucks in einen numerischen Wert umgewandelt. Dies führt häufig zu unerwarteten Ergebnissen. Im Allgemeinen sollten Stringwerte mit Hilfe einer der Stringvergleichsfunktionen verglichen werden. Diese Funktionen werden in Kapitel 7 erklärt. Zur Abkürzung können Sie auch Bedingungsausdrücke ohne einen relationalen Operator bilden. Nehmen wir beispielsweise an, dass $a eine numerische Variable ist. Dann können Sie den Ausdruck $a als Bedingungsausdruck verwenden. PHP interpretiert diesen Ausdruck als booleschen Ausdruck mit dem Wert false, wenn $a den Wert null hat; anderenfalls hat dieser Ausdruck den Wert true. Wenn Sie einen String als Bedingungsausdruck verwenden, hat der Ausdruck den Wert false, wenn der String leer ist oder den speziellen Wert "\0" enthält, der für ein Byte steht, das den Wert null hat. Auf ähnliche Weise ergibt ein nicht definierter Wert, der in einem Bedingungsausdruck verwendet wird, den Wert false. Wenn Sie ein Array oder ein Objekt als Bedingungsausdruck verwenden, hat der Ausdruck den Wert false, wenn das Array oder das Objekt leer ist; andernfalls hat er den Wert true. Die folgende Liste fasst die Regeln zusammen, nach denen das Ergebnis eines Bedingungsausdruck ermittelt wird: ● Die Konstanten true und false haben ihren entsprechenden booleschen Wert. ● Ein Bedingungsausdruck, der aus einem nicht definierten Wert besteht, ist false; andernfalls hängt das Ergebnis vom Typ (numerisch, String, Array oder Objekt) des Wertes ab. ● Ein Bedingungsausdruck, der aus einem numerischen Wert besteht, ist false, wenn der Wert null ist; andernfalls ist er true. ● Ein Bedingungsausdruck, der aus einem Stringwert besteht, ist false, wenn der String leer ist; andernfalls ist er true. ● Ein Bedingungsausdruck, der aus einem Array- oder einem Objektwert besteht, ist false, wenn das Array oder das Objekt leer ist; andernfalls ist er true. 6 120 PHP 4 IT-Tutorial ● Ein Bedingungsausdruck, der aus einem relationalen Operator und seinen Operanden besteht, hat den Wert, den der (numerische) Vergleich ergibt. Zwei einfache Bedingungsausdrücke können mit einem so genannten logischen Operator zu einem komplexeren Bedingungsausdruck zusammengefügt werden. Beispielsweise ist der folgende Ausdruck true, wenn seine beiden Teilbedingungsausdrücke true sind: $a < 1 AND $b < 1 Dies bedeutet, dass der Ausdruck true ist, wenn sowohl $a als auch $b kleiner als eins sind. Tabelle 6.2 fasst die logischen Operatoren von PHP zusammen. Wenn Sie vor den Bedingungsausdruck einen !-Operator setzen, wird der Wahrheitswert des Operanden umgekehrt (aus true wird false und umgekehrt). Operator Beschreibung x AND y true, wenn sowohl x als auch y den Wert true hat. x && y true, wenn sowohl x als auch y den Wert true hat. x OR y true, wenn x oder y oder beide true sind. x || y true, wenn x oder y oder beide true sind. x XOR y true, wenn genau einer der beiden Werte von x und y true ist. !x true, wenn x false ist. Tabelle 6.2 Die logischen Operatoren von PHP Frage an den Experten Frage: Warum enthält PHP zwei logische Operatoren, um die logische Konjunktion (AND und &&) bzw. die logische Disjunktion (OR und ||) zu repräsentieren? Wie unterscheiden sich diese Operatoren? Antwort: Sowohl die Operatoren für die Konjunktion als auch die Operatoren für die Disjunktion führen jeweils dieselbe Operation aus. Jedoch unterscheiden sich die Operatoren in ihrer Präzedenz – der Eigenschaft, die die Reihenfolge festlegt, in der Operationen beim Auswerten eines Ausdrucks ausgeführt werden. Die Operatoren && und || haben eine relativ hohe Präzedenz, während die Operatoren AND und OR über eine relativ niedrige Präzedenz verfügen. Tabelle 6.3 zeigt die Präzedenz der PHP-Operatoren einschließlich mehrerer Operatoren, die noch nicht eingeführt wurden. Kapitel 6: Kontrollbefehle schreiben 121 Operator ! ~ ++ -- (int) (double) (string) (array) (object) * / % + - . < <= > >= == != === !== & ^ | && || ?: = += -= *= /= .= %= &= |= ^= ~= <<= >>= AND XOR OR , Tabelle 6.3 Die Präzedenz der PHP-Operatoren Ausdrücke werden im Allgemeinen von links nach rechts ausgewertet. Jedoch haben die Operatoren, die am Anfang der Tabelle stehen, eine höhere Präzedenz und werden deshalb vor den Operatoren mit einer niedrigeren Präzedenz ausgeführt. Mit Klammern kann jedoch die Reihenfolge der Ausführung geändert werden. Betrachten Sie beispielsweise den folgenden Ausdruck: $a + $b * $c Die Präzedenz des Multiplikationsoperators * ist höher als die des Additionsoperators +, sodass die Multiplikation zuerst ausgeführt wird, obwohl die Addition links von der Multiplikation steht, d.h. der Ausdruck wird folgendermaßen ausgewertet: $a + ($b * $c) Wenn die Addition zuerst ausgeführt werden soll, können Sie den Ausdruck mit Klammern folgendermaßen ändern: ($a + $b) * $c 6 122 PHP 4 IT-Tutorial 1-Minuten-Test Nehmen Sie an, dass $a den Wert 10, $b den Wert 1 und $c den Wert 1 hat: ● Welchen Wert hat $a < $b? ● Welchen Wert hat $a <= $b? ● Welchen Wert hat $a > $b? ● Welchen Wert hat $b >= $c? ● Welchen Wert hat $a > $b AND $b >= $c? Einfache if-Befehle schreiben Für sich betrachtet sind Bedingungsausdrücke nicht besonders interessant oder nützlich, aber sie spielen eine wesentliche Rolle beim Schreiben von Kontrollbefehlen, die Entscheidungen treffen. Der einfachste Kontrollbefehl ist der ifBefehl, der zwei Operationen ausführt. Zunächst wertet er einen Bedingungsausdruck aus. Dann und nur dann, wenn der Bedingungsausdruck den Wert true hat, führt der if-Befehl einen bestimmten Befehl aus. Das folgende Beispiel zeigt einen einfachen if-Befehl: if ($zahl > 10) echo "Dies ist eine große Zahl."; Sie erinnern sich, dass PHP im Allgemeinen Whitespace-Zeichen ignoriert. Üblicherweise wird ein Befehl, der mit einem if-Befehl verbunden ist, eingerückt. Es ist empfehlenswert, diese Konvention zu übernehmen, weil ein Programm dadurch besser lesbar wird. Wenn der if-Befehl ausgeführt wird, wertet er zunächst den Bedingungsausdruck $zahl > 10 aus, der nur dann true ist, wenn der Wert von $zahl größer als 10 ist. Das bedeutet, dass der echo-Befehl nur ausgeführt wird, wenn der Wert von $zahl größer als 10 ist. Um Erfahrungen mit dem if-Befehl zu sammeln, sollten Sie Projekt 6–1 bearbeiten. ● ● ● ● ● false false true true true Kapitel 6: Kontrollbefehle schreiben 123 Projekt 6–1: Numerische Werte testen In diesem Projekt werden Sie ein kleines PHP-Programm schreiben und ausführen, das einen if-Befehl enthält. Das Programm teilt Ihnen mit, ob die Zahl, die Sie eingeben, größer als zehn ist. p-6–1.php p-6–1.html Projektziel ● Demonstrieren, wie der if-Befehl funktioniert Schritt für Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen p-6–1.php, und laden Sie diese Datei auf Ihren PHP-Server herauf: <html> <head> <title>Projekt 6–1</title> </head> <body> <!-- Datei p-6–1.php --> <?php echo "Die eingegebene Zahl lautete: $zahl."; if ($zahl > 10) echo "<br>Dies ist eine große Zahl."; ?> </body> </html> 2. Speichern Sie die folgende HTML-Seite unter dem Dateinamen p-6–1.html, und laden Sie diese Datei auf Ihren Server in dasselbe Verzeichnis wie die Datei p-6–1.php herauf: <html> <head> <title>Projekt 6–1</title> </head> <body> <!-- Datei p-6–1.html --> <form method="POST" action="p-6–1.php"> Geben Sie einen numerischen Wert ein: <br><input type="TEXT" name="zahl"> </form> </body> </html> 6 124 PHP 4 IT-Tutorial 3. Geben Sie den URL der HTML-Datei, die Sie zuvor heraufgeladen haben, in das Adressfeld Ihres Webbrowsers ein. Die Anzeige des Browsers sollte Abbildung 6.1 ähneln. Geben Sie eine Zahl ein, und drücken Sie auf (¢). Abbildung 6.1 Das HTML-Formular nach dem Aufruf des Skripts 4. Wenn das Verarbeitungsskript ausgeführt wird, vergleicht es den Wert, den Sie eingegeben haben, mit 10. Wenn Sie einen Wert eingegeben haben, der größer als 10 ist, gibt das Skript eine Nachricht aus. Abbildung 6.2 zeigt ein typisches Ergebnis. Abbildung 6.2 Das Vergleichsergebnis 1-Minuten-Test ● Schreiben Sie einen if-Befehl, der die Nachricht "Hoppla!" ausgibt, wenn der Wert von $errors größer als null ist. ● Schreiben Sie einen if-Befehl, der die Nachricht "warten" ausgibt, wenn der Wert von $farbe gleich dem Wert von $rot oder dem Wert von $gelb ist. ● if ($errors > 0) echo "Hoppla!"; ● if ($farbe == $rot OR $farbe == $gelb) echo "warten"; Kapitel 6: Kontrollbefehle schreiben 125 Komplexere if-Befehle schreiben Nehmen wir an, dass Sie nicht einen, sondern zwei Befehle ausführen wollen, wenn ein Bedingungsausdruck true ist. Sie könnten zwei if-Befehle schreiben, einen für jeden Befehl, den Sie ausführen wollen. Alternativ können Sie eine Befehlsgruppe erstellen, indem Sie eine Reihe von Befehlen in geschweifte Klammern einschließen. Eine Befehlsgruppe verhält sich wie ein einzelner Befehl und kann mit einem if-Befehl verbunden werden. Betrachten Sie beispielsweise den folgenden Codeausschnitt: if ($zahl > 10) { echo "<br>Die Zahl ist größer als 10."; echo "<br>Deshalb muss sie groß sein."; } Wenn der Bedingungsausdruck den Wert true hat, werden beide Befehle in der Befehlsgruppe ausgeführt. Einige Programmierer ziehen eine andere Formatierung des Codes – wie beispielsweise die folgende – vor: if ($zahl > 10) { echo "<br>Die Zahl ist größer als 10."; echo "<br>Deshalb muss sie groß sein."; } Dieser Stil ist kompakter, aber er verringert die Lesbarkeit des Codes, weil es schwieriger ist, zusammengehörige öffnende und schließende geschweifte Klammern zu identifizieren. Solche Fragen der Lesbarkeit werden umso wichtiger, je komplexer die if-Befehle werden. Nehmen wir dann, dass Sie einen Befehl ausführen wollen, wenn eine Bedingung true ist, und einen anderen Befehl, wenn die Bedingung false ist. Zu diesem Zweck können Sie den else-Befehl verwenden. Betrachten Sie das folgende Beispiel: if ($zahl > 10) echo "<br>Dies ist eine große Zahl."; else echo "<br>Dies ist eine kleine Zahl."; In diesem Beispiel wird die Nachricht "Dies ist eine große Zahl." ausgegeben, wenn der Wert von $zahl größer als 10 ist, andernfalls wird die Nachricht "Dies ist eine kleine Zahl." ausgegeben. Wenn Sie wollen, können Sie einen else-Befehl mit einer Befehlsgruppe verbinden. Ein Beispiel: 6 126 PHP 4 IT-Tutorial if ($zahl > 10) echo "<br>Dies ist eine große Zahl."; else { echo "<br>Die Zahl ist kleiner als 10."; echo "<br>Dies ist eine kleine Zahl."; } Der Befehl, der mit einem if- oder else-Befehl verbunden ist, kann selbst ein if-Befehl sein. Ein solcher if-Befehl wird als verschachtelter if-Befehl bezeichnet. Ein Beispiel: if ($zahl > 10) if ($zahl > 100) echo "<br>Dies ist eine sehr große Zahl."; else echo "<br>Dies ist eine große Zahl."; else echo "<br>Dies ist eine kleine Zahl."; Das Beispiel gibt die Nachricht "Dies ist eine sehr große Zahl." aus, wenn der Wert von $zahl größer als 100 ist; andernfalls gibt es, wenn der Wert von $zahl größer als 10 ist, die Nachricht "Dies ist eine große Zahl." aus. Wenn der Wert von $zahl nicht größer als 10 ist, gibt das Beispiel die Nachricht "Dies ist eine kleine Zahl." aus. Es kann ziemlich schwierig werden, verschachtelte if-Befehle zu verstehen, wenn die Anzahl der Befehle und der Verschachtelungsebenen zunimmt. Deshalb sollten Sie dieses Konstrukt sparsam einsetzen. Der if- und der else-Befehle können mit dem elseif-Befehl verbunden werden. Wenn dieser Befehl korrekt eingesetzt wird, ist der Code leichter zu verstehen als ein logisch gleichwertiger Code, der mit einem verschachtelten ifBefehl arbeitet. Ein Beispiel für einen elseif-Befehl: if ($zahl > 100) echo "<br>Dies ist elseif ($zahl > 10) echo "<br>Dies ist elseif ($zahl > 1) echo "<br>Dies ist else echo "<br>Dies ist eine sehr große Zahl."; eine große Zahl."; eine kleine Zahl."; eine sehr kleine Zahl." Dieses Beispiel erweitert die Fähigkeit des vorangegangenen Beispiels: Es gibt die Nachricht "Dies ist eine sehr kleine Zahl." aus, wenn der Wert von Kapitel 6: Kontrollbefehle schreiben 127 $zahl kleiner als oder gleich 1 ist. Im Allgemeinen können viel mehr elseifBefehle mit einem if-Befehl oder einem else-Befehl verbunden werden. PHP wertet Bedingungsausdrücke nacheinander aus, wobei der Bedingungsausdruck, der mit dem if-Befehl verbunden ist, zuerst ausgewertet wird. PHP führt den Befehl des ersten Bedingungsausdrucks aus, der den Wert true hat. Wenn kein Bedingungsausdruck den Wert true ergibt, führt PHP den Befehl aus, der mit dem else-Befehl verbunden ist. Der else-Befehl darf auch weggelassen werden. In diesem Fall wird kein Befehl ausgeführt, wenn keiner der Bedingungsausdrücke den Wert true hat. 1-Minuten-Test ● Schreiben Sie einen if-Befehl und einen else-Befehl, um die Nachricht "warten" auszugeben, wenn der Wert von $farbe gleich dem Wert von $rot oder gleich dem Wert von $gelb ist; geben Sie andernfalls die Nachricht "gehen" aus. ● Schreiben Sie einen if-Befehl und einen else-Befehl aus, um $zahl mit 10 zu multiplizieren, wenn der der Wert von $faktor 1 ist; multiplizieren Sie andernfalls $zahl mit 100. switch-, break- und defaultBefehle schreiben Mit dem if-Befehl können Sie eine Entscheidung mit zwei Alternativen programmieren. Um eine Entscheidung mit mehr als zwei Alternativen zu programmieren, können Sie mehrere if-, else- oder elseif-Befehle verwenden. Wenn Sie jedoch einen Satz von Alternativen programmieren wollen, die durch ganzzahlige Werte repräsentiert werden können, ist wahrscheinlich der switchBefehl übersichtlicher. Nehmen wir beispielsweise an, dass $zahl die Werte 1, 2 oder 3 annehmen kann, mit denen drei Größen – klein, mittel bzw. groß – repräsen- ● if ($farbe == $rot OR $farbe == $gelb) echo "warten"; else echo "gehen"; ● if ($faktor == 1) $zahl = 10 * $zahl; else $zahl = 100 * $zahl; 6 128 PHP 4 IT-Tutorial tiert werden. Das folgende Beispiel zeigt ein kleines Programm, das die Größe ausgibt, die mit dem jeweiligen Wert von $zahl verbunden ist: switch ($zahl) { case 1: echo "klein"; break; case 2: echo "mittel"; break; case 3: echo "groß"; break; default: echo "Dieser Code ist ungültig."; } Die Aktion eines switch-Befehls wird durch den Wert eines ganzzahligen Ausdrucks bestimmt, nicht vom Wert eines Bedingungsausdrucks. Der Name der Variablen wird in Klammern nach dem Schlüsselwort switch angegeben. Geschweifte Klammern schließen eine Reihe von case-Befehlen sowie einen optionalen default-Befehl ein, die jeweils mit Befehlen verbunden sein können. Wenn der switch-Befehl ausgeführt wird, versucht er, den Wert der Variablen in seinem Argument mit dem Wert eines seiner case-Befehle abzugleichen. Die Befehle des ersten übereinstimmenden case-Befehls werden ausgeführt. Wenn der Wert der switch-Variablen nicht mit dem Wert eines der case-Befehle übereinstimmt, werden die Befehle ausgeführt, die mit dem default-Befehl verbunden sind – falls der switch-Befehl einen default-Befehl enthält. Es gehört zu einer guten Programmierstil, dass jeder case-Befehl in einem switch-Befehl mit einem break-Befehl beendet wird. Der break-Befehl beendet die Ausführung des switch-Befehls. Das Programm wird dann mit dem nächsten sequenziellen Befehl fortgesetzt, der auf den switch-Befehl folgt. Ohne break-Befehl führt das Programm den nächsten sequenziellen case- oder default-Befehl aus, was selten das gewünschte Verhalten ist. Kapitel 6: Kontrollbefehle schreiben 129 Tipp Sie müssen in der case-Anweisung eines switch-Befehls keine aufeinander folgenden Ganzzahlen verwenden. Wenn Sie wollen, können Sie nicht aufeinander folgende Ganzzahlen, Fließkommazahlen oder Strings verwenden. Frage an den Experten Frage: PHP enthält mehrere Kontrollbefehle, einschließlich if, else, elseif und switch. Gibt es noch andere Möglichkeiten, um Entscheidungen zu treffen? Antwort: Ja. Der Bedingungsoperator ?:, der manchmal auch als ternärer Operator oder Fragezeichen-Doppelpunkt-Operator bezeichnet wird, bietet eine weitere Möglichkeit, PHP-Entscheidungen zu schreiben. Der Bedingungsoperator bildet einen Ausdruck, der in vielen PHP-Kontexten verwendet werden kann. Er hat die folgende allgemeine Form: Bedingungsausdruck ? true-Wert : false-Wert Achten Sie darauf, wie das ? und der : den true-Wert einschließen. Der Bedingungsoperator wertet seinen Bedingungsausdruck aus. Wenn der Ausdruck den Wert true hat, gibt der Bedingungsoperator den trueWert, andernfalls den false-Wert zurück. Mit dem Bedingungsoperator können Sie Entscheidungen sehr knapp formulieren. Betrachten Sie beispielsweise die folgende Zuweisung, die einen Bedingungsoperator verwendet: $a = ($b > $c) ? 1 : 2; Diese Zuweisung vergleicht die Werte von $b und $c. Wenn der Wert von $b größer als der Wert von $c ist, wird $a der Wert 1, andernfalls der Wert 2 zugewiesen. 6 130 PHP 4 IT-Tutorial 1-Minuten-Test ● Schreiben Sie einen switch-Befehl, der den Wert von $exponent testet. Der Befehl sollte $faktor den Wert 10 zuweisen, wenn $exponent den Wert 1 hat; er sollte $faktor den Wert 100 zuweisen, wenn $exponent den Wert 2 hat; und andernfalls sollte er $faktor den Wert 0 zuweisen. ● Mit welchem Befehl sollte jeder case-Befehl beendet werden, wenn man auf einen guten Programmierstil achtet? for-Befehle schreiben Der for-Befehl ist ein Schleifenbefehl oder iterativer Befehl. Dabei handelt es sich um einen Befehl, der die mit ihm verbundenen Befehle wiederholt ausführt. Das folgende Beispiel zeigt einen for-Befehl: $summe = 0; for ($n=1; $n<=3; $n++) $summe += $n; echo "<br>Die Summe der Ganzzahlen 1 bis 3 ist $summe."; Das Beispiel berechnet die Summe der Ganzzahlen von 1 bis 3. Zu diesem Zweck wird zunächst die Variable $summe mit dem Wert 0 initialisiert. Dann wird ein for-Befehl ausgeführt, der den Wert von $summe wiederholt erhöht. Um zu sehen, wie dies funktioniert, wollen wir die Teile des for-Befehls im Detail analysieren. Der for-Befehl enthält drei Ausdrücke, die in Klammern eingeschlossen sind. Jeder Ausdruck ist von seinem Nachbarn durch ein Semikolon getrennt. Der for-Befehl enthält auch einen Befehl oder eine Befehlsgruppe, der bzw. die als der Body (dt. Körper) des for-Befehls bezeichnet wird. In unserem Beispiel bildet der Befehl $summe += $n den Body des for-Befehls. ● switch ($exponent) { case 1: $faktor = 10; break; case 2: $faktor = 100; break; default: $faktor = 0; } ● mit einem break-Befehl Kapitel 6: Kontrollbefehle schreiben 131 Betrachten wir die drei Ausdrücke genauer: ● Der erste Ausdruck ist der Initialisierungsausdruck. Er wird ausgeführt, wenn PHP den for-Befehl erreicht. In unserem Beispiel weist der Initialisierungsausdruck der Variablen $n den Wert 1 zu. Diese Variable wird als Schleifenvariable oder Index bezeichnet. Sie muss nicht $n heißen, sondern kann einen beliebigen gültigen Variablennamen haben. ● Der zweite Ausdruck ist der Testausdruck. Es handelt sich um einen Bedingungsausdruck, der festlegt, ob die Befehle im Body des Befehls ausgeführt werden sollen. Im Allgemeinen referenziert dieser Ausdruck die Schleifenvariable. In unserem Beispiel vergleicht der Testausdruck den Wert von $n mit 3. Der Testausdruck wird unmittelbar nach der Auswertung des Initialisierungsausdrucks zum ersten Mal ausgewertet. ● Der dritte Ausdruck ist der Schrittausdruck. Im Allgemeinen ändert er eine oder mehrere Variablen, die in dem Testausdruck referenziert werden. In unserem Beispiel erhöht der Schrittausdruck den Wert von $n. Ein for-Befehl wird in den folgenden Schritten ausgeführt: 1. Werte den Initialisierungsausdruck aus. 2. Werte den Testausdruck aus. 3. Wenn die Auswertung des Testausdrucks false ergibt, gehe zu Schritt 7. 4. Führe den Body der Schleife aus. 5. Werte den Schrittausdruck aus. 6. Gehe zu Schritt 2. 7. Verlasse den for-Befehl und gehe zum nächsten sequenziellen Befehl. Der for-Befehl eignet sich dazu, Vorgänge zu zählen und Aktionen wiederholt auszuführen. Das folgende weitere Beispiel zeigt, wie mit einem for-Befehl mehrere Schaltflächen erstellt werden. Die Anzahl der Schaltflächen wird durch den Wert von $zahl bestimmt: for ($n=0; $n<=$zahl; $n++) echo "<br><input type=\"BUTTON\" value=\"$n\">\n"; In Kapitel 8 werden Sie sehen, dass der for-Befehl speziell beim Arbeiten mit Arrays nützlich ist. 6 132 PHP 4 IT-Tutorial 1-Minuten-Test ● Schreiben Sie einen for-Befehl, der die Summe der Ganzzahlen von 1 bis 100 berechnet. ● Schreiben Sie einen for-Befehl, der HTML-<br>-Tags ausgibt. Die Anzahl der ausgegebenen Tags soll dem Wertvon $n entsprechen. while- und do while-Befehle schreiben Sie können while- und do while-Befehle als Do-it-yourself-Versionen des forBefehls betrachten. Während ein for-Befehl über drei Ausdrücke verfügt, hat ein while- oder ein do while-Ausdruck nur einen: den Testausdruck. Die Ausdrücke eines for-Befehls sind optional. Ohne einen Initialisierungsausdruck und ohne einen Schrittausdruck funktioniert ein for-Befehl genauso wie ein whileBefehl. Vorausgesetzt, dass $summe den Anfangswert null hat, sind deshalb die folgenden Befehle gleichwertig: for ( ; $summe <= 3; ) $summe += 1; while ($summe <= 3) $summe += 1; Wenn Sie einen while-Befehl verwenden, müssen Sie einen Mechanismus zur Verfügung stellen, der analog zu dem Schrittausdruck des for-Befehls funktioniert, der die Variablen aktualisiert, die in dem Testausdruck referenziert werden. Außerdem sind Sie dafür verantwortlich, die Werte zu initialisieren, die in dem Testausdruck verwendet werden. Ein while-Befehl wird in den folgenden Schritten ausgeführt: 1. Werte den Testausdruck aus. 2. Wenn das Ergebnis false ist, gehe zu Schritt 5. 3. Führe die Befehle im Body der Schleife aus. 4. Gehe zu Schritt 1. 5. Verlasse die Schleife und gehe zum nächsten sequenziellen Befehl. ● $summe = 0; for ($i = 1; $i <= 100; $i++) $summe = $summe + $i; ● for ($i = 1; $i <= $n; $i++) echo "<br>"; Kapitel 6: Kontrollbefehle schreiben 133 Das folgende Beispiel zeigt einen while-Befehl in Aktion: $n = 0; $summe = 0; while ($n <= 3) { $summe = $summe + $n; $n++; } echo "Die Summe beträgt $summe." Der Befehl $n = 0; initialisiert die Schleife; der Befehl n++; zählt den Wert der Schleifenvariablen $n weiter. Der while-Befehl ist am nützlichsten, wenn diese Funktionen bereits von anderen Codezeilen ausgeführt werden; in solchen Fällen ist der while-Befehl klarer als ein degenerierter for-Befehl, dem ein oder mehrere seiner üblichen Ausdrücke fehlen. Der do while-Befehl ähnelt dem while-Befehl. Der Unterschied besteht darin, dass der do while-Befehl die Befehle in seinem Body ausführt, bevor er seinen Testausdruck auswertet. Deshalb wird der Schleifen-Body eines do while-Befehls immer wenigstens einmal ausgeführt. Der Body eines while-Befehls wird übersprungen, wenn der Testausdruck anfänglich den Wert false ergibt. Ein do while-Befehl wird in den folgenden Schritten ausgeführt: 1. Führe die Befehle im Body der Schleife aus. 2. Werte den Testausdruck aus. 3. Wenn das Ergebnis true ist, gehe zu Schritt 1. 4. Verlasse die Schleife und gehe zum nächsten sequenziellen Befehl. Das folgende Beispiel zeigt einen do while-Befehl in Aktion. Beachten Sie, wie die Position des Testausdrucks am Ende des Bodys Sie daran erinnert, dass der Body ausgeführt wird, bevor der Testausdruck ausgewertet wird: $summe = 0; $n = 1; do { $summe += $n; $n++; } while ($n <= $zahl); echo "<br>Die Summe der Ganzzahlen von 1 bis $zahl beträgt $summe."; 6 134 PHP 4 IT-Tutorial Frage an den Experten Frage: Der while-Befehl und der do while-Befehl scheinen sehr ähnlich zu sein. Wann sollte ich einen do while-Befehl anstelle eines while-Befehls verwenden? Antwort: Informatiker haben bewiesen, dass man jedes Programm ohne einen einzigen do while-Befehl schreiben kann. Deshalb ist die Verwendung eines do while-Befehls eine Frage der Bequemlichkeit, nicht der Notwendigkeit. Sie können ein Programm auch nur mit whileBefehlen schreiben. Im Allgemeinen ist es am besten hinzuschauen, bevor man springt. In unserem Fall bedeutet das, dass Sie den while-Befehl benutzen, der einen Testausdruck auswertet, bevor er die Befehle in seinem Body ausführt. Damit können Sie vermeiden, dass der Body der Schleife fälschlicherweise ausgeführt wird. Wenn Sie jedoch ein Muster wie <aktionen>; while (test-ausdruck) { <zu wiederholende aktionen>; } sehen, können Sie den Code gefahrlos durch Code ersetzen, der einen do while-Befehl verwendet: do { <aktionen >; } while (test-ausdruck); 1-Minuten-Test ● Schreiben Sie eine while-Schleife, die die Summe der Ganzzahlen von 1 bis 100 ausgibt. ● $summe = 0; $n = 1; while ($n <= 100) $summe += $n; echo "Die Summe beträgt $summe."; Kapitel 6: Kontrollbefehle schreiben ● 135 Schreiben Sie eine do while-Schleife, die die Summe der Ganzzahlen von 1 bis 100 ausgibt. Projekt 6–2: Benutzereingaben überprüfen In diesem Projekt werden Sie ein HTML-Formular und ein PHP-Skript p-6–2.php erstellen, mit denen ein Benutzer persönliche E-Mail-Adressdaten eingeben p-6–2.html kann. Das PHP-Skript prüft die Benutzereingaben auf Gültigkeit, um sicherzustellen, dass die erforderlichen Felder vorhanden sind. Projektziele ● Demonstrieren, wie Kontrollbefehle verwendet werden ● Eine Möglichkeit zeigen, wie Formulardaten validiert werden können Schritt für Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen p-6–2.php, und laden Sie diese Datei auf Ihren PHP-Server herauf: <html> <head> <title>Projekt 6–2</title> </head> <body> <!-- Datei p-6–2.php --> <?php $errors=0; if (!trim($spitzname)) { echo "<br><b>Spitzname</b> ist erforderlich."; $errors++; } if (!trim($vorname)) { echo "<br><b>Vorname</b> ist erforderlich."; ● $summe = 0; $n = 1; do { $summe += $n; } while ($n <= 100) echo "Die Summe beträgt $summe."; 6 136 PHP 4 IT-Tutorial $errors++; } if (!trim($nachname)) { echo "<br><b>Nachname</b> ist erforderlich."; $errors++; } if (!trim($email)) { echo "<br><b>Haupt-E-Mail-Adresse</b> ". "ist erforderlich."; $errors++; } if ($errors > 0) echo "<br><br><br>Bitte verwenden Sie die ". "Zurück-Schaltfläche Ihres Browsers, ". "um zu dem Formular zurückzukehren, "; if ($errors == 1) echo "den Fehler "; if ($errors > 1) echo "die Fehler "; if ($errors > 0) echo "zu korrigieren und das Formular ". "erneut abzusenden."; ?> </body> </html> 2. Speichern Sie die folgende HTML-Seite unter dem Dateinamen p-6– 2.html, und laden Sie diese Datei auf Ihren Server in dasselbe Verzeichnis wie die Datei p-6–2.php herauf: <html> <head> <title>Projekt 6–2</title> </head> <body> <!-- Datei p-6–2.html --> <form method="POST" action="p-6–2.php"> Kapitel 6: Kontrollbefehle schreiben 137 <h1>Kontaktinformationen</h1> <table> <tr> <td><b>Spitzname:</b></td> <td><input type="TEXT" name="spitzname"></td> </tr> <tr> <td>Titel:</td> <td><input type="TEXT" name="title"></td> </tr> <tr> <td><b>Vorname:</b></td> <td><input type="TEXT" name="vorname"></td> </tr> <tr> <td>Initialen:</td> <td><input type="TEXT" name="initialen"></td> </tr> <tr> <td><b>Nachname:</b></td> <td><input type="TEXT" name="nachname"></td> </tr> <tr> <td><b>Haupt-E-Mail-Adresse:</b></td> <td><input type="TEXT" name="email"></td> <td WIDTH="20">&nbsp;</td> <td>Zweite E-Mail-Adresse:</td> <td><input type="TEXT" name="email2"></td> </tr> <tr> <td>Firmenname:</td> <td><input type="TEXT" name="firmenname"></td> </tr> <tr> <td>Geschäftsadresse:</td> <td><input type="TEXT" name="geschaeftsadresse"></td> <td WIDTH="20">&nbsp;</td> <td>Privatadresse:</td> 6 138 PHP 4 IT-Tutorial <td><input type="TEXT" name="privatadresse"></td> </tr> <tr> <td></td> <td><input type="TEXT" name="geschaeftsadresse2"></ td> </tr> <tr> <td>Stadt:</td> <td><input type="TEXT" name="geschaeftsort"></td> <td WIDTH="20">&nbsp;</td> <td>&nbsp;</td> <td><input type="TEXT" name="privatort"></td> </tr> <tr> <td>Bundesland:</td> <td><input type="TEXT" name="geschaeftsbuland"></td> <td WIDTH="20">&nbsp;</td> <td>&nbsp;</td> <td><input type="TEXT" name="privatbuland"></td> </tr> <tr> <td>Postleitzahl:</td> <td><input type="TEXT" name="geschaeftsplz"></td> <td WIDTH="20">&nbsp;</td> <td>&nbsp;</td> <td><input type="TEXT" name="privatplz"></td> </tr> <tr> <td>Telefon:</td> <td><input type="TEXT" name="geschaeftstel"></td> <td WIDTH="20">&nbsp;</td> <td>&nbsp;</td> <td><input type="TEXT" name="privattel"></td> </tr> <tr> <td>Geburtsdatum:</td> <td><input type="TEXT" name="geburtsdatum"></td> </tr> Kapitel 6: Kontrollbefehle schreiben 139 <tr> <td>Name des Partners:</td> <td><input type="TEXT" name="partnername"></td> <td WIDTH="20">&nbsp;</td> <td>Namen der Kinder:</td> <td><input type="TEXT" name="kinder"></td> </tr> <tr> <td>Jahrestag:</td> <td><input type="TEXT" name="jahrestag"></td> </tr> </table> <br> <br> <br> <input type="SUBMIT" value="Absenden"> <br> <br> <input type="RESET" value="Formular löschen"> </form> </body> </html> 3. Nehmen Sie sich Zeit, das PHP-Skript zu studieren, wobei Sie besonders darauf achten sollten, wie mit Kontrollbefehlen sichergestellt wird, dass die Formulardaten gültig sind. 4. Geben Sie den URL der HTML-Datei, die Sie zuvor heraufgeladen haben, in das Adressfeld Ihres Webbrowsers ein. Die Anzeige des Browsers sollte ähnlich wie Abbildung 6.3 aussehen. Geben Sie in mehrere Felder Werte ein, und klicken Sie dann auf die SUBMIT-Schaltfläche (ABSENDEN). 6 140 PHP 4 IT-Tutorial Abbildung 6.3 Das Eingabeformular von Projekt 6–2 5. Wenn das Skript ausgeführt wird, prüft es, ob der Spitzname, der Vorname, der Nachname und die E-Mail-Adresse angegeben wurden. Wenn eines dieser Felder fehlt, gibt das Skript eine Fehlermeldung aus. Abbildung 6.4 zeigt ein typisches Ergebnis. Kapitel 6: Kontrollbefehle schreiben 141 6 Abbildung 6.4 Der Output von Projekt 6–2 mit einer Anzeige von Gültigkeitsfehlern 9Übungsaufgaben 1. Schreiben Sie einen if-Befehl, der den Wert von $y auf 1 setzt, wenn $x den Wert 1 hat, und der andernfalls den Wert von $y auf 2 setzt. 2. Schreiben Sie einen switch-Befehl, der $y den Wert 5 zuweist, wenn $x den Wert 1 hat, der $y den Wert 15 zuweist, wenn $x den Wert 2 hat, der $y den Wert 20 zuweist, wenn $x den Wert 3 hat, und der andernfalls $y den Wert -1 zuweist. 3. Schreiben Sie eine for-Schleife, die eine Reihe von Sternchen ausgibt; die Anzahl der Sternchen sollte durch den Wert von $stars festgelegt sein. 4. Schreiben Sie einen if-Befehl, der $y den Wert 1 zuweist, wenn $x den Wert 1 hat, der $y den Wert 3 zuweist, wenn $x den Wert 2 hat, der $y den Wert 5 zuweist, wenn $x den Wert 3 hat, und der andernfalls $y den Wert -1 zuweist. Kapitel 7 Mit Funktionen arbeiten Lernziele ● Wie Funktionen aufgerufen werden ● Wie der Name einer Funktion einer Variablen zugewiesen wird ● Wie Fehlermeldungen verborgen werden, die während der Ausführung einer Funktion erzeugt werden ● Wie Code verwendet werden kann, der in externen Dateien gespeichert ist ● Wie eine Funktion definiert wird ● Wie globale, lokale und statische Variablen verwendet werden ● Wie Referenzen verwendet werden 144 PHP 4 IT-Tutorial In Kapitel 2 wurden Funktionen vorgestellt, die die Ausführung verschiedener Berechnungen vereinfachen. In diesem Kapitel werden Sie mehr über den Einsatz von Funktionen erfahren und lernen, wie Sie Ihre eigenen Funktionen definieren können. Eine Funktion verwenden Das Ausführen einer Funktion wird auch als Aufrufen der Funktion bezeichnet. Um eine Funktion aufzurufen, schreiben Sie den Namen der Funktion, gefolgt von einem Paar Klammern. Beispielsweise wird die rand()-Funktion, die eine Zufallszahl erzeugt, folgendermaßen aufgerufen: rand(); Die meisten Funktionen verfügen über so genannte Argumente. Dabei handelt es sich um Input-Wert (Eingabewerte), die die Arbeitsweise und das Ergebnis der Funktion beeinflussen. Argumente werden zwischen den Klammern angegeben. Wenn eine Funktion mehr als ein Argument hat, müssen die einzelnen Argumente jeweils durch ein Komma getrennt werden. Ein Argument einer Funktion kann ein Literal, eine Variable oder ein Ausdruck sein. Einige PHP-Funktionen verfügen über optionale Argumente, die je nach Zweck angegeben oder weggelassen werden können. Beispielsweise hat die rand()-Funktion zwei optionale Argumente. Ihr erstes Argument legt die kleinste Zufallszahl fest, die die Funktion zurückgeben darf; ihr zweites Argument legt die größte fest. Wenn Sie beide Argumente weglassen, gibt die Funktion einen Wert zwischen 0 und dem größtmöglichen Ergebnis zurück. Wenn Sie wollen, können Sie nur das erste Argument angeben und das zweite weglassen: rand(100); Dann gibt die Funktion einen Wert zwischen 100 und dem größtmöglichen Ergebnis zurück. Wie rand() haben die meisten Funktionen Rückgabewerte. Sie können den Rückgabewert einer Funktion in einem Ausdruck verwenden. Sehr häufig wird der Rückgabewert einer Funktion einer Variablen zugewiesen, sodass der Wert wiederholt verwendet werden kann, ohne die Funktion mehr als einmal aufzurufen. Ein Beispiel: $radius = rand(1, 12); Kapitel 7: Mit Funktionen arbeiten 145 Wenn beim Ausführen einer Funktion ein Fehler auftritt, erzeugt PHP Fehlermeldungen. Manchmal sind solche Fehlermeldungen unerwünscht. Wenn dies der Fall ist, können Sie die Erzeugung von Fehlermeldungen unterdrücken, indem Sie vor den Namen der aufgerufenen Funktion ein @ setzen. Um beispielsweise Fehlermeldungen zu unterdrücken, die beim Ausführen der Funktion f() auftreten könnten, rufen Sie die Funktion folgendermaßen auf: y = @f(x); 1-Minuten-Test ● Schreiben Sie einen Befehl, der $x eine Zufallszahl von 1 bis 10 zuweist. ● Schreiben Sie einen Befehl, der die Funktion errorprone() aufruft, die keine Argumente hat und kein Ergebnis zurückgibt, und der dabei mögliche Fehlermeldungen unterdrückt. Dateien einbinden Mit PHP-Funktionen können Sie auf fertigen PHP-Code zugreifen, den Sie oder andere PHP-Programmierer geschrieben haben. Der require-Befehl stellt einen weiteren Mechanismus zur Verfügung, mit dem Sie fertigen Code nutzen können. Der Befehl hat die folgende Form: Require(dateiname); Das Argument dateiname ist ein String, sodass ein typischer require-Befehl folgendermaßen aussehen könnte: require ("datei.inc"); Wenn ein PHP-Skript mit einem require-Befehl geladen wird, wird der Inhalt der angegebenen Datei – der so genannten Include-Datei – in das Skript eingefügt und ersetzt dort den require-Befehl. Wenn die Include-Datei PHP-Code enthält, muss dieser an den richtigen Stellen die Tags <?php und ?> enthalten. Es ist üblich, dem Namen einer Include-Datei die Dateierweiterung inc zu geben, aber dies ist nicht erforderlich. Einige PHP-Programmierer verwenden für alle Dateien die Namenserweiterung php. ● $x = rand(1, 10); ● @errorprone(); 7 146 PHP 4 IT-Tutorial Mit dem require-Befehl können Sie sehr viel Arbeit sparen. Nehmen wir beispielsweise an, dass Sie eine PHP-Anwendung schreiben wollen, die aus vielen Skripts besteht, die jeweils eine HTML-Seite anzeigen, die in ihrem Kopf die gleichen Standardinformationen enthält. Dann könnten Sie eine spezielle Skriptdatei namens header.inc erstellen, die den gleichbleibenden Code enthält. Ein Beispiel: <html> <head> <title>Der ultimative Anwendungsgenerator</title> </head> <body> <h1>Der ultimative Anwendungsgenerator</h1> <h5>Copyright 2005, Hans Programmierer mit Freunden, Inc.</ h5> und so weiter Indem Sie den Befehl require("header.inc"); an den Anfang jedes Skripts setzen, veranlassen Sie PHP, den Inhalt dieser Datei so einzubinden, als wäre er ein Teil des jeweiligen Skripts. Mit diesem Verfahren können Sie die Wartung von Programmen vereinfachen, weil Sie gewisse Standardinformationen in einer einzigen Datei speichern können, sodass das Aufinden und Ändern dieser Informationen erheblich leichter ist. Mit dem zugehörigen require_once-Befehl können Sie sicherstellen, dass die angegebene Datei nur einmal in ein bestimmtes Skript eingebunden wird. Wenn Sie IncludeDateien erstellen, die den require-Befehl verwenden, um die Inhalte anderer Include-Dateien einzubinden, kann der require_once-Befehl für Sie nützlich sein. Frage an den Experten Frage: Was ist, wenn man den Namen einer Include-Datei erst in einem Programm zusammensetzen will? Wie ist das möglich? Antwort: Der require-Befehl wird verarbeitet, wenn das verbundene PHP-Skript geladen wird, aber bevor Werte an Variablen gebunden werden. Deshalb können Sie keinen Ausdruck verwenden, um den Namen der Datei anzugeben, die mit einem require-Befehl eingebunden werden soll. Kapitel 7: Mit Funktionen arbeiten 147 Sie können jedoch den include-Befehl verwenden. Dabei handelt es sich um einen ausführbaren Befehl, der bewirkt, dass das PHP-Skript, das sich in der angegebenen Datei befindet, ausgewertet wird. Beispielsweise wertet der include-Befehl in dem folgenden Code die Datei datei1.inc aus: $x = 1; include ("datei" . $x . ".inc"); Wenn die Include-Datei ausgewertet wird, werden die PHP-Befehle, die in ihr enthalten sind, so ausführt, als stünden sie in dem Text des aufrufenden Skripts. 1-Minuten-Test ● Schreiben Sie einen Befehl, der den Inhalt der Datei footer.inc in den aktuellen Quelltext einbindet. ● Schreiben Sie einen Befehl, der den Inhalt der Datei footer.inc in den aktuellen Quelltext einbindet und sicherstellt, dass die Datei nur einmal eingefügt wird. Eine Funktion definieren Sie können nicht nur Funktionen der PHP-Funktionsbibliothek verwenden, sondern auch eigene Funktionen definieren und verwenden. Die Definition einer Funktion hat das folgende allgemeine Muster: function funktionsname(argumentname) { // Hier stehen die Befehle des Funktionskörpers. } Hier steht funktionsname für den Namen der Funktion und argumentname den Namen des Funktionsarguments. In PHP spielt die Schreibweise von Funktionsnamen keine Rolle, d.h. f() und F() beziehen sich auf dieselbe Funktion. Das Schlüsselwort function, der Funktionsname, und das Argument bilden ● require("footer.inc"); ● require_once("footer.inc"); 7 148 PHP 4 IT-Tutorial zusammen den Kopf der Funktion. Die Befehle, die von den geschweiften Klammern eingeschlossen werden, die auf den Kopf der Funktion folgen, werden zusammenfassend als Körper der Funktion bezeichnet. Die Befehle des Funktionskörpers werden ausführt, wenn die Funktion aufgerufen wird. Wenn Sie eine Funktion ohne Argument definieren wollen, können Sie argumentname weglassen; wenn Sie eine Funktion mit mehreren Argumenten definieren wollen, können Sie nach argumentname zusätzliche Argumente angeben, wobei Sie benachbarte Funktionen jeweils durch ein Komma trennen. Die Klammern und die eingeschlossenen Argumentnamen werden zusammenfassend als Argumentenliste bezeichnet. Das folgende Beispiel zeigt eine Funktion, die die Fläche eines Rechtecks berechnet: function flaeche_berechnen($hoehe, $breite) { return $hoehe * $breite; } Die Argumentenliste der flaeche_berechnen-Funktion enthält die Argumente $hoehe und $breite. Der Funktionskörper besteht aus einem einzigen Befehl; jedoch kann ein Funktionskörper eine beliebige Anzahl von Befehlen enthalten. Wenn die Funktion einen Wert zurückgeben soll, sollten Sie einen return-Befehl in die Funktion einfügen, die den Wert zur Verfügung stellt. Der return-Befehl beendet die Ausführung der Funktion. Er muss nicht der physisch letzte Befehl des Funktionskörpers sein. Wenn Sie eine Funktion definieren, die keinen return-Befehl enthält, gibt die Funktion den speziellen Wert NULL zurück. Eine benutzerdefinierte Funktion aufrufen Eine benutzerdefinierte Funktion wird auf dieselbe Weise aufgerufen wie eine eingebaute Funktion. Das folgende Beispiel zeigt einen Befehl, der die Funktion flaeche_berechnen aufruft: $flaeche = flaeche_berechnen(2, 4); Die Werte der aktuellen Argumente – 2 und 4 – werden für die formellen Argumente in den Funktionskörper von flaeche_berechnen eingefügt. Die Funktion verhält sich so, als hätten Sie den Befehl folgendermaßen geschrieben: return 2 * 4; Kapitel 7: Mit Funktionen arbeiten 149 Tipp In PHP 3 musste die Definition einer Funktion vor dem Code stehen, der die Funktion aufrief. In PHP 4 kann die Definition einer Funktion vor oder nach dem Code stehen, der die Funktion aufruft. Die Ausführung einer Funktion beenden Ein return-Befehl beendet die Ausführung der Funktion, in der er enthalten ist. Wenn Sie die Ausführung eines kompletten Skripts beenden wollen, können Sie die exit()-Funktion ausführen. Ein einfaches Beispiel: function stop() { exit(); } echo "<br>Eins..."; echo "<br>Zwei..."; stop(); echo "<br>Drei!"; Der Output dieses Skripts enthält die Wörter Eins und Zwei, aber nicht das Wort Drei. Wenn die stop()-Funktion aufgerufen wird, wird der Körper der Funktion ausgeführt. Wenn die exit()-Funktion aufgerufen wird, wird die Ausführung des Skripts beendet. Rekursive Funktionen In PHP ist es möglich, Funktionen zu schreiben, die sich selbst aufrufen. Eine Funktion, die sich selbst aufruft, wird als rekursive Funktion bezeichnet. Jedoch sollten Sie, wenn Sie nicht gerade Informatik studiert haben, rekursive Funktionen eher nicht verwenden. Dennoch kann dies unabsichtlich geschehen, sodass gewisse Kenntnisse über diese Funktionen hilfreich sein können. Der folgende Code definiert eine einfache rekursive Funktion und ruft sie auf: function recurser() { return recurser(); } $x = recurser(); 7 150 PHP 4 IT-Tutorial Wenn die recurser()-Funktion aufgerufen wird, ruft sie sofort die recurser()-Funktion auf, die sich wiederum selbst aufruft, usw. Auf diese Weise wird die recurser()-Funktion wiederholt aufgerufen, bis ein spezieller Fehler, ein so genannter Stapelüberlauf auftritt. Wenn Ihr Programm mit einem Stapelüberlauf abgebrochen wird, kann die Ursache dafür eine unbeabsichtigte Rekursion sein. Standardargumente definieren In PHP 4 können Sie Funktionen definieren, die über Standardargumente verfügen. Wenn Sie eine Funktion mit einem Standardargument aufrufen, aber für dieses Argument keinen Wert angeben, dann nimmt das Argument ein vordefinierten Standardwert an. Ein einfaches Beispiel: function steuer($betrag, $satz=0.16) { echo "<br>Betrag=$betrag"; echo "<br>Satz=$satz"; return $betrag * $satz; } $netto = 123.45; echo "<br>Nettobetrag = $netto"; $steuer = steuer($netto, 0.07); echo "<br>Steuer = $steuer"; $netto = 123.45; echo "<br>Nettobetrag = $netto"; $steuer = steuer($netto); echo "<br>Steuer = $steuer"; Die steuer-Funktion hat zwei Argumente: ein erforderliches Argument namens $betrag und ein Standardargument namens $satz. Wenn Sie die Funktion aufrufen und nur ein einziges Argument angeben, wird der Wert dieses Arguments als Wert von $betrag interpretiert, während $satz den vordefinierten Standardwert annimmt. Deshalb hat $satz beim ersten Aufruf der Funktion den Wert 0.07, der als zweites Argument der Funktion angegeben wird, während $satz beim zweiten Aufruf der Funktion den Wert 0.16 (den Standardwert) annimmt, weil nur ein einziges Argument angegeben wird. Kapitel 7: Mit Funktionen arbeiten 151 Frage an den Experten Frage: Kann eine Funktion mehrere Standardargumente haben? Antwort: Ja, aber das Ergebnis ist häufig verwirrend. Betrachten wir beispielsweise den folgenden Funktionskopf: function twobad($zeit = 1, $ort = 2) Wie sollte das Ergebnis lauten, wenn die Funktion folgendermaßen aufgerufen wird? x = twobad(3); Anders ausgedrückt: Welches Argument sollte als Wert von $zeit oder als Wert von $ort verwendet werden? PHP verfügt über Regeln, um solche Situationen zu klären, aber diese Regeln können verwirrend sein. Deshalb ist es besser, wenn Sie dieses Problem vermeiden, indem Sie nur ein einziges Standardargument definieren und dieses als letztes Argument der Argumentenliste angeben. 1-Minuten-Test ● Schreiben Sie die Definition einer Funktion, die die Fläche eines Kreises berechnet, wenn der Radius bekannt ist. ● Schreiben Sie die Definition einer Funktion, die den <head>-Block einer HTML-Seite ausgibt und in einem <title>-Block den String enthält, der als Argument der Funktion angegeben wird. ● function kreisflaeche($radius) { return 3.14159 * $radius * $radius; } ● function head_block($titelstring) { echo "<head>\n"; echo "<title>$titelstring</title>\n"; echo "</head>\n"; } 7 152 PHP 4 IT-Tutorial PHP-Variablen und -Referenzen PHP-Variablen können in zwei Typen eingeteilt werden: ● globale Variablen ● lokale Variablen Globale Variablen werden außerhalb aller Funktionen erstellt, während lokale Variablen innerhalb einer Funktion definiert werden. Dieser Abschnitt beschreibt globale und lokale Variablen sowie so genannte Referenzen, die eine spezielle Methode bilden, um Variablen anzugeben. Globale Variablen verwenden Wie bereits erwähnt wurde, werden globale Variablen außerhalb aller Funktionen deklariert. Ein wichtiger Typ von globalen Variablen sind die Formularvariablen. Jedoch können Sie eine globale Variable einfach dadurch erstellen, dass Sie ihr einen Wert zuweisen und dabei einen Befehl benutzen, der sich nicht im Körper einer Funktion befindet. Der Bereich, in dem der Zugriff auf eine Variable möglich ist, wird als Geltungsbereich der Variablen bezeichnet. Standardmäßig ist es nicht möglich, innerhalb eines Funktionskörpers auf globale Variablen zuzugreifen, d.h. der Geltungsbereich einer globalen Variablen erstreckt sich nicht auf Funktionskörper. Wenn Sie innerhalb einer Funktion auf eine globale Variable zugreifen wollen, können Sie den Geltungsbereich der Variablen mit einem global-Befehl erweitern. Der global-Befehl hat die folgende Form: global variable1, variable2, variable3 Der Befehl besteht aus dem Schlüsselwort global und einem oder mehreren Namen von Variablen; benachbarte Variablen werden jeweils durch ein Komma getrennt. Das folgende Beispiel zeigt den global-Befehl in Aktion: function isnotglobal() { echo "<br>nicht global: x=$x"; } function isglobal() { global $x; echo "<br>global: x=$x"; } Kapitel 7: Mit Funktionen arbeiten 153 $x = 1; isnotglobal(); isglobal(); Wenn Sie dieses Skript ausführen, wird der folgende Output angezeigt: nicht global: x= global: x=1 Beachten Sie, dass die Wertzuweisung der Variablen $x außerhalb jedes Funktionskörpers erfolgt; das heißt, $x ist eine globale Variable. Folglich befindet sich die Variable $x nicht innerhalb des Geltungsbereiches der Funktion isnotglobal(), und deshalb zeigt der echo-Befehl innerhalb von isnotglobal() keinen Wert an. Dagegen enthält die Funktion isglobal() einen globalBefehl, der den Geltungsbereich von $x erweitert; deshalb zeigt der echo-Befehl innerhalb von isglobal() den Wert von $x an. Lokale und statische Variablen verwenden Neben dem Geltungsbereich, der beschreibt, wo eine Variable verfügbar ist, spielt die Lebensdauer einer Variablen eine wichtige Rolle. Die Lebensdauer beschreibt, wann ein Variable verfügbar ist. Globale Variablen werden erstellt, wenn ihnen ein Wert zugewiesen wird. Sie existieren für die Dauer eines Programms. Im Gegensatz dazu werden lokale Variablen erstellt, wenn die zugehörige Funktion aufgerufen wird, und sie werden zerstört, wenn der Funktionsaufruf beendet wird. Lokale Variablen sind deshalb nur beim Ausführen der zugehörigen Funktion verfügbar. Funktionsargumente sind ein wichtiger Typ von lokalen Variablen. Sie können jedoch eine lokale Variable einfach dadurch erstellen, dass Sie einer Variablen innerhalb einer Funktion einen Wert zuweisen. Das folgende Skript illustriert den Unterschied zwischen lokalen und globalen Variablen. Es definiert eine lokale Variable namens $x und ein globale Variable mit demselben Namen: function haslocal() { $x = 2; echo "<br>Im Funktionskörper: x=$x"; } $x = 1; echo "<br>Im Skriptkörper: x=$x"; 7 154 PHP 4 IT-Tutorial haslocal(); echo "<br>Im Skriptkörper: x=$x"; Wenn Sie dieses Skript ausführen, wird der folgende Output angezeigt: Im Skriptkörper: x=1 Im Funktionskörper: x=2 Im Skriptkörper: x=1 Beachten Sie, dass es sich um zwei unterschiedliche Variablen handelt, obwohl sie denselben Namen haben. Der Geltungsbereich der globalen Variablen $x reicht nicht in den Körper der Funktion haslocal() hinein, und der Geltungsbereich der lokalen Variablen $x reicht nicht über den Körper dieser Funktion hinaus. Das bedeutet, dass die Geltungsbereiche der beiden Variablen vollkommen getrennt sind, sodass PHP ihre Werte nicht verwechselt. Manchmal soll eine lokale Variable ihren Wert von einem Funktionsaufruf zum nächsten beibehalten, d.h. die Variable soll nicht zerstört werden, wenn die Funktion beendet wird. Mit dem static-Befehl können Sie dieses Verhalten einer Variablen festlegen. Der static-Befehl verwendet das Schlüsselwort static, ansonsten hat er dieselbe Form wie der global-Befehl. Eine Variable, die in einem static-Befehl aufgeführt ist, wird als statische lokale Variable oder knapper als statische Variable bezeichnet. Das folgende Beispiel zeigt die Verwendung einer statischen Variablen: function isnotstatic() { $x = $x + 1; echo "<br>x=$x"; } function isstatic() { static $x; $x = $x + 1; echo "<br>x=$x"; } isnotstatic(); isnotstatic(); isnotstatic(); isstatic(); isstatic(); isstatic(); Kapitel 7: Mit Funktionen arbeiten 155 Wenn Sie dieses Skript ausführen, wird der folgende Output angezeigt: x=1 x=1 x=1 x=1 x=2 x=3 Beachten Sie, dass die lokale Variable $x, die in der Funktion isnotstatic() definiert wird, bei jedem Aufruf der Funktion neu erstellt wird. Deshalb wird sie jedes Mal mit dem Wert 1 angezeigt. Im Gegensatz dazu behält die statische Variable $x, die in der Funktion isstatic() definiert wird, ihren Wert von einem Funktionsaufruf zum nächsten; deshalb erhöht sich ihr Wert mit jeder Ausführung der Funktion. Beachten Sie auch, dass die Geltungsbereiche der lokalen Variablen $x und der statischen Variablen $x verschieden sind; deshalb unterscheiden sich die Werte der beiden Variablen, obwohl die Variablen denselben Namen haben. Referenzen benutzen (PHP4) Standardmäßig werden die Argumente in einer PHP-Funktion als Werte übergeben. Dies bedeutet, dass die Werte von Argumenten kopiert werden und die Funktionen mit Kopien ihrer Argumentwerte anstatt mit den tatsächlichen Argumenten arbeiten. Folglich kann eine PHP-Funktion die Werte ihrer Argumente nicht ändern. Im Allgemeinen ist ein solches Verhalten hilfreich, weil das Verhalten von Funktionen leichter zu verstehen ist, wenn sie einfach einen Wert zurückgeben, anstatt Werte zu ändern. Wenn eine Funktion jedoch in der Lage sein soll, den Wert eines Arguments zu ändern, können Sie das Argument per Referenz übergeben. In diesem Fall wird sein Wert nicht kopiert; die Funktion arbeitet nicht mit einer Kopie, sondern mit dem Argument selbst und kann dessen Wert ändern. Um ein Argument per Referenz zu übergeben, wird ein kaufmännisches Und-Zeichen (&) vor den Namen des Arguments gesetzt. Sie können dieses Präfix entweder im Kopf der Funktion oder in dem Funktionsaufruf vor den Namen des Arguments setzen. Das folgende Beispiel zeigt einen Funktionsaufruf per Wert und einen per Referenz: function perwert($x) { $x = 1; } 7 156 PHP 4 IT-Tutorial function perreferenz(&$x) { $x = 1; } $y = 0; perwert($y); echo "<br>\$y=$y"; $y = 0; perwert(&$y); echo "<br>\$y=$y"; $y = 0; perreferenz($y); echo "<br>\$y=$y"; Wenn Sie dieses Skript ausführen, wird der folgende Output angezeigt: $y=0 $y=1 $y=1 Beachten Sie, dass das Skript zwei Funktionen, perwert() und perreferenz(), enthält. Jede Funktion hat ein einziges Argument namens $x. Der Kopf der perreferenz()-Funktion legt fest, dass ihr Argument per Referenz übergeben wird; das Argument der perwert()-Funktion wird per Wert übergeben, wie es dem Standardverhalten von PHP entspricht. Jede Funktion versucht, den Wert ihres Arguments zu ändern. Der erste Absatz des Codes ruft perwert() auf und übergibt das Argument per Wert. Folglich arbeitet die Funktion mit einer Kopie ihres Arguments, und der Wert von $y wird nicht geändert. Der zweite Absatz des Codes ruft ebenfalls perwert() auf; dabei wird jedoch ein kaufmännisches Und-Zeichen verwendet, was zur Folge hat, dass $y per Referenz übergeben wird. Deshalb modifiziert die Funktion den Wert ihres Arguments, das sich von 0 in 1 ändert. Der dritte Absatz des Codes ruft perreferenz() auf. Im Kopf dieser Funktion wird ein kaufmännisches Und-Zeichen verwendet, um festzulegen, dass ihr Argument per Referenz übergeben werden soll. Folglich modifiziert die Funktion den Wert ihres Arguments, der sich von 0 in 1 ändert. Kapitel 7: Mit Funktionen arbeiten 157 Frage an den Experten Frage: Warum sollte ich eine Referenz oder einen Aufruf per Referenz verwenden? Antwort: Referenzen vermeiden den zusätzlichen Aufwand, der mit dem Kopieren der Werte verbunden ist, und können deshalb die Ausführung eines Programms beschleunigen. Jedoch erschweren sie häufig das Verstehen von Programmen und können dadurch Programmfehler verursachen. Wenn möglich, sollten Sie Referenzen vermeiden und Funktionen definieren, die Werte zurückgeben, anstatt die Werte ihrer Argumente zu ändern. Jedoch ist es wichtig, Referenzen zu verstehen, damit Sie mit Programmen arbeiten können, die von Programmierern geschrieben wurden, die diesen Rat nicht beherzigt haben. 7 1-Minuten-Test ● Welcher Befehl wird in einer Funktion benötigt, um auf eine Variable namens $gewicht zuzugreifen, die außerhalb der Funktion erstellt wurde? ● Mit welchem Befehl könnte die lokale Variable $zaehler ihren Wert über mehrere Aufrufe der verbundenen Funktion hinweg beibehalten? Projekt 7–1: Eine Überarbeitung des Kontaktformulars p-7 – 1.php p-7–1.inc p-7–1.html In diesem Projekt werden Sie überarbeitete Versionen des HTML-Formulars und des PHP-Skripts von Projekt 6–2 erstellen. Mit dem Formular kann ein Benutzer Adressdaten eingeben. Das PHP-Skript prüft die Benutzereingaben auf Gültigkeit, um sicherzustellen, dass die erforderlichen Felder vorhanden sind. ● global $gewicht; ● static $zaehler; 158 PHP 4 IT-Tutorial Projektziele ● Demonstrieren, wie der include-Befehl funktioniert ● Demonstrieren, wie eine Funktion definiert und erstellt wird ● Demonstrieren, wie Dummy-Routinen funktionieren Schritt für Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen p-7– 1.php, und laden Sie diese Datei auf Ihren PHP-Server herauf: <?php include "p-7–1.inc"; function formular_validieren() { global $spitzname, $vorname, $nachname, $email; $errors=0; if (!trim($spitzname)) { echo "<br><b>Spitzname</b> ist erforderlich."; $errors++; } if (!trim($vorname)) { echo "<br><b>Vorname</b> ist erforderlich."; $errors++; } if (!trim($nachname)) { echo "<br><b>Nachname</b> ist erforderlich."; $errors++; } if (!trim($email)) { echo "<br><b>Haupt-E-Mail-Adresse</b> ist "; echo "erforderlich."; $errors++; } switch ($errors) Kapitel 7: Mit Funktionen arbeiten 159 { case 0: return TRUE; case 1: echo "<br><br><br>Bitte verwenden Sie die "; echo "Zurück-Schaltfläche Ihres Browsers, "; echo "um zu dem Formular zurückzukehren, "; echo "den Fehler zu korrigieren und "; echo "das Formular erneut abzusenden."; return FALSE; default: echo "<br><br><br>Bitte verwenden Sie die "; echo "Zurück-Schaltfläche Ihres Browsers, "; echo "um zu dem Formular zurückzukehren, "; echo "die Fehler zu korrigieren und "; echo "das Formular erneut abzusenden."; return FALSE; } } function datenbank_aktualisieren() { echo "<br>Datenbank aktualisieren..."; } $ok = formular_validieren(); if ($ok) datenbank_aktualisieren(); ?> </body> </html> 2. Speichern Sie den folgenden HTML-Text unter dem Dateinamen p-7–1.inc, und laden Sie diese Datei auf Ihren Server in dasselbe Verzeichnis wie die Datei p-7–1.php herauf: <html> <head> <title>Projekt 7–1</title> </head> <body> 7 160 PHP 4 IT-Tutorial 3. Speichern Sie den folgenden HTML-Text unter dem Dateinamen p-7 – 1.html , und laden Sie diese Datei auf Ihren Server in dasselbe Verzeichnis wie die Datei p-7 – 1.php herauf: <html> <head> <title>Projekt 7–1</title> </head> <body> <!-- Datei p-7–1.html --> <form method="POST" action="p-7–1.php"> <h1>Kontaktinformationen</h1> <table> <tr> <td><b>Spitzname:</b></td> <td><input type="TEXT" name="spitzname"></td> </tr> <tr> <td>Titel:</td> <td><input type="TEXT" name="title"></td> </tr> <tr> <td><b>Vorname:</b></td> <td><input type="TEXT" name="vorname"></td> </tr> <tr> <td>Initialen:</td> <td><input type="TEXT" name="initialen"></td> </tr> <tr> <td><b>Nachname:</b></td> <td><input type="TEXT" name="nachname"></td> </tr> <tr> <td><b>Haupt-E-Mail-Adresse:</b></td> <td><input type="TEXT" name="email"></td> <td width="20">&nbsp;</td> <td>Zweite E-Mail-Adresse:</td> Kapitel 7: Mit Funktionen arbeiten 161 <td><input type="TEXT" name="email2"></td> </tr> <tr> <td>Firmenname:</td> <td><input type="TEXT" name="firmenname"></td> </tr> <tr> <td>Geschäftsadresse:</td> <td><input type="TEXT" name="geschaeftsadresse"></td> <td width="20">&nbsp;</td> <td>Privatadresse:</td> <td><input type="TEXT" name="privatadresse"></td> </tr> <tr> <td></td> <td><input type="TEXT" name="geschaeftsadresse2"> </td> </tr> <tr> <td>Stadt:</td> <td><input type="TEXT" name="geschaeftsort"></td> <td width="20">&nbsp;</td> <td>&nbsp;</td> <td><input type="TEXT" name="privatort"></td> </tr> <tr> <td>Bundesland:</td> <td><input type="TEXT" name="geschaeftsbuland"></td> <td width="20">&nbsp;</td> <td>&nbsp;</td> <td><input type="TEXT" name="privatbuland"></td> </tr> <tr> <td>Postleitzahl:</td> <td><input type="TEXT" name="geschaeftsplz"></td> <td width="20">&nbsp;</td> <td>&nbsp;</td> <td><input type="TEXT" name="privatplz"></td> </tr> 7 162 PHP 4 IT-Tutorial <tr> <td>Telefon:</td> <td><input type="TEXT" name="geschaeftstel"></td> <td width="20">&nbsp;</td> <td>&nbsp;</td> <td><input type="TEXT" name="privattel"></td> </tr> <tr> <td>Geburtsdatum:</td> <td><input type="TEXT" name="geburtsdatum"></td> </tr> <tr> <td>Name des Partners:</td> <td><input type="TEXT" name="partnername"></td> <td width="20">&nbsp;</td> <td>Namen der Kinder:</td> <td><input type="TEXT" name="kinder"></td> </tr> <tr> <td>Jahrestag:</td> <td><input type="TEXT" name="jahrestag"></td> </tr> </table> <br> <br> <br> <input type="SUBMIT" value="Absenden"> <br> <br> <input type="RESET" value="Formular löschen"> </form> </body> </html> 4. Nehmen Sie sich Zeit, das PHP-Skript zu studieren, wobei Sie besonders darauf achten sollten, wie das ursprüngliche Programm geändert wurde, um eine Include-Datei und Funktionen zu verwenden. Achten Sie insbesondere auch darauf, dass die Funktion datenbank_aktualisieren()in ihrem Körper nur einen echo-Befehl enthält. Eine solche Funktion wird Kapitel 7: Mit Funktionen arbeiten 163 auch als Dummy-Routine oder Platzhalterroutinen (engl. stub) bezeichnet. Dummy-Routinen werden während der Programmentwicklung verwendet, um ein Programm ausführen und testen zu können, bevor eine Funktion komplett fertig ist. Der Körper der Funktion datenbank_aktualisieren() wird später ausgearbeitet, um dann tatsächlich eine Datenbank zu aktualisieren. 5. Geben Sie den URL der HTML-Datei, die Sie zuvor heraufgeladen haben, in das Adressfeld Ihres Webbrowsers ein. Die Anzeige des Browsers sollte ähnlich wie Abbildung 7.1 aussehen. Geben Sie in mehrere Felder Werte ein, und klicken Sie dann auf die SUBMIT-Schaltfläche (ABSENDEN). 7 Abbildung 7.1 Das Eingabeformular von Projekt 7–1 164 PHP 4 IT-Tutorial 6. Wenn das Skript ausgeführt wird, prüft es, ob der Spitzname, der Vorname, der Nachname und die E-Mail-Adresse angegeben wurden. Wenn eines dieser Felder fehlt, gibt das Skript eine Fehlermeldung aus. Abbildung 7.2 zeigt ein typisches Ergebnis. Abbildung 7.2 Der Output von Projekt 7–1 mit einer Anzeige von Gültigkeitsfehlern 9Übungsaufgaben 1. Schreiben Sie einen Befehl, der die Funktion test() aufruft und die Werte 1 und 2 als Argumente übergibt. 2. Schreiben Sie einen Befehl, der die Funktion live() aufruft und die Werte 1 und 2 als Argumente übergibt; stellen Sie sicher, dass während der Ausführung der Funktion keine Fehlermeldungen generiert werden. 3. Schreiben Sie einen Befehl, der den Inhalt der Datei header.php in das aktuelle Skript einbindet. 4. Schreiben Sie die Definition einer Funktion namens quadrat(), die die Fläche eines Quadrats berechnet, wenn die Länge einer Seite des Quadrats bekannt ist. 5. Schreiben Sie die Definition einer Funktion namens zaehler(), die den Wert einer statischen lokalen Variablen erhöht und zurückgibt. Kapitel 8 Mit Arrays arbeiten Lernziele ● Wie ein Array erstellt wird ● Wie ein Array durchlaufen wird ● Wie Listenfunktionen verwendet werden ● Wie ein Array sortiert wird ● Wie Arrays beim Arbeiten mit Formularvariablen verwendet werden 166 PHP 4 IT-Tutorial In Kapitel 2 wurden Arrays als ein spezieller Typ von Variablen vorgestellt, die mehrere zusammenhängende Werte enthalten. In diesem Kapitel werden Sie mehr über das Arbeiten mit Arrays lernen. Arrays erstellen Es gibt zwei Hauptmethoden, um ein PHP-Array zu erstellen: Sie können einer Array-Variablen einen Wert zuweisen, oder Sie können die array()-Funktion aufrufen. In diesem Abschnitt werden diese beiden Methoden erklärt. Ein Array mit einer Zuweisung erstellen Der direkteste Weg, ein Array zu erstellen, besteht darin, einer Array-Variablen einen Wert zuzuweisen. Ein Beispiel: $sprachen[] = "Perl"; $sprachen[] = "PHP"; $sprachen[] = "Python"; Die eckigen Klammern hinter dem Variablennamen zeigen PHP an, dass die Variable $sprachen eine Array-Variable ist. PHP speichert automatisch alle Werte, die dem Array zugewiesen werden, in fortlaufend nummerierten Zellen, beginnend mit $sprachen[0]. Die drei Zuweisungsbefehle führen zu den folgenden Array-Inhalten: 0 => Perl 1 => PHP 2 => Python Das Symbol => zeigt an, dass mit einem Wert ein Schlüssel verbunden ist. In diesem Fall ist der Schlüssel 0 mit dem Wert "Perl", der Schlüssel 1 mit dem Wert "PHP" und der Schlüssel 2 mit dem Wert "Python" verbunden. Alternativ können Sie ein Array auch als Tabelle betrachten und das vorangegangene Beispiel folgendermaßen repräsentieren: 0 1 2 Perl PHP Python Kapitel 8: Mit Arrays arbeiten 167 Wenn Sie wollen, können Sie in der Zuweisung ausdrücklich einen Schlüsselwert angeben, um einen Wert mit einem bestimmten Array-Element zu verbinden. Betrachten Sie das folgende Beispiel: $sprachen[0] = "Perl"; $sprachen[1] = "PHP"; $sprachen[] = "Python"; Beachten Sie, dass die letzte Zuweisung keinen Indexwert enthält. PHP verbindet den Wert "Python" mit dem nächsten fortlaufenden Element des Arrays: 0 => Perl 1 => PHP 2 => Python Array-Elemente müssen nicht über fortlaufende Schlüssel verfügen. Die Zuweisungen $sprachen[10] = "Perl"; $sprachen[20] = "PHP"; $sprachen[] = "Python"; ergeben die folgenden Array-Inhalte: 10 => Perl 20 => PHP 21 => Python Beachten Sie, dass der Wert "Python" wie zuvor mit dem nächsten fortlaufenden Element des Arrays verbunden wird. In Kapitel 2 wurde erwähnt, dass die Schlüsselwerte in PHP nicht auf Ganzzahlen beschränkt sind. Sie können ein so genanntes assoziatives Array oder stringindiziertes Array erstellen, indem Sie Strings als Schlüssel verwenden: $sprachen['PHP'] = "Hoch"; $sprachen['Python'] = "Mittel"; $sprachen['Perl'] = "Niedrig"; Diese Zuweisungen verbinden die folgenden Schlüssel und Werte: PHP => Hoch Python => Mittel Perl => Niedrig 8 168 PHP 4 IT-Tutorial Fortlaufende Ganzzahlen als Schlüssel nehmen eine Sonderstellung ein, weil sie dazu verwendet werden können, mit einer einfachen for-Schleife alle Elemente des Arrays zu durchlaufen, um diese zu untersuchen oder zu bearbeiten. Im nächsten Abschnitt werden Sie mehr über das Durchlaufen von Arrays lernen. Mit der array()-Funktion arbeiten Neben den Zuweisungsbefehlen bildet die array()-Funktion die andere Hauptmethode, um ein PHP-Array zu erstellen. Das folgende einfache Beispiel erstellt ein Array mit fortlaufenden Ganzzahlen als Schlüssel: $sprachen = array("Perl", "PHP", "Python"); Dieser Befehl erstellt ein Array mit den folgenden Elementen: 0 => Perl 1 => PHP 2 => Python Wenn Sie einen bestimmten Schlüssel mit einem Wert verbinden wollen, können Sie den =>-Operator verwenden: $sprachen = array(10=>"Perl", "PHP", "Python"); Dieser Befehl erstellt das folgende Array: 10 => Perl 11 => PHP 12 => Python Wie bei einem Zuweisungsbefehl müssen die Schlüsselwerte nicht fortlaufend und nicht ganzzahlig sein: $sprachen = array("PHP"=>"Hoch", "Python"=>"Mittel", "Perl"=>"Niedrig"); Dieser Befehl erstellt das folgende Array: PHP => Hoch Python => Mittel Perl => Niedrig Kapitel 8: Mit Arrays arbeiten 169 Frage an den Experten Frage: In anderen Programmiersprachen ist es möglich, mehrdimensionale Arrays zu erstellen. Gilt dies auch für PHP? Antwort: Man kann ein mehrdimensionales Array einfach als ein Array auffassen, dessen Zellen Array-Werte enthalten, gewissermaßen also als ein Array von Arrays. Nehmen wir beispielsweise an, dass Sie den Schwierigkeitsgrad und die Verbreitung mehrerer Skriptsprachen erfassen wollen. Sie könnten die Daten in einer Tabelle repräsentieren: Sprache Schwierigkeitsgrad Verbreitung PHP einfach verbreitet Python einfach nicht verbreitet Perl schwer verbreitet Mit den folgenden Befehlen können Sie diese Daten in einem PHPArray namens $daten repräsentieren: $daten["PHP"] = Array ("einfach", "verbreitet"); $daten["Python"] = Array ("einfach", "nicht verbreitet"); $daten["Perl"] = Array ("schwer", "verbreitet"); Alternativ könnten Sie den folgenden Befehl verwenden: $daten = array("PHP"=>array("einfach", "verbreitet"), "Python"=>array("einfach", "nicht verbreitet"), "Perl"=>array("schwer", "verbreitet")); 1-Minuten-Test ● Schreiben Sie PHP-Zuweisungsbefehle, die die Namen der additiven Primärfarben (rot, grün und blau) fortlaufend nummerierten Schlüsseln eines Arrays namens $farbe zuweisen. ● $farbe[] = "rot"; $farbe[] = "grün"; $farbe[] = "blau"; 8 170 PHP 4 IT-Tutorial ● Schreiben Sie PHP-Zuweisungsbefehle, die die Werte 100, 1000 und 1000000 mit den Schlüsseln "hundert", "tausend" und "million" eines Arrays namens $massstab verbinden. Ein Array elementweise durchlaufen Nachdem Sie Daten in einem Array gespeichert haben, können Sie mit Hilfe des Schlüssels auf ein Array-Element zugreifen und seinen Wert ändern. Nehmen wir beispielsweise an, dass Sie mit den folgenden Befehlen ein Array erstellt haben: $x[0] = 1; $x[1] = 10; $x[2] = 1000; Dann können Sie mit dem folgenden Befehl beispielsweise auf den Wert des Schlüssels 1 zugreifen: $y = 3 * $x[1]; Auf ähnliche Weise können Sie den Wert des Schlüssels 2 ändern: $x[2] = 100; Manchmal wollen Sie nicht nur ein einzelnes Array-Element ändern, sondern auf mehrere Array-Elemente zugreifen. Nehmen wir beispielsweise an, dass Sie feststellen wollen, ob ein bestimmter Schlüssel oder Wert in dem Array vorhanden ist. Oder nehmen wir an, dass das Array Gehälter repräsentiert und Sie jeden Wert um zehn Prozent erhöhen wollen. Bei solchen Operationen muss das Array elementweise durchlaufen werden. Dieser Vorgang wir auch als Iteration bezeichnet. In diesem Abschnitt wird erklärt, wie sequenzielle und nichtsequenzielle Arrays elementweise durchlaufen werden können. ● $massstab["hundert"] = 100; $massstab["tausend"] = 1000; $massstab["million"] = 1000000; Kapitel 8: Mit Arrays arbeiten 171 Ein sequenzielles Array elementweise durchlaufen Ein Array, dessen Schlüssel aus fortlaufenden Ganzzahlen besteht, wird als sequenzielles Array bezeichnet. Der kleinste Schlüsselwert eines sequenziellen Arrays beträgt im Allgemeinen null. Sie können jedoch sequenzielle Arrays erstellen, deren kleinster Schlüsselwert den Wert eins oder einen anderen ganzzahligen Wert hat. Wenn Sie den kleinsten Schlüsselwert eines sequenziellen Arrays kennen, können Sie das Array mit Hilfe einer for-Schleife elementweise durchlaufen. Zu diesem Zweck initialisieren Sie die Schleifenvariable mit dem kleinsten Schlüsselwert. Mit Hilfe der count()-Funktion bilden Sie den Testausdruck der Schleife. Die count()-Funktion gibt die Anzahl der Elemente in einem Array zurück. Ein einfaches Beispiel einer Array-Iteration sieht so aus: $sprachen = array(0=>"Perl", 1=>"PHP", 2=>"Python"); $obergrenze = count($sprachen); for ($i = 0; $i < $obergrenze; $i++) { echo "<br>$i => $sprachen[$i]"; } Der erste Befehl erstellt das Array. Der zweite Befehl fragt die Anzahl der Elemente in dem Array ab. Der for-Befehl verwendet die Schleifenvariable $i, um das Array elementweise zu durchlaufen. Der Körper dieses Befehls enthält einen echo-Befehl, der den Schlüssel und den Wert jedes Array-Elements ausgibt. Der Output sieht folgendermaßen aus: 0 => Perl 1 => PHP 2 => Python Ein sequenzielles Array durchsuchen Um zu demonstrieren, wozu die Iteration verwendet wird, wollen wir das Problem untersuchen, wie man feststellen kann, ob ein Array einen bestimmten Wert enthält. Ein Beispiel: $sprachen = array(0=>"Perl", 1=>"PHP", 2=>"Python"); $suchbegriff = "PHP"; // Durchsuche das Array $sprachen nach // dem Wert von $suchbegriff $obergrenze = count($sprachen); 8 172 PHP 4 IT-Tutorial for ($i = 0; $i < $obergrenze; $i++) { echo "<br>Übereinstimmung mit $sprachen[$i] prüfen"; if ($suchbegriff == $sprachen[$i]) { echo "<br>$suchbegriff ist eine zulässige Sprache."; } } Der erste Befehl erstellt das Array, das durchsucht werden soll. Natürlich würde das Array in einer echten Iterationsanwendung nicht unmittelbar vor der Suche mit Literalwerten initialisiert werden. Bei einer echten Anwendung ändert sich der Inhalt des Arrays wahrscheinlich laufend. Der zweite Befehl weist der Variablen $suchbegriff den Wert "PHP" zu. In diesem Beispiel soll das Array nach dem Wert durchsucht werden, der in der Variablen $suchbegriff gespeichert ist. Der nächste Befehl nach dem Kommentar fragt die Anzahl der Elemente in dem Array ab und speichert den Wert in der Variablen $obergrenze. Der for-Befehl funktioniert wie vorher, aber sein Körper enthält andere Befehle und führt eine andere Operation aus. Ein echo-Befehl gibt bei jeder Iteration den Wert des aktuellen Array-Elements aus. Der if-Befehl testet jedes Element und gibt eine Nachricht aus, wenn der Wert des Elements dem Wert der Variablen $suchbegriff entspricht. Wenn das Beispiel ausgeführt wird, wird das folgende Ergebnis angezeigt: Übereinstimmung mit Perl prüfen Übereinstimmung mit PHP prüfen PHP ist eine zulässige Sprache. Übereinstimmung mit Python prüfen Der break-Befehl Beachten Sie, dass die Iteration fortgesetzt wird, auch nachdem eine Übereinstimmung gefunden wurde. Wenn Sie ein Array durchsuchen, können Sie die Suche abbrechen, wenn Sie das gewünschte Element gefunden haben. Wenn Sie die Iteration des Arrays fortsetzen, verschwenden Sie nur Computerressourcen, ohne dass sich das Ergebnis ändert. Mit dem break-Befehl können Sie eine Iteration beenden und die einschließende Schleife sofort verlassen. Mit einem breakBefehl sieht die for-Schleife des vorangegangenen Beispiels folgendermaßen aus: for ($i = 0; $i < $obergrenze; $i++) { echo "<br>Übereinstimmung mit $sprachen[$i] prüfen"; if ($suchbegriff == $sprachen[$i]) Kapitel 8: Mit Arrays arbeiten 173 { echo "<br>$suchbegriff ist eine zulässige Sprache."; break; } } Wenn jetzt eine Übereinstimmung gefunden wird, bewirkt der break-Befehl, dass die Schleife beendet wird. Der Output enthält jetzt nicht mehr den überflüssigen Test des Arrays-Elements, das "Python" enthält: Übereinstimmung mit Perl prüfen Übereinstimmung mit PHP prüfen PHP ist eine zulässige Sprache. Der continue-Befehl Der continue-Befehl ist mit dem break-Befehl verwandt. Der continue-Befehl beendet die aktuelle Iteration der Schleife und bewirkt, dass der Schleifenzähler erhöht und der Testausdruck sofort erneut ausgewertet wird. Nehmen wir beispielsweise an, dass Sie das Array $sprachen durchsuchen wollen, um festzustellen, wie viele Sprachen einen kurzen Namen haben, d.h. einen Namen, der aus vier oder weniger Zeichen besteht. Das folgende Beispiel führt die erforderlichen Berechnungen aus: $sprachen = array(0=>"Perl", 1=>"PHP", 2=>"Python"); // Kurze Namen zählen $short = 0; $obergrenze = count($sprachen); for ($i=0; $i<$obergrenze; $i++) { $n = strlen($sprachen[$i]); echo "<br>$sprachen[$i] ist $n Zeichen lang."; if ($n > 4) continue; $short++; } echo "<br>$short Sprachen haben einen kurzen Namen."; Mit einem Zuweisungsbefehl wird der Wert der Variablen $kurz auf null gesetzt. Mit dieser Variablen zählen Sie, wie viele kurze Namen gefunden werden. Der for-Befehl sieht wie vorher aus. Natürlich unterscheidet sich sein Körper von dem letzten Beispiel. Mit der strlen()-Funktion, die die Länge eines Strings zurückgibt, wird der Variablen $n die Länge (d.h. die Anzahl der Zeichen) des Namens der jeweiligen Sprache zugewiesen. Wenn der if-Befehl feststellt, 8 174 PHP 4 IT-Tutorial dass das aktuelle Array-Element eine Sprache mit einem langen Namen enthält, wird der continue-Befehl ausgeführt. Der continue-Befehl bewirkt, dass die Iteration mit dem nächsten Array-Element fortfährt. Wenn es keine weiteren Array-Elemente gibt, wird die for-Schleife beendet. Wenn die Iteration beendet ist, gibt ein echo-Befehl die Anzahl der gefundenen kurzen Sprachnamen aus. Das Ergebnis lautet: Perl ist 4 Zeichen lang. PHP ist 3 Zeichen lang. Python ist 6 Zeichen lang. 2 Sprachen haben einen kurzen Namen. Ein nichtsequenzielles Array elementweise durchlaufen In einigen Programmiersprachen ist es kompliziert, ein nichtsequenzielles Array elementweise zu durchlaufen. PHP 4 verfügt jedoch über einen foreach-Befehl, mit dem derartige Iterationen einfach durchzuführen sind. Der foreach-Befehl hat die folgende allgmeine Form: foreach ($array as $key => $wert) { body } Der Befehl durchläuft automatisch elementweise das Array namens $array und setzt bei jedem Array-Element die entsprechenden Werte von $key und $wert. Ein einfaches Beispiel: $sprachen = array(10=>"Perl", 20=>"PHP", 21=>"Python"); // Das Array elementweise durchlaufen foreach ($sprachen as $index => $sprache) { echo "<br>$index => $sprache"; } Beachten Sie, wie der echo-Befehl einfach die Werte der Variablen $index und $sprache referenziert, die automatisch auf die Werte des aktuellen Schlüssels und Elements gesetzt werden. Das Beispiel erzeugt den folgenden Output: 10 => Perl 20 => PHP 21 => Python Kapitel 8: Mit Arrays arbeiten 175 Frage an den Experten Frage: Wie kann ich ein mehrdimensionales Array elementweise durchlaufen? Antwort: Um diese Frage zu beantworten, wollen wir ein mehrdimensionales Array mit den folgenden Daten elementweise durchlaufen: Sprache Schwierigkeitsgrad Verbreitung PHP einfach verbreitet Python einfach nicht verbreitet Perl schwer verbreitet Das Array kann mit den folgenden PHP-Befehlen erstellt werden: $daten["PHP"] = Array ("einfach", "verbreitet"); $daten["Python"] = Array ("einfach", "nicht verbreitet"); $daten["Perl"] = Array ("schwer", "verbreitet"); Um das Array elementweise zu durchlaufen, werden verschachtelte foreach-Befehle verwendet: foreach ($daten as $sprache => $wert) { foreach ($wert as $key => $eigenschaft) { echo "<br>$sprache: $eigenschaft"; } } Der äußere foreach-Befehl greift auf das Array der einzelnen Sprachen zu; der innere foreach-Befehl durchläuft elementweise die Eigenschaften der jeweiligen Sprache. Das Ergebnis lautet: PHP: einfach PHP: verbreitet Python: einfach Python: nicht verbreitet Perl: schwer Perl: verbreitet 8 176 PHP 4 IT-Tutorial 1-Minuten-Test ● Welcher Befehl wird dazu verwendet, um ein nichtsequenzielles Array elementweise zu durchlaufen? ● Welche Funktion gibt die Anzahl der Elemente in einem Array zurück? ● Mit welchem Befehl wird die aktuelle Iteration einer Schleife beendet? ● Mit welchem Befehl wird eine Schleife sofort abgebrochen? Mit Listenfunktionen arbeiten Neben der Möglichkeit, Arrays elementweise zu durchlaufen, stellt PHP mehrere Funktionen zur Verfügung, mit denen Sie Arrays auf Wunsch vorwärts und rückwärts durchlaufen können. Die grundlegendste dieser Funktionen ist current(), die den Wert des aktuellen Array-Elements zurückgibt. Die aktuelle Funktion verwendet einen speziellen internen Array-Zeiger, den PHP für jedes Array erstellt. Wenn Sie ein Array erstellen, wird der interne Array-Zeiger auf das erste Element des Arrays gesetzt. Die Funktionen next() und prev() ändern den internen Zeiger eines Arrays. Zusammen mit current() können sie verwendet werden, um ein Array zu durchlaufen. Die next()-Funktion setzt – wie der Name suggeriert – den internen Array-Zeiger auf das nächste Element, während die prev()-Funktion den internen Array-Zeiger auf das vorangegangene Element setzt. Das folgende Beispiel zeigt die Arbeitsweise dieser Funktionen: $sprachen = array(10=>"Perl", 20=>"PHP", 21=>"Python"); $current = current($sprachen); echo "<br>Rückgabewert von current(): $current"; $next = next($sprachen); echo "<br>Rückgabewert von next(): $next"; $next = next($sprachen); echo "<br>Rückgabewert von next(): $next"; $prev = prev($sprachen); echo "<br>Rückgabewert von prev(): $prev"; ● ● ● ● foreach count() continue break Kapitel 8: Mit Arrays arbeiten 177 Das Beispiel erzeugt den folgenden Output: Rückgabewert Rückgabewert Rückgabewert Rückgabewert von von von von current(): Perl next(): PHP next(): Python prev(): PHP Beachten Sie, wie prev() und next()dazu verwendet werden, um sich vorwärts und rückwärts durch das Array zu bewegen. Die key()-Funktion Die key()-Funktion ist mit current() verwandt. Während current()den Wert des aktuellen Elements zurückgibt, gibt key() den Schlüssel des aktuellen Elements zurück. Das folgende Beispiel zeigt den Befehl in Aktion: $sprachen = array(10=>"Perl", 20=>"PHP", 21=>"Python"); $current = current($sprachen); $key = key($sprachen); echo "<br>Rückgabewert von current(): $current"; echo "<br>Rückgabewert von key(): $key"; Das Beispiel erzeugt den folgenden Output: Rückgabewert von current(): Perl Rückgabewert von key(): 10 Die each()-Funktion Die each()-Funktion ist eine weitere Funktion, die beim Durchlaufen von Arrays nützlich ist. Die each()-Funktion gibt das aktuelle Schlüssel-Wert-Paar des angegebenen Arrays in Form eines assoziativen Arrays mit vier Elementen zurück, das die folgende Struktur hat: Schlüssel Wert 0 Schlüsselkomponente des aktuellen Schlüssel-Wert-Paars 1 Wertkomponente des aktuellen Schlüssel-Wert-Paars "key" Schlüsselkomponente des aktuellen Schlüssel-Wert-Paars "value" Wertkomponente des aktuellen Schlüssel-Wert-Paars Beachten Sie, dass Sie den Schlüsselwert 0 oder "Schlüssel" verwenden können, um auf den Schlüssel des Schlüssel-Wert-Paars zuzugreifen. Analog können Sie den Schlüsselwert 1 oder "value" verwenden, um auf den Wert des 8 178 PHP 4 IT-Tutorial Schlüssel-Wert-Paars zuzugreifen. Das folgende kurze Beispiel zeigt die each()Funktion in Aktion: $sprachen = array(10=>"Perl", 20=>"PHP", 21=>"Python"); $sprache = each($sprachen); $null = $sprache[0]; $eins = $sprache[1]; $key = $sprache["key"]; $value = $sprache["value"]; echo "<br>null=$null"; echo "<br>eins=$eins"; echo "<br>Schlüssel=$key"; echo "<br>Wert=$value"; Das Beispiel erzeugt den folgenden Output: null=10 eins=Perl Schlüssel=10 Wert=Perl Die list()-Funktion Die list()-Funktion ist noch eine weitere Funktion, die beim Arbeiten mit Arrays nützlich ist. Mit dieser Funktion können Sie in einer einzelnen Zuweisung mehreren Variablen Werte zuweisen. Die list()-Funktion wird häufig zusammen mit each() verwendet, weil es mit der list()-Funktion einfach ist, auf die Schlüssel und Werte separat zuzugreifen, die von each() zurückgegeben werden. Die list()-Funktion hat die folgende allgemeine Form: list($var1, $var2, ..., $varn) = array_wert; Jeder der angegebenen Variablen, $var1 bis $varn, wird ein Wert des Arrays array_wert zugewiesen. In gewisser Weise ist die list()-Funktion das Gegenteil der array()-Funktion: Die list()-Funktion zerlegt ein Array in eine Reihe von skalaren Werten, während die array()-Funktion aus einer Reihe von skalaren Werten ein Array konstruiert. Das folgende Beispiel zeigt die list()-Funktion in Aktion: $sprachen = array(10=>"Perl", 20=>"PHP", 21=>"Python"); list($key,$wert) = each($sprachen); echo "<br>Schlüssel=$key, Wert=$wert"; $next = next($sprachen); echo "<br>next=$next"; Kapitel 8: Mit Arrays arbeiten 179 Das Beispiel erzeugt den folgenden Output: Schlüssel=10, Wert=Perl next=Python 1-Minuten-Test ● Mit welcher Funktion können mehreren Variablen auf einmal Werte zugewiesen werden? ● Welche Funktion gibt die Schlüsselkomponente des Schlüssel-Wert-Paars des aktuellen Array-Elements zurück? ● Welche Funktion erhöht den Wert des internen Array-Zeigers? Frage an den Experten Frage: Enthält PHP noch weitere Funktionen für das Arbeiten mit Arrays? Antwort: Ja, PHP enthält über vier Dutzend Funktionen für das Arbeiten mit Arrays, also viel mehr Funktionen, als in diesem Kapitel beschrieben werden können. Beispielsweise stellt die array_search()-Funktion eine einfache Methode zur Verfügung, um ein Array zu durchsuchen. Informationen über diese und andere Array-Funktionen finden Sie in der PHP-Online-Dokumentation unter http://www.php.net. Arrays sortieren Das Sortieren ist eine weitere übliche Array-Operation. PHP stellt eine Reihe von Funktionen zur Verfügung, die das Sortieren von Arrays vereinfachen. Nehmen wir beispielsweise an, dass Sie das folgende Array erstellen: $sprachen = array(10=>"Perl", 20=>"PHP", 21=>"Python"); Nehmen wir weiter an, dass Sie das Array nach den Namen der Programmiersprachen sortieren wollen. Zu diesem Zweck rufen Sie einfach die sort()-Funktion auf: sort($sprachen); ● list() ● key() ● next() 8 180 PHP 4 IT-Tutorial Nach dem Sortieren erscheinen die Array-Inhalte folgendermaßen: 0 => PHP 1 => Perl 2 => Python Beachten Sie, dass die Schreibweise bei der Sortierreihenfolge eine Rolle spielt. Weil danach das große H vor dem kleinen e eingeordnet wird, steht PHP in dem sortierten Output vor Python. Tabelle 8.1 fasst die PHP-Sortierfunktionen zusammen und zeigt, wie die jeweilige Funktion das Array des vorangegangenen Beispiels sortiert. Operation Funktion Ergebnis Array nach Wert sortiern sort() 0 => PHP 1 => Perl 2 => Python Assoziatives Array nach Wert sortieren asort() 20 => PHP 10 => Perl 21 => Python Array absteigend nach Wert sortieren rsort() 0 => Python 1 => Perl 2 => PHP Assoziatives Array absteigend nach Wert sortieren Arsort() 21 => Python 10 => Perl 20 => PHP Array oder assoziatives Array nach Schlüssel sortieren ksort() 10 => Perl 20 => PHP 21 => Python Array oder assoziatives Array absteigend nach Wert sortieren Krsort() 21 => Python 20 => PHP 10 => Perl Tabelle 8.1 Zusammenfassung der PHP-Sortierfunktionen Frage an den Experten Frage: Nehmen wir an, dass ich eine Suche ausführen möchte, bei der Groß- und Kleinbuchstaben unterschieden werden. Wie kann ich das tun? Antwort: Eine Möglichkeit besteht darin, die natcasesort()-Funktion zu verwenden, die ein Array in einer „natürlichen Reihenfolge“ sortiert, bei der die Schreibweise keine Rolle spielt. Kapitel 8: Mit Arrays arbeiten 181 Eine weitere Möglichkeit besteht darin, die usort()-Funktion oder eine der verwandten Funktionen, uksort() oder uasort(), zu verwenden. Mit diesen Funktionen können Sie eine benutzerdefinierte Sortierfolge definieren. Diese Sortierfolge wird dadurch definiert, dass Sie eine Funktion angeben, die die Werte anhand der gewünschten Sortierfolge vergleicht. Die usort()-Funktion sortiert die Array-Werte und gibt ein sequenzielles Array zurück; die uksort()-Funktion sortiert die ArraySchlüssel; die uasort()-Funktion sortiert ein assoziatives Array. Beispielsweise erstellen die folgenden Befehle ein Array und sortieren es ohne Berücksichtigung der Groß- oder Kleinschreibung: $sprachen = array("Perl", "PHP", "Python"); usort($sprachen, "strcmpcase"); Die strcmpcase()-Funktion ist eine PHP-Library-Funktion, die zwei Strings ohne Berücksichtigung der Groß- oder Kleinschreibung vergleicht. Die Funktion gibt einen negativen Wert zurück, wenn der erste String kleiner als der zweite ist, null, wenn beide Strings gleich sind, oder einen positiven Wert, wenn der erste String größer als der zweite ist. Sie können eine benutzerdefinierte Sortierfolge verwenden, indem Sie eine eigene Funktion schreiben und deren Namen als Argument der usort()- oder einer verwandten Funktion angeben. Schreiben Sie einfach eine Funktion, die zwei Strings als Argumente übernimmt und abhängig vom Ergebnis des Stringvergleichs -1, 0 oder +1 zurückgibt. Weitere Informationen über die usort()-Funktion und ihre verwandten Funktionen finden Sie in der Online-Dokumentation unter http:// www.php.net. 1-Minuten-Test ● Mit welcher Funktion kann ein assoziatives Array in absteigender Reihenfolge sortiert werden? ● Mit welcher Funktion kann ein Array in aufsteigender Reihenfolge nach Schlüsselwerten sortiert werden? ● arsort() ● ksort() 8 182 PHP 4 IT-Tutorial Projekt 8–1: Eine Überarbeitung des Kontaktformulars p-8–1.php p-8–1.html In diesem Projekt werden Sie ein einfaches Beispiel bearbeiten, das eine Array-Iteration und eine Sortierfunktion enthält. Das Projekt greift wieder das E-Mail-Kontaktsystem der vorangegangenen Projekte auf. Das E-Mail-Kontaktformular enthält Felder, in die die Namen der Kinder des Kontakts eingegeben werden können. Dieses Projekt zeigt, wie die Namen alphabetisch sortiert und angezeigt werden können. Projektziele ● Demonstrieren, wie ein Array als Formularvariable verwendet werden kann ● Demonstrieren, wie ein Array elementweise durchlaufen werden kann ● Demonstrieren, wie ein Array sortiert wird Schritt-für-Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen p-8–1.php, und laden Sie diese Datei auf Ihren PHP-Server herauf: <?php foreach ($kinder as $index => $kind) { echo "<br>kind[$index]=$kind"; } echo "<br>"; sort($kinder); foreach ($kinder as $index => $kind) { echo "<br>kind[$index]=$kind"; } ?> 2. Speichern Sie den folgenden HTML-Text unter dem Dateinamen p-8–1.html, und laden Sie diese Datei auf Ihren Server in dasselbe Verzeichnis wie die Datei p8–1.php herauf: <html> <head> <title>Projekt 8–1</title> </head> Kapitel 8: Mit Arrays arbeiten 183 <body> <!-- Datei p-8–1.html --> <form method="POST" action="p-8–1.php"> <h1>Kontaktinformationen</h1> <table> <tr> <td>Namen der Kinder:</td> </tr> <tr> <td><input type="TEXT" name="kinder[]"></td> </tr> <tr> <td><input type="TEXT" name="kinder[]"></td> </tr> <tr> <td><input type="TEXT" name="kinder[]"></td> </tr> <tr> <td><input type="TEXT" name="kinder[]"></td> </tr> <tr> <td><input type="TEXT" name="kinder[]"></td> </tr> </table> <br> <br> <br> <input type="SUBMIT" value="Absenden"> <br> <br> <input type="RESET" value="Formular löschen"> </form> </body> </html> 3. Nehmen Sie sich Zeit, das PHP-Skript zu studieren. Achten Sie insbesondere auf die Namen der Textfelder, die sich auf eine PHP-Array-Variable 8 184 PHP 4 IT-Tutorial beziehen. Sie sollten sich außerdem in dem PHP-Skript genau ansehen, wie die Iteration funktioniert, mit der die Namen der Kinder angezeigt werden. 4. Geben Sie den URL der HTML-Datei, die Sie zuvor heraufgeladen haben, in das Adressfeld Ihres Webbrowsers ein. Die Anzeige des Browsers sollte ähnlich wie Abbildung 8.1 aussehen. Geben Sie Namen in die Felder ein, und klicken Sie dann auf die SUBMIT-Schaltfläche (ABSENDEN). Abbildung 8.1 Das Eingabeformular von Projekt 8–1 5. Wenn das Skript ausgeführt wird, zeigt es die Namen der Kinder in der Reihenfolge an, in der sie eingegeben wurden. Dann sortiert es die Namen und zeigt sie in sortierter Reihenfolge an. Abbildung 8.2 zeigt ein typisches Ergebnis. Kapitel 8: Mit Arrays arbeiten 185 8 Abbildung 8.2 Die Anzeige der Namen in unsortierter und in sortierter Reihenfolge 9Übungsaufgaben 1. Schreiben Sie Befehle, die ein Array namens $pop erstellen, das die Namen mehrerer großer Weltstädte mit ihrer Bevölkerungszahl verbindet. 2. Schreiben Sie einen for-Befehl, der die Elemente eines Arrays namens 3. $dwarfs sequenziell abarbeitet, deren Schlüsselwert mindestens eins beträgt. Der Body (Körper) des for-Befehls sollte den Namen aller Elemente von $dwarfs ausgeben. Achten Sie darauf, dass der Testausdruck die Tatsache berücksichtigt, dass der niedrigste Schlüssel den Wert eins und nicht null hat. 4. Schreiben Sie einen foreach-Befehl, der das Array $states nach einem 5. Element durchsucht, dessen Schlüssel denselben Wert wie die Variable $abbr hat. Geben Sie den Wert, nicht den Schlüssel des entsprechenden Elements aus. 6. Schreiben Sie einen Befehl, der das assoziative Array $pop in aufsteigender Reihenfolge nach Werten sortiert. Kapitel 9 Strings verwenden Lernziele ● Wie mit zusätzlichen Escape-Sequenzen Sonderzeichen in Strings eingebettet werden ● Wie Strings in einfachen Anführungszeichen verwendet werden ● Wie mit ASCII-Codes gearbeitet wird ● Wie formatierter Output erstellt wird ● Wie Strings mit diversen PHP-Stringfunktionen durchsucht und manipuliert werden können 188 PHP 4 IT-Tutorial In Kapitel 2 wurden Strings vorgestellt, der PHP-Datentyp, mit dem Text gespeichert wird. In diesem Kapitel erfahren Sie mehr über das Arbeiten mit Strings. Strings erstellen und anzeigen Bis jetzt haben Sie mehrere Tatsachen über Strings erfahren. Bevor wir uns den fortgeschritteneren Themen zuwenden, wollen wir die Grundlagen noch einmal wiederholen: ● Stringliterale sind Zeichenfolgen, die in doppelte Anführungszeichen eingeschlossen sind. ● Durch so genannte Escape-Sequenzen können Sonderzeichen in einen String eingebettet werden. ● Variablen können den Datentyp string haben. Ihnen kann mit dem Zuweisungsoperator ein Stringwert zugewiesen werden. ● Mit dem Verkettungsoperator (.) können Strings verkettet werden. ● PHP kann einen numerischen Wert automatisch in einen String oder einen Stringwert in eine Zahl umwandeln. Falls Ihnen diese Grundlagen nicht geläufig sind, sollten Sie die entsprechenden Informationen in Kapitel 2 oder Kapitel 5 wiederholen, bevor Sie weiterlesen. Zusätzliche Escape-Sequenzen In Kapitel 2 wurden mehrere Escape-Sequenzen eingeführt, mit denen Sie Sonderzeichen in Strings einbetten können. Darüber hinaus verfügt PHP über zwei Escape-Sequenzen, die in Kapitel 2 nicht beschrieben wurden. Tabelle 9.1 fast alle PHP-Escape-Sequenzen zusammen. Escape-Sequenz Bedeutung \n Zeilenvorschub \r Wagenrücklauf \t Horizontaler Tabulator \\ Backslash \$ Dollarzeichen \“ Doppeltes Anführungszeichen \xxx Das Zeichen des ASCII-Wertes xxx in Form einer Oktalzahl \xnn Das Zeichen des ASCII-Wertes nn in Form einer Hexadezimalzahl Tabelle 9.1 PHP-Escape-Sequenzen Kapitel 9: Strings verwenden Die beiden letzten Escape-Sequenzen in Tabelle 9.1 wurden in Kapitel 2 nicht beschrieben. Jede dieser Escape-Sequenzen verwendet einen ASCII-Code (ASCII = American Standard Code for Information Interchange), um ein Zeichen zu repräsentieren. ASCII-Codes sind Ganzzahlen mit einem Wertebereich von 0 bis 255. Jeder Buchstabe oder jedes Symbol, der bzw. das üblicherweise in westeuropäischen Sprachen verwendet wird, wird durch einen ASCII-Code repräsentiert. Beispielsweise hat der Buchstabe A den ASCII-Code 65, und die Ziffer 1 hat den ASCII-Code 49. Mit der ersten neuen Escape-Sequenz können Sie einen ASCII-Code durch eine Oktalzahl (Basis 8) darstellen, um das zugehörige Zeichen zu repräsentieren. Beispielsweise kann der Dezimalwert 65 (der ASCII-Code für den Buchstaben A) durch die Oktalzahl 101 repräsentiert werden. Deshalb können Sie den Buchstaben A durch die Escape-Sequenz "\101" repräsentieren. Mit der zweiten neuen Escape-Sequenz können Sie einen ASCII-Code durch eine Hexadezimalzahl (Basis 16) darstellen, um das zugehörige Zeichen zu repräsentieren. Beispielsweise kann der Dezimalwert 65 (der ASCII-Code für den Buchstaben A) durch die Hexadezimalzahl 41 repräsentiert werden. Deshalb können Sie den Buchstaben A durch die Escape-Sequenz "\x41" repräsentieren. Falls Ihre Fähigkeiten im Arbeiten mit verschiedenen Zahlensystemen eingerostet sind, hier eine kurze Auffrischung: Der Wert einer Dezimalzahl ist die Summe der Produkte jeder ihrer Ziffern und einer Potenz von zehn. Beispielsweise hat die Dezimalzahl 123 den Wert 1×102 + 2×101 + 3×100 = 1×100 + 2×10 + 3×1. Sie können den Wert einer Zahl, die durch eine andere Basis repräsentiert wird, berechnen, indem Sie in einem Ausdruck wie dem obigen die Basis 10 durch die fragliche Basis ersetzen. Beispielsweise entspricht der Hexadezimalwert 123 dem Dezimalwert 1×162 + 2×161 + 3×160 = 1×256 + 2×16 + 3×1 = 291. Analog dazu entspricht der Oktalwert 123 dem Dezimalwert 1×82 + 2× 81 + 3×80 = 1×64 + 2×8 + 3×1 = 83. Falls Algebra nicht zu Ihren Stärken zählt, müssen Sie nicht verzweifeln: Im folgenden Unterabschnitt erfahren Sie, wie Sie einen Oktal- oder Hexadezimalwert mit Hilfe eines gleichwertigen Dezimalwerts bestimmen können. Mit ASCII-Codes arbeiten Es gibt mehrere PHP-Funktionen, die für das Arbeiten mit ASCII-Codes besonders nützlich sind. Diese Funktionen sind in Tabelle 9.2 zusammengefasst. Das folgende kurze Beispiel zeigt, wie mit der ord()-Funktion der ASCII-Code eines Zeichens ermittelt werden kann: $c = "A"; $n = ord($c); echo "<br>ASCII-Wert von $c: $n"; 189 9 190 PHP 4 IT-Tutorial Der Output dieses Beispiels ist: ASCII-Wert von A: 65 Das folgende Beispiel gibt den Dezimal-, den Oktal- und den Hexadezimalwert der ASCII-Zeichen mit den Codes von 32 bis 127 aus: for ($i=32; $i<128; $i++) { $c = chr($i); $octal = decoct($i); $hex = dechex($i); echo "<br>$i (oktal $octal, hex $hex): $c"; } Der angegebene Wertebereich enthält die druckbaren ASCII-Zeichen. Das folgende Beispiel zeigt einen Teil des Outputs dieses Beispiels: 32 33 34 35 36 (octal (octal (octal (octal (octal 40, 41, 42, 43, 44, hex hex hex hex hex 20): 21): 22): 23): 24): ! " # $ Beachten Sie, dass der ASCII-Code 32 einem Leerzeichen entspricht. Funktion Beschreibung chr(n) Gibt das Zeichen mit dem ASCII-Code n zurück dechex(n) Gibt den Hexadezimalwert des Dezimalwerts n zurück decoct(n) Gibt den Oktalwert des Dezimalwerts n zurück hexdec(n) Gibt den Dezimalwert des Hexadezimalwerts n zurück octdec(n) Gibt den Dezimalwert des Oktalwerts n zurück ord(c) Gibt den ASCII-Code des Zeichens c zurück Tabelle 9.2 Nützliche Funktionen für das Arbeiten mit ASCII-Codes Strings in einfachen Anführungszeichen Wenn Sie wollen, können Sie einen String in einfache statt in doppelte Anführungszeichen einschließen. Ein Grund dafür kann darin bestehen, den Gebrauch doppelter Anführungszeichen in dem String zu vereinfachen. Wenn Sie einen String in doppelte Anführungszeichen einschließen, muss allen doppelten Anführungszeichen, die in dem String vorkommen, ein Backslash-Zeichen (\) vorangestellt werden. Kapitel 9: Strings verwenden 191 Das folgende Beispiel zeigt einen String, der mehrere doppelte Anführungszeichen enthält: "\"Halt\", rief er, \"oder ich schieße!\"" Dieser String kann einfacher in folgender Form geschrieben werden: '"Halt", rief er, "oder ich schieße!"' Strings in einfachen Anführungszeichen verhalten sich anders als Strings in doppelten Anführungszeichen: ● Die einzigen zulässigen Escape-Sequenzen in Strings mit einfachen Anführungszeichen sind \\ und \'. ● Wenn ein String in einfachen Anführungszeichen ausgegeben wird, werden Variablen nicht substituiert. Folglich erzeugen die Befehle $x = "test"; echo 'x ist $x.'; den Output x ist $x. und nicht x ist test. Formatierten Output erstellen PHP verfügt über zwei Funktionen, die nützlich sind, um formatierten Output zu erzeugen: printf() und sprintf(). Die printf()-Funktion gibt ihren Output aus; die sprintf()-Funktion gibt ihren Output als Stringwert zurück. Beide Funktionen haben im Allgemeinen zwei oder mehr Argumente: Das erste Argument ist ein String, der so genannte Formatstring, der das Output-Format festlegt; die restlichen Argumente enthalten die Werte, die ausgegeben werden sollen. Ein einfaches Beispiel für die printf()-Funktion: printf("Der Wert von n ist: %d", $n); 9 192 PHP 4 IT-Tutorial Das folgende Beispiel zeigt ein komplexeres Beispiel, in dem mehrere Argumente mit sprintf() ausgegeben werden: $ergebnis = sprintf("Werte: %d, %f", $n, $x); Der Formatstring besteht aus einer Reihe von gewöhnlichen Zeichen und Direktiven. Als gewöhnliches Zeichen gilt jedes Zeichen, das kein % ist. Gewöhnliche Zeichen werden einfach in den Output kopiert. Direktiven sind Zeichenfolgen, die mit dem Zeichen % beginnen. Sie legen fest, wie die entsprechenden Argumente formatiert werden. Eine einfache Direktive, wie beispielsweise die Direktive in dem vorangegangenen Beispiel, kann aus einem %-Zeichen bestehen, auf das eine Typangabe (beispielsweise d) folgt, die festlegt, dass das Argument als Dezimalzahl behandelt werden soll. Es gibt jedoch komplexere Direktiven, die die folgenden Komponenten in der angegebenen Reihenfolge enthalten können: ● Füllzeichen (optional): Das Füllzeichen legt fest, welches Zeichen verwendet werden soll, um das Ergebnis bis zur gewünschten Stringgröße aufzufüllen. Wenn kein Füllzeichen angegeben wird, wird das Ergebnis mit Leerzeichen aufgefüllt. Das Füllzeichen kann ein Leerzeichen oder eine 0 (Null) sein. Ein Leerzeichen wird gewöhnlich als Füllzeichen für Strings verwendet, während eine Null üblicherweise als Füllzeichen für Zahlen benutzt wird. Andere Füllzeichen können definiert werden, indem dem Zeichen ein einfaches Anführungszeichen (') vorangestellt wird. Um beispielsweise ein Ergebnis mit Unterstreichungszeichen zu füllen, können Sie das Füllzeichen wie folgt definieren: '_. ● Ausrichtungszeichen (optional): Ein Ausrichtungszeichen legt fest, ob das Ergebnis links- oder rechtsbündig ausgerichtet werden soll. Wenn keine Ausrichtung angegeben wird, wird das Ergebnis standardmäßig rechtsbündig ausgerichtet. Wenn ein Bindestrich (-) als Ausrichtungszeichen angegeben wird, wird das Ergebnis linksbündig ausgerichtet. ● Größenangabe (optional): Die Größenangabe ist eine Ganzzahl, die die Mindestanzahl der Zeichen des Ergebnisses festlegt. Wenn das Argument vom Typ double ist, legt die Größenangabe die Mindestanzahl der Zeichen vor dem Dezimalpunkt (Dezimalkomma) fest. Wenn das Ergebnis weniger Zeichen enthält, wird es aufgefüllt. ● Genauigkeit (optional): Die Genauigkeit wird durch einen Dezimalpunkt festgelegt, auf den eine Ganzzahl folgt, die die Anzahl der Dezimalziffern angibt, die in dem Ergebnis angegeben werden sollen. Die Genauigkeit wird nur bei dem Datentyp double berücksichtigt. Kapitel 9: Strings verwenden ● 193 Formatzeichen (erforderlich): Das Formatzeichen legt fest, wie das Argument behandelt und ausgegeben werden soll. In Tabelle 9.3 werden die verfügbaren Formatzeichen zusammengefasst. Formatzeichen Beschreibung b Behandelt das Argument als Ganzzahl und gibt es als binären Wert aus c Behandelt das Argument als Ganzzahl und gibt das Zeichen aus, das zu dem ASCII-Wert des Arguments gehört d Behandelt das Argument als Ganzzahl und gibt es als Dezimalwert aus f Behandelt das Argument als double-Wert und gibt es als Fließkommawert aus o Behandelt das Argument als Ganzzahl und gibt es als Oktalwert aus s Behandelt das Argument als String und gibt es aus x Behandelt das Argument als Ganzzahl und gibt es als Hexadezimalzahl in Kleinbuchstaben aus X Behandelt das Argument als Ganzzahl und gibt es als Hexadezimalzahl in Großbuchstaben aus Tabelle 9.3 PHP-Formatzeichen, die in Formatstrings verwendet werden Wenn Sie ein Prozentzeichen in den Output einer printf()- oder sprintf()-Funktion einfügen wollen, müssen Sie zwei %-Zeichen an der gewünschten Stelle ein fügen. Dann wird das Prozentzeichen nicht als Formatdirektive behandelt. Tabelle 9.4 zeigt die Ergebnisse der Anwendung verschiedener Formatstrings auf ausgewählte Werte. Sehen Sie sich die Tabelle genau an, und vergewissern Sie sich, dass Sie die Arbeitsweise der Steuerzeichen in den Formatstrings wirklich verstehen. Beachten Sie, dass Zahlen automatisch auf- oder abgerundet werden, wenn Dezimalziffern weggelassen werden. Tipp In Tabelle 9.4 werden Einschaltungszeichen (Carets; ^) anstelle von Leerzeichen verwendet, um die Anzahl und die Position von Leerzeichen zu verdeutlichen. Wert Format Ergebnis 100 "%d" 100 100 "%b" 1100100 100 "%o" 144 Tabelle 9.4 Beispiele für die Anwendung verschiedener Formatstrings 9 194 PHP 4 IT-Tutorial Wert Format Ergebnis 100 "%x" 64 100 "%f" 100.000000 12.345 "%'^-10f" 12.345000^^^^^^^^ 12.345 "%'^10f" ^^^^^^^^12.345000 12.345 "%'^-10.2f" 12.35^^^^^^^^ 12.345 "%'10.2f" ^^^^^^^^12.35 „test“ "%'^-10s" test^^^^^^ „test“ "%'^10s" ^^^^^^test Tabelle 9.4 Beispiele für die Anwendung verschiedener Formatstrings Frage an den Experten Frage: Das Formatieren von Zahlen mit printf() und sprintf() scheint ziemlich umständlich zu sein. Gibt es noch eine andere Methode? Antwort: Wenn Sie wollen, können Sie die number_format()-Funktion verwenden, die einen Stringwert zurückgibt, der das formatierte Ergebnis enthält. Sie können die Funktion mit einem, mit zwei oder mit vier Argumenten aufrufen: number_format (zahl) number_format (zahl, dezimalstellen) number_format (zahl, dezimalstellen, dezimalpunktzeichen, tausenderzeichen) Das number-Argument gibt den numerischen Wert an, den Sie formatieren wollen. Das dezimalstellen-Argument legt die gewünschte Anzahl der Dezimalstellen fest. Das dezimalpunktzeichen-Argument legt das Zeichen fest, das als Dezimalpunkt (Dezimalkomma) verwendet werden soll. Das tausenderzeichen-Argument legt das Zeichen fest, das zur Abgrenzung der Tausenderstellen verwendet werden soll. Standardmäßig wird das Ergebnis ohne Dezimalstellen formatiert, Dezimalstellen werden mit einem Punkt (.) abgetrennt und Tausender werden durch ein Komma (,) getrennt. Beispielsweise gibt der Funktionsaufruf number_format(1.234, 2) den folgenden Wert zurück: 1.23 Kapitel 9: Strings verwenden 195 1-Minuten-Test ● Schreiben Sie die Escape-Sequenz, die das Zeichen repräsentiert, dessen ASCII-Wert durch die Oktalzahl 17 angegeben wird. ● Schreiben Sie die Escape-Sequenz, die das Zeichen repräsentiert, dessen ASCII-Wert durch die Hexadezimalzahl 1f angegeben wird. ● Wie heißt die Funktion, die den Hexadezimalwert einer Dezimalzahl zurückgibt? ● Schreiben Sie einen Formatstring, der eine Fließkommazahl mit zwei Dezimalstellen ausgibt. Strings manipulieren PHP stellt über sechs Dutzend Funktionen zur Verfügung, die Strings bearbeiten. Dieser Abschnitt beschreibt mehrere Funktionen, die Sie wahrscheinlich häufig verwenden werden. Mit diesen Funktionen können Sie die Länge eines Strings ermitteln, Whitespace-Zeichen von einem String abschneiden und Zeichen in einem String in Groß- oder in Kleinbuchstaben umwandeln. Die Länge eines Strings ermitteln Die strlen()-Funktion gibt die Länge des Strings zurück, der in ihrem Argument angegeben wird. Ein einfaches Beispiel: $s = "Dies ist ein String."; $n = strlen($s); echo "<br>Die Länge des Strings ist: $n"; Dieses Beispiel erzeugt den folgenden Output: Die Länge des Strings ist: 20 ● ● ● ● "\017" "\x1f" dechex() "%.2f" 9 196 PHP 4 IT-Tutorial Einen String beschneiden Mehrere PHP-Funktionen dienen dazu, Whitespace-Zeichen abzuschneiden, die am Anfang und/oder am Ende eines Strings stehen. Whitespace-Zeichen (Leerzeichen, Tabulatorzeichen, Zeilenvorschubzeichen u.a.) haben keine sichtbare Repräsentation. Tabelle 9.5 fasst diese Funktionen zusammen. Funktion Beschreibung chop(s) Schneidet Whitespace-Zeichen am Ende von s ab und gibt das Ergebnis zurück; dieselbe Funktion wir rtrim() ltrim(s) Schneidet Whitespace-Zeichen am Anfang von s ab und gibt das Ergebnis zurück rtrim(s) Schneidet Whitespace-Zeichen am Ende von s ab und gibt das Ergebnis zurück; dieselbe Funktion wie chop() trim(s) Schneidet Whitespace-Zeichen an beiden Enden von s ab und gibt das Ergebnis zurück Tabelle 9.5 PHP-Funktionen zum Beschneiden von Strings Das folgende Beispiel zeigt diese Funktionen in Aktion: $s = " Dies ist ein String. "; $n = strlen($s); echo "<br>Die Länge des Strings ist: $trim = chop($s); $n = strlen($trim); echo "<br>Die Länge des Strings ist: $trim = ltrim($s); $n = strlen($trim); echo "<br>Die Länge des Strings ist: $trim = rtrim($s); $n = strlen($trim); echo "<br>Die Länge des Strings ist: $trim = trim($s); $n = strlen($trim); echo "<br>Die Länge des Strings ist: $n"; $n"; $n"; $n"; $n"; Dieses Beispiel erzeugt den folgenden Output: Die Die Die Die Die Länge Länge Länge Länge Länge des des des des des Strings Strings Strings Strings Strings ist: ist: ist: ist: ist: 26 23 23 23 20 Kapitel 9: Strings verwenden 197 Strings komplett in Groß- oder Kleinbuchstaben umwandeln Die Funktion strtoupper() wandelt alle Buchstaben des Strings, der in ihrem Argument angegeben wird, in Großbuchstaben um und gibt den Wert zurück. Die komplementäre Funktion strtolower()wandelt alle Buchstaben des Strings in Kleinbuchstaben um. Keine der beiden Funktionen ändert den Wert ihres Arguments; der umgewandelte Wert wird als Ergebnis der Funktion zurückgegeben. Das folgende kurze Beispiel zeigt diese Funktionen in Aktion: $s = "abcd"; $ergebnis = strtoupper($s); echo "<br>strtoupper(\"$s\"): $ergebnis"; $s = "ABCD"; $ergebnis = strtolower($s); echo "<br>strtolower(\"$s\"): $ergebnis"; Dieses Beispiel erzeugt den folgenden Output: strtoupper("abcd"): ABCD strtolower("ABCD"): abcd 1-Minuten-Test ● Welche Funktion gibt die Länge eines Strings zurück? ● Welche Funktion schneidet Whitespace-Zeichen an beiden Enden eines Strings ab? ● Welche Funktion wandelt die Zeichen eines Strings in Kleinbuchstaben um? ● strlen() ● trim() ● strtolower() 9 198 PHP 4 IT-Tutorial Frage an den Experten Frage: Sie haben gesagt, dass PHP über sechs Dutzend Stringfunktionen enthält, aber Sie haben nur einige wenige beschrieben. Wo kann ich mehr über die restlichen Funktionen erfahren? Antwort: Der nächste Abschnitt beschreibt einige PHP-Stringfunktionen, die Strings vergleichen und durchsuchen. Jedoch enthält PHP viel mehr Stringfunktionen, als in diesem Kapitel beschrieben werden können. Wenn Sie mehr über die weiteren Stringfunktionen erfahren wollen, sollten Sie die PHP-Online-Dokumentation unter http://www.php.net heranziehen. Strings vergleichen und durchsuchen Im vorangegangenen Abschnitt haben Sie mehrere PHP-Funktionen kennen gelernt, die Strings manipulieren. In diesem Abschnitt werden mehrere PHPFunktionen beschrieben, mit denen Strings verglichen und durchsucht werden können. Strings vergleichen PHP stellt vier Funktionen für das Vergleichen von Strings zur Verfügung. Diese Funktionen sind in Tabelle 9.6 zusammengefasst. Jede Funktion gibt einen Wert zurück, dessen Vorzeichen das Ergebnis der Vergleichsoperation anzeigt. Dabei sollten Sie nur das Vorzeichen, nicht den tatsächlichen Rückgabewert (seinen Betrag) beachten. Die Funktion strncasecmp() wurde in der PHP-Version 4.0.2 eingeführt. Wenn Sie mit einer älteren Version von PHP arbeiten, steht Ihnen diese Funktion nicht zur Verfügung. Funktion Beschreibung strcmp(s1, s2) Vergleicht zwei Strings unter Berücksichtigung der Groß-/ Kleinschreibung; gibt einen Wert kleiner als null zurück, wenn s1 kleiner als s2 ist, gibt einen Wert größer als null zurück, wenn s1 größer als s2 ist, und gibt andernfalls den Wert null zurück. Tabelle 9.6 PHP-Funktionen zum Vergleichen von Strings Kapitel 9: Strings verwenden Funktion Beschreibung strncmp(s1, s2, n) Vergleicht maximal n Zeichen zweier Strings unter Berücksichtigung der Groß-/Kleinschreibung; gibt einen Wert kleiner als null zurück, wenn s1 kleiner als s2 ist, gibt einen Wert größer als null zurück, wenn s1 größer als s2 ist, und gibt andernfalls den Wert null zurück. Bei dem Vergleich werden maximal n Zeichen verglichen. strcasecmp(s1, s2) Vergleicht zwei Strings ohne Berücksichtigung der Groß-/ Kleinschreibung; gibt einen Wert kleiner als null zurück, wenn s1 kleiner als s2 ist, gibt einen Wert größer als null zurück, wenn s1 größer als s2 ist, und gibt andernfalls den Wert null zurück. strncasecmp(s1, s2, n) Vergleicht maximal n Zeichen zweier Strings ohne Berücksichtigung der Groß-/Kleinschreibung; gibt einen Wert kleiner als null zurück, wenn s1 kleiner als s2 ist, gibt einen Wert größer als null zurück, wenn s1 größer als s2 ist, und gibt andernfalls den Wert null zurück. 199 Tabelle 9.6 PHP-Funktionen zum Vergleichen von Strings Das folgende kurze Beispiel zeigt diese Funktionen in Aktion: $s1 = "abcd"; $s2 = "ABCE"; 9 $ergebnis = strcmp($s1, $s2); echo "<br> Rückgabewert von strcmp: $ergebnis."; $ergebnis = strncmp($s1, $s2, 3); echo "<br>Rückgabewert von strncmp: $ergebnis."; $ergebnis = strcasecmp($s1, $s2); echo "<br>Rückgabewert von strcasecmp: $ergebnis."; // PHP 4.02+ $ergebnis = strncasecmp($s1, $s2, 3); echo "<br>Rückgabewert von strncasecmp: $ergebnis."; Dieses Beispiel erzeugt den folgenden Output: Rückgabewert Rückgabewert Rückgabewert Rückgabewert von von von von strcmp: 1 strncmp: 1 strcasecmp: -1 strncasecmp: 0 200 PHP 4 IT-Tutorial Der Output sagt Ihnen, dass der String "abcd" beim Vergleich mit strcmp() oder mit strncmp()größer als der String "ABCE" ist. Der Grund dafür besteht darin, dass Kleinbuchstaben in der ASCII-Sortierfolge höhere Werte als Großbuchstaben haben. Der Buchstabe A hat den ASCII-Wert 65, während der Buchstabe a den ASCII-Wert 97 hat. Der Output sagt Ihnen auch, dass der String "abcd" beim Vergleich mit strcasecmp() kleiner als der String "ABCE" ist, und dass er beim Vergleich mit strncasecmp() gleich "ABCD" ist. Substrings suchen und extrahieren PHP enthält mehrere Funktionen, mit den Substrings, also Teilstrings eines Strings, gesucht und extrahiert werden können. Tabelle 9.7 fasst die wichtigsten Funktionen dieser Art zusammen: Funktion Beschreibung strchr(s1, s2) Gibt den gesamten Teil von s1 vom ersten Vorkommen von s2 bis zum Ende zurück. Wenn s1 nicht gefunden wird, gibt die Funktion false zurück. Die Funktion strstr() führt dieselbe Operation aus. stristr(s1, s2) Gibt den gesamten Teil von s1 vom ersten Vorkommen von s2 bis zum Ende zurück. Wenn s1 nicht gefunden wird, gibt die Funktion false zurück. Die Strings s1 und s2 werden ohne Rücksicht auf die Groß-/Kleinschreibung verglichen. strpos(s1, s2) Gibt die ganzzahlige Position des ersten Vorkommens von s2 in s1 zurück. Wenn s2 nicht gefunden wird, gibt die Funktion false zurück. strrchr(s1, s2) Gibt den gesamten Teil von s1 vom letzten Vorkommen von s2 bis zum Ende zurück. Wenn s1 nicht gefunden wird, gibt die Funktion false zurück. Nur das erste Zeichen von s2 wird bei der Vergleichsoperation verwendet. strstr(s1, s2) Gibt den gesamten Teil von s1 vom ersten Vorkommen von s2 bis zum Ende zurück. Wenn s1 nicht gefunden wird, gibt die Funktion false zurück. Die Funktion strchr() führt dieselbe Operation aus. substr(s, start) substr(s, start, len) Gibt den Teil von s zurück, der an der mit start angegebenen Position beginnt. Wenn len angegeben wird, wird die entsprechende Anzahl von Zeichen zurückgegeben. Wenn der String kürzer ist, wird der Rest des Strings zurückgegeben. Die erste Position eines Strings hat den Wert null. Tabelle 9.7 PHP-Funktionen zum Suchen und Extrahieren Kapitel 9: Strings verwenden 201 Das folgende einfache Beispiel zeigt diese Funktionen in Aktion: $s = $b = $n = echo "Das Kind steht im Wind."; "ind"; strpos($s, $b); "<br>strpos(\"$s\", \"$b\"): $n"; $s = $b = $r = echo "Das Kind steht im Wind."; "ind"; strchr($s, $b); "<br>strchr(\"$s\", \"$b\"): $r"; $s = $b = $r = echo "Das Kind steht im Wind."; "ind"; strrchr($s, $b); "<br>strrchr(\"$s\", \"$b\"): $r"; $s = "Das Kind steht im Wind."; $ergebnis = substr($s, 4, 4); echo "<br>substr(\"$s\", 4, 4): $ergebnis"; Dieses Beispiel erzeugt den folgenden Output: strpos("Das Kind steht im Wind.", "ind"): 5 strchr("Das Kind steht im Wind.", "ind"): ind steht im Wind. strrchr("Das Kind steht im Wind.", "ind"): ind. substr("Das Kind steht im Wind.", 4, 4): Kind Bei der Funktion strpos() kann es schwierig sein, den Rückgabewert null, der anzeigt, dass der gesuchte Substring am Anfang des Strings gefunden wurde, von dem Rückgabewert false zu unterscheiden, der anzeigt, dass der Substring nicht gefunden wurde. Das folgende kurze Beispiel zeigt, wie Sie den Rückgabewert strpos() testen können, um die Ergebnisse zu unterscheiden: $pos = strpos ($s1, $s2); if ($pos === false) { // Substring nicht gefunden... } Das Verfahren verwendet den Identitätsoperator (===), mit dem Sie bestimmen können, ob der Rückgabewert einem Wert nicht nur arithmetisch gleich, sondern mit ihm identisch ist. Wenn Sie stattdessen den Gleichheitsoperator verwenden, erhalten Sie möglicherweise ein falsches Ergebnis: false hat den nume- 9 202 PHP 4 IT-Tutorial rischen Wert null, also denselben Wert, der zurückgegeben wird, wenn der gesuchte Substring an der ersten Position des durchsuchten Strings steht. Achtung Dieses Verfahren setzt voraus, dass Sie mit der PHP-Version 4.0b3 oder einer neueren Version arbeiten. In älteren Versionen von PHP gab die strpos()Funktion einen Stringwert zurück. Falls Sie mit einer älteren Version von PHP arbeiten, sollten Sie im PHP-Handbuch nach weiteren Informationen über strpos() suchen. Einen Substring ersetzen In Programmen wird häufig eine Operation verwendet, die einen Substring sucht und ihn durch einen anderen Wert ersetzt. PHP verfügt über zwei Funktionen, die für derartige Operationen besonders geeignet sind: str_replace() und substr_replace(). In Tabelle 9.8 sind diese Funktionen zusammengefasst. Beachten Sie, dass die substr_replace()-Funktion den Substring durch seine Position in dem zu durchsuchenden String anzeigt. Funktion Beschreibung str_replace(suchbegriff, ersatzstring, quelle) Durchsucht quelle nach dem Substring suchbegriff. Wenn der Substring gefunden wird, wird das erste Vorkommen von suchbegriff in quelle durch ersatzstring ersetzt und das Ergebnis zurückgegeben. substr_replace(quelle, ersatzstring, start, len) Ersetzt in quelle den Substring, der bei start beginnt und len Zeichen lang ist, durch ersatzstring und gibt das Ergebnis zurück. Tabelle 9.8 PHP-Funktionen zum Ersetzen von Substrings Das folgende Beispiel zeigt diese Funktionen in Aktion: $quelle = "Das Kind steht im Wind."; $suchbegriff = "Kind"; $ersatz = "KIND"; $ergebnis = str_replace($suchbegriff, $ersatz, $quelle); echo "<br>str_replace(\"$suchbegriff\", \"$ersatz\", \"$quelle\"): $ergebnis"; Kapitel 9: Strings verwenden 203 $ergebnis = substr_replace($quelle, $ersatz, 4, 3); echo "<br>substr_replace(\"$quelle\", \"$ersatz\", 4, 3): $ergebnis"; Dieses Beispiel erzeugt den folgenden Output: str_replace("Kind", "KIND", "Das Kind steht im Wind."): Das KIND steht im Wind. substr_replace("Das Kind steht im Wind.", "KIND", 4, 3): Das KINDd steht im Wind. Reguläre Ausdrücke Eine der leistungsstärksten Funktionen von PHP ist seine Fähigkeit, mit so genannten regulären Ausdrücken zu arbeiten. Dabei handelt es sich um eine spezielle Syntax, um eine Mehrzahl von Strings zu beschreiben. Ein regulärer Ausdruck wird häufig dazu verwendet, um festzustellen, ob ein Quellstring einen Substring enthält, der dem regulären Ausdruck entspricht. Später in diesem Unterabschnitt werden Sie erfahren, wie diese Operation ausgeführt wird. Vorher müssen Sie lernen, wie reguläre Ausdrücke gebildet werden. Reguläre Ausdrücke schreiben Nehmen wir beispielsweise an, dass Sie einen String angeben wollen, der an einer bestimmten Stelle den Buchstaben b oder den Buchstaben c enthält. Zu diesem Zweck können Sie den regulären Ausdruck [bc] verwenden. Indem Sie die möglichen Werte in eckige Klammern einschließen, bilden Sie einen regulären Ausdruck, der bedeutet: „Wähle einen dieser Werte aus.“ Nehmen wir jetzt an, dass Sie wollen einen String angeben wollen, der an einer bestimmten Stelle einen beliebigen Vokal enthält. Dann können Sie zu diesem Zweck den regulären Ausdruck [aeiou] benutzen. Wenn Sie auch Großbuchstaben zulassen wollen, können Sie [aeiouAEIOU] verwenden. Wenn Sie einen String angeben wollen, der beliebige Kleinbuchstaben enthält, können Sie den folgenden regulären Ausdruck verwenden: [abcdefghijklmnopqrstuvwxyz] oder auf Deutsch: [abcdefghijklmnopqrstuvwxyzäöü] Alternativ können Sie die kompaktere Form [a-z] (deutsch: [a-zäöüß]) verwenden, bei der eine fortlaufende Reihe von Zeichen durch einen Bindestrich gekennzeichnet wird. 9 204 PHP 4 IT-Tutorial Wenn Sie die Strings "Kind", "Wind" und "Rind" beschreiben wollen, können Sie den regulären Ausdruck [KWR]ind verwenden. Dieser reguläre Ausdruck sagt: „Wähle einen der Buchstaben K, W oder R, gefolgt von den Buchstaben ind.“ Wenn Sie vor dem ersten Symbol innerhalb der eckigen Klammern ein Einschaltungszeichen (Caret; ^) einfügen, wird die Bedeutung des regulären Ausdrucks innerhalb der Klammern umgekehrt. Beispielsweise entspricht der reguläre Ausdruck [^a-z] (deutsch: [^a-zäöüß]) jedem Zeichen, das kein Kleinbuchstabe ist. Um einen regulären Ausdruck anzugeben, der wiederholt werden kann, setzen Sie hinter den regulären Ausdruck ein Paar geschweifter Klammern, die die Unter- bzw. Obergrenze der Anzahl von Wiederholungen enthalten. Beispielsweise entspricht der reguläre Ausdruck [aeiou]{1,4} einem String, der aus einem bis vier Vokalen besteht. Um festzulegen, dass mehrere Teile eines regulären Ausdrucks wiederholt werden sollen, schließen Sie die Teile in Klammern ein. Beispielsweise entspricht der reguläre Ausdruck ([KWR]ind){1,2} einer oder zwei Wiederholungen der Strings "Kind", "Wind" oder "Rind". Einige Wiederholungswerte kommen so häufig vor, dass dafür spezielle Abkürzungen geschaffen wurden: Abkürzung Bedeutung + {1, n}, wobei n eine beliebig große Zahl sein kann * {0, n}, wobei n eine beliebig große Zahl sein kann ? {0, 1} Nehmen wir an, dass Sie eine Multiplikation repräsentieren wollen. Wenn Sie für die Operanden Kleinbuchstaben verwenden, schreiben Sie möglicherweise den folgenden Ausdruck: [a-z]*[a-z]. Jedoch bedeutet dieser reguläre Ausdruck nicht das, was Sie ausdrücken möchten, weil das Zeichen * ein Wiederholungsfaktor und nicht ein Zeichen in dem String ist. Um die spezielle Bedeutung des Zeichens * als Wiederholungsfaktor aufzuheben, müssen Sie ihm einen Backslash voranstellen: [a-z]\*[a-z]. Um einen regulären Ausdruck festzulegen, der nur einem Substring entspricht, der das erste Zeichen eines Quellstrings enthält, stellen Sie dem regulären Ausdruck ein Einschaltungszeichen (Carets; ^) voran. Beispielsweise entspricht der reguläre Ausdruck ^[KWR]ind nur dann den Substrings "Kind", "Wind" oder "Rind", wenn er am Anfang des Quellstrings steht. Analog dazu können Sie festlegen, dass ein regulärer Ausdruck nur einem Substring entspricht, der das letzte Zeichen eines Quellstrings enthält, indem Sie ein Dollarzeichen ($) an den regulären Ausdruck anhängen. Beispielsweise entspricht der reguläre Ausdruck [KWR]ind$ nur dann den Substrings "Kind", "Wind" oder "Rind", wenn er am Ende des Quellstrings steht. Der reguläre Ausdruck Kapitel 9: Strings verwenden 205 ^[KWR]ind$ entspricht nur dann den Substrings "Kind", "Wind" oder "Rind", wenn der Quellstring mit einem dieser Substrings identisch ist. Tipp Neben den bisher beschriebenen Komponenten verfügen reguläre Ausdrücke über weitere Elemente, die nicht alle in einem einzigen Kapitel beschrieben werden können. Selbst das PHP-Online-Handbuch enthält keine komplette Beschreibung regulärer Ausdrücke. Wenn Sie Zugriff auf die Handbuchseiten haben, die mit PHP installiert worden sind, können Sie eine komplette Beschreibung der regulären Ausdrücke in PHP lesen, die mit dem POSIX-Standard 1003.2 kompatibel sind. Der POSIX-Standard selbst ist ein teures Dokument, das dem Copyright unterliegt. Wenn Sie keinen Zugriff auf die PHPMan-Pages oder den POSIX-Standard haben, können Sie unter http:// www.phpbuilder.com ein nützliches Tutorial über reguläre Ausdrücke von Dario F. Gomes finden. Reguläre Ausdrücke verwenden PHP enthält mehrere Funktionen, die mit regulären Ausdrücken arbeiten. Tabelle 9.9 fasst diese Funktionen zusammen. In diesem Unterabschnitt wird die ereg()-Funktion beschrieben; Informationen über die anderen Funktionen finden Sie im PHP-Handbuch. Funktion Beschreibung ereg Prüft die Übereinstimmung mit einem regulären Ausdruck ereg_replace Ersetzt einen Substring, der einem regulären Ausdruck entspricht eregi Prüft die Übereinstimmung mit einem regulären Ausdruck, ohne dass die Groß-/Kleinschreibung eine Rolle spielt eregi_replace Ersetzt einen Substring, der einem regulären Ausdruck entspricht, ohne dass die Groß-/Kleinschreibung eine Rolle spielt split Zerlegt einen String mit Hilfe eines regulären Ausdrucks in ein Array spliti Zerlegt einen String mit Hilfe eines regulären Ausdrucks in ein Array, ohne dass die Groß-/Kleinschreibung eine Rolle spielt sql_regcase Erstellt aus einem String, der einen regulären Ausdruck enthält, einen regulären Ausdruck, bei dem die Groß-/Kleinschreibung keine Rolle spielt Tabelle 9.9 PHP-Funktionen für reguläre Ausdrücke Die einfache Form der ereg()-Funktion hat zwei Argumente: einen String, der einen regulären Ausdruck enthält, und einen Quellstring. Die Funktion gibt 9 206 PHP 4 IT-Tutorial true zurück, wenn der reguläre Ausdruck einem Substring des Quellstrings entspricht; andernfalls gibt sie false zurück. Ein einfaches Beispiel: $muster = "[KWR]ind"; $quelle = "Wo ist das Kind?"; $ergebnis = ereg($muster, $quelle); Die Variable $ergebnis erhält den Wert true, weil der Quellstring den Substring "Kind" enthält, der dem regulären Ausdruck entspricht. Die komplexere Form von ereg() enthält ein drittes Argument – ein Array, das die Substrings aufnimmt, die mit den Teilen des Musters übereinstimmen, die in Klammern gesetzt wurden. Das Projekt dieses Kapitels zeigt, wie diese Form von ereg() verwendet wird. Dort soll mit dieser Funktion festgestellt werden, ob ein String eine korrekt geformte E-Mail-Adresse enthält. Frage an den Experten Frage: In diesem Kapitel wird erklärt, wie formatierter Output erstellt wird. Gibt es eine einfache Methode, um formatierten Input einzulesen („zu scannen“)? Antwort: Die PHP-Funktion sscanf(), die in PHP 4.01 eingeführt wurde, stellt das Gegenstück zu der Funktion printf() dar. Während printf()formatierten Output erzeugt, liest sscanf()einen String ein, interpretiert ihn nach Maßgabe eines Formatstrings und weist den angegebenen Variablen Werte zu, die auf dem Inhalt des Strings basieren. Betrachten Sie das folgende Beispiel: $quelle = "01,31,2005"; $n = sscanf($quelle, "%d,%d,%d", &$monat, &$tag, &$jahr); echo "<br>Es wurden $n Werte gefunden:"; echo "<br>Monat=$monat"; echo "<br>Tag=$tag"; echo "<br>Jahr=$jahr"; Kapitel 9: Strings verwenden 207 Dieses Beispiel erzeugt den folgenden Output: Es wurden 3 Werte gefunden: Monat=1 Tag=31 Jahr=2005 Weitere Informationen über sscanf() finden Sie im PHP-Handbuch. 1-Minuten-Test ● Welche PHP-Funktion durchsucht einen Quellstring nach einem gegebenen Substring, ohne dass die Groß-/Kleinschreibung eine Rolle spielt, und verwendet bei der Suche höchstens eine bestimmte Anzahl von Zeichen? ● Welche PHP-Funktion extrahiert aus einem Quellstring einen Substring, der an einer bestimmten Position beginnt und eine bestimmte Länge hat? ● Schreiben Sie einen regulären Ausdruck, der nur den Substrings "joe", "moe", und "zoe" entspricht, die am Anfang eines Strings stehen. Projekt 9–1: Reguläre Ausdrücke testen p-9–1.php p-9–1.html In diesem Projekt werden Sie eine Seite konstruieren, mit der Sie einen String und einen regulären Ausdruck eingeben können, und den String nach einem Substring durchsuchen, der dem regulären Ausdruck entspricht. Dieses Projekt soll Ihnen helfen, reguläre Ausdrücke besser zu verstehen. Projektziele ● Demonstrieren, wie die ereg()-Funktion verwendet wird ● Demonstrieren, wie die Form der Daten getestet wird, die die Benutzer eingegeben haben ● Demonstrieren, wie die Gültigkeit einer E-Mail-Adresse geprüft wird ● strncmp() ● substr() ● ^[jmz]oe 9 208 PHP 4 IT-Tutorial Schritt für Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen p-9–1.php, und laden Sie diese Datei auf Ihren PHP-Server herauf: <?php echo "<br><b>String:</b>&nbsp;$string"; echo "<br><b>Regulärer Ausdruck:</b>&nbsp;$muster"; if (get_magic_quotes_gpc()) { echo "<br><br>"; echo "<br>Magic-Quotes entfernen..."; $string = stripslashes($string); $muster = stripslashes($muster); echo "<br><b>String:</b>&nbsp;$string"; echo "<br><b>Regulärer Ausdruck:</b>&nbsp;$muster"; } $gefunden = ereg($muster, $string, $treffer); echo "<br><br>"; if ($gefunden) { echo "<br><b>gültig:</b>&nbsp;wahr"; echo "<br><br>"; echo "<br><b>Komponenten:&nbsp</b>"; for ($i = 0; $i < count($treffer); $i++) { echo "<br>$treffer[$i]"; } } else echo "<br><b>gültig:</b>&nbsp;falsch"; ?> 2. Speichern Sie den folgenden HTML-Text unter dem Dateinamen p-9–1.html, und laden Sie diese Datei auf Ihren Server in dasselbe Verzeichnis wie die Datei p-9–1.php herauf: <html> <head> <title>Projekt 9–1</title> </head> <body> <h2>Projekt 9–1: Reguläre Ausdrücke testen</h2> <form method="POST" action="p-9–1.php"> Kapitel 9: Strings verwenden 209 <font face="Courier"> String: <br> <input type="TEXT" name="string"> <br><br> Regulärer Ausdruck: <br> <input type="TEXT" size=64 name="muster" value= "^([_a-zA-Z0–9-]+)@([a-zA-Z0–9-]+(.[a-zA-Z0–9]+)*)$" > <br><br> <br> <input type="SUBMIT"> </font> </form> </body> </html> 3. Nehmen Sie sich Zeit, um das PHP-Skript zu studieren. Beachten Sie den Aufruf der Funktion get_magic_quotes_gpc(). Diese Funktion gibt einen Wert zurück, der der magic_quotes_gpc-Option von PHP entspricht, der von dem PHP-Systemadministrator gesetzt wird. Wenn diese Option gesetzt ist, fügt PHP automatisch Backslashes zu Formularvariablen hinzu, sodass deren Werte in Kontexten verwendet werden können, in denen der Schutz von Sonderzeichen erforderlich ist. Diese Funktion bringt keinen Nutzen, wenn man einen regulären Ausdruck eingibt, anzeigt und verwendet. Deshalb wird in dem Skript, wenn diese Option gesetzt ist, die stripslashes()-Funktion verwendet, um unerwünschte Slashes zu entfernen, die automatisch von PHP hinzugefügt wurden. Um zu sehen, warum dies erforderlich ist, sollten Sie den if-Befehl und seinen Körper aus dem , Skript entfernen und versuchen, das Skript auszuführen. Wenn bei Ihrer PHP-Installation die magic_quotes_gpc-Option gesetzt ist, wird das Skript nicht korrekt funktionieren. 4. Nehmen Sie sich auch Zeit, um die HTML-Seite zu studieren. Achten Sie besonders auf den regulären Ausdruck, der in dem Textfeld namens muster vorgegeben wird. Dieser reguläre Ausdruck beschreibt die ungefähre Form einer E-Mail-Adresse. Jedoch ist die Repräsentation nicht perfekt. Die Suche nach dem perfekten regulären Ausdruck, um gültige E-MailAdressen zu repräsentieren, ähnelt der mittelalterlichen Suche nach dem Heiligen Gral. Reguläre Ausdrücke, die als Kandidaten in Frage kommen, können Sie unter http://www.phpbuilder.com und in dem kommentierten PHP-Handbuch finden. 9 210 PHP 4 IT-Tutorial 5. Geben Sie den URL der HTML-Datei, die Sie vorher heraufgeladen haben, in das Adressfeld Ihres Webbrowsers ein. Geben Sie einen Wert für den String ein. Wenn Sie wollen, können Sie auch den Wert des regulären Ausdrucks ändern. Klicken Sie dann auf die SUBMIT-Schaltfläche (ANFRAGE ABSENDEN). Die Anzeige des Browsers sollte Abbildung 9.1 ähneln. Abbildung 9.1 Das Eingabeformular von Projekt 9–1 6. Wenn das Skript ausgeführt wird, versucht es, den regulären Ausdruck mit einem Substring des Strings abzugleichen und das Ergebnis anzuzeigen. Abbildung 9.2 zeigt ein typisches Ergebnis: Kapitel 9: Strings verwenden 211 9 Abbildung 9.2 Die Anzeige von Projekt 9–2 212 PHP 4 IT-Tutorial 9Übungsaufgaben 1. Schreiben Sie einen Formatstring, der einen linksbündig ausgerichteten Stringwert festlegt, der 24 Stellen lang ist und auf den nach einem Leerzeichen ein linksbündig ausgerichteter double-Wert mit zwei Dezimalstellen folgt. 2. Schreiben Sie eine Fluchtsequenz, die das Zeichen repräsentiert, dessen ASCII-Wert oktal 45 beträgt. 3. Schreiben Sie einen Funktionsaufruf und eine Zuweisung, der bzw. die die Whitespace-Zeichen am Anfang und Ende von $s entfernt und $r den Wert von $s zuweist. 4. Schreiben Sie einen Funktionsaufruf, der einen String zurückgibt, der dem String $s ähnelt, aber bei dem – beginnend mit Position i – n Zeichen durch den String $r ersetzt sind. 5. Schreiben Sie einen regulären Ausdruck, der nur den Substrings "axb", "ayb" und "azb" am Ende eines Strings entspricht. Teil III Mit gespeicherten Daten arbeiten Kapitel 10 Mit Cookies arbeiten Lernziele ● Wie Cookies funktionieren ● Wie Cookies erstellt, benutzt und gelöscht werden ● Wie mehrere Werte in einem Cookie gespeichert werden ● Wie Cookie-Optionen festgelegt werden 216 PHP 4 IT-Tutorial In diesem Kapitel erhalten Sie eine Einführung in Cookies, eine HTTP-Funktion, die es möglich macht, Daten auf dem System eines Benutzers zu speichern. Cookies eignen sich dazu, Präferenzen von Benutzern und andere Informationen zu speichern, die aufbewahrt werden sollten, wenn der Benutzer zu einer anderen Seite des Browsers weitergeht. Auf Cookies zugreifen und Cookies erstellen Der Werte der meisten Variablen verschwinden, wenn das PHP-Skript beendet wird, in dem sie enthalten sind. Im Gegensatz dazu sind Cookies Variablen, deren Werte unbegrenzt lange aufbewahrt werden können. Um ihre Werte dauerhaft speichern zu können, speichert der Browser des Benutzers Cookies auf der lokalen Festplatte des Benutzers. Cookies erfüllen eine Reihe nützlicher Funktionen. Beispielsweise verwenden viele Websites Cookies, um die Identität und Präferenzen des Benutzers zu speichern. Wenn der Benutzer zu der Website zurückkehrt, kann der Browser anhand von Cookies den Benutzer wiedererkennen und die Site-Optionen wiederherstellen, die der Benutzer bei einem früheren Besuch gewählt hatte. Leider sind Cookies nicht die perfekte Lösung für eine dauerhafte Speicherung. Sie sind unter anderem den folgenden Beschränkungen unterworfen: ● Ein Benutzer kann Cookies deaktivieren, indem er die entsprechende Browseroption einstellt. ● Unter gewissen Umständen können fremde Personen die Daten in den Cookies eines Benutzers lesen. ● Eine Site kann nur zwanzig Cookies und nur 4 KB Informationen auf der lokalen Festplatte des Benutzers speichern. ● Mehrere Versionen der gebräuchlichen Browser haben Fehler, die Ihre Fähigkeit beeinträchtigen, mit Cookies korrekt zu arbeiten. Trotz dieser Einschränkungen bleiben Cookies das gebräuchlichste Verfahren, um Daten dauerhaft zu speichern. Deshalb ist es wichtig zu verstehen, wie sie funktionieren und wie sie eingesetzt werden. Auf ein Cookie zugreifen Die vielleicht beste Eigenschaft, mit der man Cookies charakterisieren kann, ist Bequemlichkeit. Wenn Sie ein Cookie erstellt haben, wird der Wert des Cookies Kapitel 10: Mit Cookies arbeiten 217 automatisch als PHP-Variable zur Verfügung gestellt, die denselben Namen wie das Cookie hat. Nehmen wir beispielsweise an, dass Sie ein Cookie namens frucht erstellen und ihm den Wert banane zuweisen. Dieses Name-Wert-Paar steht dann jedem PHP-Skript zur Verfügung, das mit Ihrer Website verbunden ist. Deshalb können Sie den Wert des Cookies mit einem einfachen echo-Befehl ausgeben: echo "Der Wert des Cookies ist $frucht."; Dieser Befehl erzeugt den folgenden Output: Der Wert des Cookies ist banane. Die PHP-Variable $_COOKIE bezeichnet ein assoziatives Array, das die Namen und Werte jedes aktuellen Cookies enthält. Wenn Sie alle verfügbaren Cookies und ihre Werte sehen wollen, können Sie die phpinfo()-Funktion aufrufen, das die Werte des $_COOKIE-Arrays ausgibt. Wenn Sie per Programm auf das Array zugreifen wollen, können Sie beispielsweise den folgenden Code verwenden: foreach ($_COOKIE as $Name => $Wert) echo "<br>$Name => $Wert"; Ein Cookie erstellen Ein Cookie zu erstellen ist fast so einfach, wie auf ein Cookie zuzugreifen. Zu diesem Zweck wird die setcookie()-Funktion aufgerufen, die die folgende Form hat: setcookie(name, wert, ablauf) Das name-Argument legt den Namen des Cookies fest, und das wert-Argument bestimmt seinen Wert. Das ablauf-Argument weist dem Cookie einen Zeitpunkt zu, an dem es abläuft. Nach diesem Zeitpunkt kann nicht mehr auf das Cookie zugegriffen werden. Im Allgemeinen kann der Ablaufzeitpunkt bequem dadurch festgelegt werden, dass die time()-Funktion aufgerufen und zu ihrem Rückgabewert ein Offsetwert addiert wird. Die time()-Funktion gibt die Anzahl der Sekunden zurück, die seit dem 1. Januar 1970 abgelaufen sind. Der Offsetwert gibt die Zeitdauer an, für die das Cookie verfügbar sein soll. Betrachten Sie beispielsweise den folgenden Befehl: setcookie("frucht", "banane", time()+3600); 10 218 PHP 4 IT-Tutorial Dieser Befehl erstellt ein Cookie namens frucht, das den Wert banane hat. Das Cookie wird nach seiner Erstellung für eine Stunde (3600 Sekunden) zur Verfügung stehen. Wenn Sie wollen, können Sie den Ablaufzeitpunkt mit der mktime()-Funktion einstellen. Diese Funktion hat die folgende Form: mktime(stunde, minute, sekunde, monat, tag, jahr) Beispielsweise erstellt der folgende Befehl ein Cookie, das am Neujahrstag 2005 eine Sekunde nach Mitternacht abläuft: setcookie("frucht", "banane", mktime (0,0,1,1,1,2005)); Achtung Cookie-Werte werden von dem Browser als Teil des HTTP-Header übertragen. Deshalb müssen Cookie-Werte gesetzt werden, bevor Output an den Browser gesendet wird. Selbst wenn nur ein einzelnes Leerzeichen gesendet wird, können Sie keinen Cookie-Wert mehr übertragen. Um Probleme zu vermeiden, sollten Sie darauf achten, dass ein PHP-Skript, das einen Cookie-Wert setzt, ohne voranstehende Whitespace-Zeichen ganz am Anfang der Datei steht. Außerdem sollten Sie den Cookie-Wert setzen, bevor Sie einen echo- oder einen anderen PHP-Befehl ausführen, der Output an den Browser sendet. Frage an den Experten Frage: Was ist ein HTML-Header? Antwort: Bevor ein Webserver HTML-Daten an einen Browser überträgt, sendet er im Allgemeinen einen oder mehrere HTTP-Header; diese Header werden als Server-Response-Header bezeichnet. Auf ähnliche Weise sendet ein Webbrowser, bevor er Informationen an einen Webserver überträgt, im Allgemeinen einen oder mehrere HTTP-Header. Diese Header werden als Request-Header bezeichnet. Üblicherweise beschreiben ServerResponse-Header die Konfiguration des Servers und stellen Informationen über den URL zur Verfügung, der von dem Client angefordert wurde. Im Gegensatz dazu beschreiben Request-Header normalerweise die Konfiguration des Clients und die Datenformate, die der Client verarbeiten kann. Kapitel 10: Mit Cookies arbeiten 219 Zusätzlich zu den Server-Response-Headern und den Request-Headern verwendet das HTTP-Protokoll so genannte General-Header und Entity-Header. General-Header werden sowohl von Clients als auch von Servern verwendet, um Informationen, wie beispielsweise das aktuelle Datum und Verbindungsoptionen, anzugeben. Entity-Header beschreiben das Format von Daten, die zwischen einem Client und Server ausgetauscht werden. Ein Cookie löschen Weil ein Cookie einen Ablaufzeitpunkt hat, wird es einige Zeit nach seiner Erstellung automatisch gelöscht. Sie können jedoch ein Cookie sofort löschen. Setzen Sie zu diesem Zweck den Ablaufzeitpunkt des Cookies auf einen Zeitpunkt in der Vergangenheit. Um beispielsweise ein Cookie namens frucht zu löschen, können Sie den folgenden Befehl verwenden: setcookie("frucht", "", time()-3600); Dieser Befehl setzt den Ablaufzeitpunkt des Cookies auf einen Zeitpunkt, der eine Stunde (3600 Sekunden) in der Vergangenheit liegt. Beachten Sie, dass der Wert des Cookies als leerer String angegeben wird. Da das Cookie nicht mehr zur Verfügung stehen wird, spielt sein Wert keine Rolle. 1-Minuten-Test ● Welche PHP-Variable enthält den Namen aller verfügbaren Cookie-Variablen? ● Welche Funktion dient dazu, ein Cookie zu erstellen? ● Welche Funktion dient dazu, ein Cookie zu löschen? Fortgeschrittene Cookie-Verfahren In diesem Abschnitt werden einige fortgeschrittene Verfahren für das Arbeiten mit Cookies erklärt. Der erste Unterabschnitt erklärt, wie mehr als zwanzig Werte in einem einzigen Cookie gespeichert werden können. Der zweite Unterabschnitt erklärt, wie in der setcookie()-Funktion mehrere zusätzliche Argumente verwendet werden können. ● $_COOKIE ● setcookie() ● setcookie() 10 220 PHP 4 IT-Tutorial Mehrere Werte in einem Cookie speichern Weil eine Website nur zwanzig Cookies auf dem System eines Benutzers speichern kann, ist es nützlich, wenn in einem einzelnen Cookie mehrere Werte gespeichert werden können. Laut PHP-Online-Handbuch ist dies möglich, wenn ein Array als Name des Cookies angegeben wird. Beispielsweise könnten Sie den folgenden Code verwenden: // fehlerhaftes Beispiel-Cookie mit mehreren Werten for ($i=0; $i<30; $i++) { setcookie("cookies[$i]", "$i"); } if (isset($cookies)) { foreach ($cookies as $i => $cookie) { echo "<br>$i => $cookie"; } } Leider funktioniert dieses Verfahren nicht. Im Gegensatz zu den Informationen in dem PHP-Handbuch wird jedes Array-Element in einem separaten Cookie gespeichert. Deshalb können Sie mit diesem Verfahren nicht mehr als zwanzig Werte speichern. Andererseits ist es möglich, mehrere Werte in einem einzelnen Cookie zu speichern. Zu diesem Zweck können Sie die Werte in einem Array speichern und dann die Elemente des Arrays mit der serialize()-Funktion in einen String packen. Später können Sie die Werte des Arrays mit der unserialize()-Funktion wiedergewinnen. Das folgende Beispiel zeigt, wie ein Cookie mit mehreren Werten erstellt wird und wie man darauf zugreifen kann: // Ein Array erstellen for ($i = 0; $i < 30; $i++) { $array[$i]=$i; } // Das gesamte Array in einen String packen $s=serialize($array); // Ein Cookie erstellen und seinen Wert setzen setcookie("cookies", $s); Kapitel 10: Mit Cookies arbeiten 221 if (isset($cookies)) { // Wert des Cookies entpacken $array = unserialize(stripslashes($cookies)); // Zeigen, dass alles in Ordnung ist, // indem die Array-Elemente ausgegeben werden foreach ($array as $i => $cookie) { echo "<br>$i => $cookie"; } } Die stripslashes()-Funktion wird aufgerufen, um Escape-Zeichen zu entfernen, die dem String hinzugefügt wurden, als der Wert des Cookies von PHP zurückgegeben wurde. Achtung Obwohl mit diesem Verfahren die Beschränkung von zwanzig Cookies umgangen werden kann, kann damit nicht die 4-KB-Grenze für den Umfang der Cookie-Daten pro Website überwunden werden. Wenn Sie mehr als 4 KB Daten speichern wollen, müssen Sie die Daten in einer serverseitigen Datenbank oder in anderer Form als in einem Cookie speichern. Den Zugriff auf ein Cookie und andere Optionen festlegen Die setcookie()-Funktion hat bis zu sechs Argumente, einschließlich dreier Argumente, die noch nicht beschrieben wurden. Das komplette Format der setcookie()-Funktion lautet: setcookie(name, wert, ablauf, pfad, domaene, sicher) Die Argumente name, wert und ablauf wurden im vorangegangenen Abschnitt dieses Kapitels beschrieben. Mit dem pfad-Argument können Sie den URL-Pfad festlegen, der mit dem Cookie verbunden ist. Standardmäßig steht das Cookie den Skripts zur Verfügung, die sich in dem Verzeichnis befinden, welches das Skript enthält, in dem das Cookie definiert wurde, sowie den Skripts, die sich Unterverzeichnissen dieses Verzeichnisses befinden. Insbesondere haben Skripts, die sich im übergeordneten Verzeichnis des Verzeichnisses befinden, das das Skript enthält, 10 222 PHP 4 IT-Tutorial standardmäßig keinen Zugriff auf das Cookie. Um das Cookie den Skripts zur Verfügung zu stellen, die sich in einem bestimmten Verzeichnis und seinen Unterverzeichnissen befinden, geben Sie in dem pfad-Argument den Pfad zu diesem Verzeichnis an. Um das Cookie beispielsweise im gesamten Verzeichnisbaum verfügbar zu machen, geben Sie "/" als Wert des pfad-Arguments an. Um das Cookie in dem /~test-Verzeichnis und dessen Unterverzeichnissen verfügbar zu machen, geben Sie "/~test/" als Wert des pfad-Arguments an. Achtung Eine Schwierigkeit beim Einsatz das pfad-Arguments besteht in der Art und Weise, wie Verzeichnisnamen interpretiert werden. Wenn "/~test/" als Wert des pfad-Arguments angegeben wird, wird das Cookie zusätzlich zu dem Verzeichnis /~test in den Verzeichnissen /~test1, /~test2 und ähnlich benannten Verzeichnissen sowie deren Unterverzeichnissen zugänglich gemacht. Wenn kein domaene-Argument angegeben wird, ist ein Cookie nur für Skripts verfügbar, die sich auf dem Webserver befinden, auf dem das Cookie erstellt wurde. Mit dem domaene-Argument können Sie den Domänennamen angeben, der mit einem Cookie verbunden ist. Das Cookie steht dann nur den Websites in der angegebenen Domäne zur Verfügung. Nehmen wir beispielsweise an, dass ein Skript auf dem Webserver http://www.subdomain.domain.com ein Cookie erstellt. Standardmäßig steht das Cookie nur auf diesem Host zur Verfügung. Sie können das Cookie jedoch der gesamten Domäne subdomain.domain.com zur Verfügung stellen, indem Sie "subdomain.domain.com" als Wert des domaeneArguments angeben. Tipp Die Cookie-Spezifikation von Netscape (http://www.netscape.com/ erfordert, dass das domaene-Argument wenigstens zwei Punkte enthält. Deshalb sollten Sie nicht einen String wie beispielsweise "domain.com" als Wert des domaene-Arguments angeben. newsref/std/cookie_spec.html) Das sicher-Argument ist eine Ganzzahl, die festlegt, ob das Cookie nur über eine sichere (HTTPS-)Verbindung gesendet werden darf. Geben Sie den Wert 1 an, wenn das Cookie nur über eine sichere Verbindung übertragen werden darf. Wenn das Cookie auch über gewöhnliche HTTP-Verbindungen gesendet werden darf, geben Sie den Wert 0 an. Kapitel 10: Mit Cookies arbeiten 223 Frage an den Experten Frage: Wenn jeder, der Zugriff auf die Festplatte des Benutzers hat, die Werte lesen kann, die in einem Cookie gespeichert sind, wie kann ich dann die Cookie- Informationen geheim halten? Antwort: Weil Browser Cookies auf der lokalen Festplatte speichern, können Benutzer eines Systems möglicherweise auf Cookie-Dateien zugreifen und diese lesen oder sogar deren Inhalt ändern. Eine Möglichkeit, um dies zu verhindern, besteht darin, die Daten zu verschlüsseln, die in den Cookies gespeichert sind. Zu diesem Zweck können Sie die Mcrypt-Funktionen von PHP verwenden. Diese Funktionen sind in der libmcrypt-Library enthalten, die nicht zur Standardinstallation von PHP gehört. Deshalb müssen Sie möglicherweise Ihren Systemadministrator bitten, die Library zu installieren und PHP so zu konfigurieren, dass Sie auf die Library zugreifen können. Unter http://www.php.net finden Sie weitere Informationen über die Installation und den Einsatz der McryptFunktionen. Achtung Obwohl die ablauf- und pfad-Argumente von setcookie()optional sind, enthalten einige Versionen führender Browser Bugs, die zur Folge haben, dass sie Cookies ablehnen, wenn diese Argumente nicht angegeben werden. Deshalb sollten Sie im Allgemeinen diese Argumente angeben. 1-Minuten-Test ● Wie viele Werte können in einem Cookie gespeichert werden? ● Mit welcher Funktion kann ein Array codiert werden, damit mehrere Werte in einem Cookie gespeichert werden können? ● Welchen Wert sollte das sicher-Argument der setcookie()-Funktion haben, um festzulegen, dass ein Cookie nur über eine sichere (HTTPS-) Verbindung übertragen werden sollte? ● 20 ● serialize() ● 1 10 224 PHP 4 IT-Tutorial Projekt 10–1: Eine Login-Seite In diesem Projekt werden Sie eine HTML-Seite und ein PHP-Skript schreip-10–1.php ben, mit denen sich ein Benutzer bei einem System einloggen (anmelden) p-10–1.html kann. Die Seite ermöglicht es dem Benutzer, eine Benutzer-ID und ein Passwort einzugeben, die von dem Skript anhand eines gespeicherten Satzes von gültigen Benutzer-IDs und Passwörtern authentifiziert werden. Wenn der Benutzer erfolgreich authentifiziert wird, erstellt das Skript ein Cookie, das folgenden Skripts mitteilt, dass der Benutzer authentifiziert worden ist. Projektziele ● Demonstrieren, wie Cookies angewendet werden ● Zeigen, wie eine einfache Login-Seite und ein Login-Skript erstellt werden Schritt für Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen p-10– 1.php, und laden Sie diese Datei auf Ihren PHP-Server herauf: <?php $passwoerter = array( "bill" =>"apple", "charles"=>"potato", "david" =>"igneous"); if ($passwort == $passwoerter[$benutzername]) { setcookie("benutzername", $benutzername, time() + 1200); echo "<h2>Zugang gewährt.</h2>"; } else { setcookie("benutzername", "", time()-3600); echo "<h2>Benutzername oder Passwort ungültig: "; echo "Zugang verweigert.</h2>"; } ?> Kapitel 10: Mit Cookies arbeiten 225 2. Speichern Sie den folgenden HTML-Text unter dem Dateinamen p-10– 1.html, und laden Sie diese Datei auf Ihren Server in dasselbe Verzeichnis wie die Datei p-10–1.php herauf: <html> <head> <title>Projekt 10–1</title> </head> <body> <form method="POST" action="p-10–1.php"> <h2>Projekt 10–1: Eine Login-Seite</h2> <br><br> Benutzername: <br><input type="TEXT" name="benutzername" size="16"> <br><br> Passwort: <br><input type="PASSWORT" name="passwort" size="16"> <br><br> <br><br> <input type="SUBMIT" value="Absenden"> </form> </body> </html> 3. Nehmen Sie sich Zeit, um das PHP-Skript zu studieren. Beachten Sie, dass es die Eingaben des Benutzers anhand der Werte authentifiziert, die in einem Array gespeichert sind. Bei einer echten Anwendung würden die gültigen Werte wahrscheinlich in einer Datenbank gespeichert sein. In einem der folgenden Kapitel werden Sie lernen, mit Datenbanken zu arbeiten. 4. Beachten Sie auch, dass der Ablaufzeitpunkt des Cookies auf zwanzig Minuten gesetzt worden ist. Nachfolgende Skripts können den Ablaufzeitpunkt des Cookies neu setzen, sodass die Authentifizierung des Benutzers nicht während seiner Arbeit aufgehoben wird. Wenn der Benutzer jedoch das System verlässt, garantiert der Ablaufzeitpunkt des Cookies, dass der Benutzer automatisch nach zwanzig Minuten ausgeloggt wird. Dies hilft, Sicherheitsverletzungen zu vermeiden, die daher rühren, dass Benutzer ihren Arbeitsplatz verlassen, während sie eingeloggt sind. 5. Geben Sie den URL der HTML-Datei, die Sie zuvor heraufgeladen haben, in das Adressfeld Ihres Webbrowsers ein. Die Anzeige des Browsers sollte ähnlich wie Abbildung 10.1 aussehen. Geben Sie eine Benutzer-ID und ein Passwort ein, und klicken Sie dann auf die SUBMIT-Schaltfläche (ABSENDEN). 10 226 PHP 4 IT-Tutorial Abbildung 10.1 Das Eingabeformular von Projekt 10–1 6. Das Skript prüft die Daten, die Sie eingegeben haben. Wenn Sie eine gültige Benutzer-ID und ein gültiges Passwort eingegeben haben, sollten Sie eine Anzeige wie in Abbildung 10.2 sehen; andernfalls sollten Sie eine Fehleranzeige sehen. Abbildung 10.2 Die Anzeige bei gültigen Eingaben Kapitel 10: Mit Cookies arbeiten 227 9Übungsaufgaben 1. Schreiben Sie einen PHP-Befehl, der ein Cookie namens correct erstellt, das den Wert "false" hat und das nach 30 Minuten abläuft. 2. Schreiben Sie einen PHP-Befehl, der ein Cookie namens bygone löscht. 3. Schreiben Sie einen PHP-Befehl, der den Wert eines Cookies namens age ausgibt. 4. Schreiben Sie einen PHP-Befehl, der ein Array namens $inhalte in einen String namens $x packt. 5. Schreiben Sie einen PHP-Befehl, der ein Cookie namens woimmer erstellt, das den Wert "hier" hat. Das Cookie sollte nach 30 Minuten ablaufen und in jedem Verzeichnis des Web-Verzeichnisbaums zugänglich sein. 10 Kapitel 11 Mit Dateien und Verzeichnissen arbeiten Lernziele ● Wie das UNIX-Dateisystem funktioniert ● Wie Informationen über Dateien und Verzeichnisse abgefragt werden können ● Wie Dateien gelesen und geschrieben werden ● Wie Datei- und Verzeichnisberechtigungen gesetzt werden ● Wie Dateien heraufgeladen, kopiert, umbenannt und gelöscht werden ● Wie Verzeichnisse erstellt und gelöscht werden ● Wie Verzeichnisse gelesen und gewechselt werden 230 PHP 4 IT-Tutorial In diesem Kapitel werden die PHP-Funktionen für das Arbeiten mit Dateien und Verzeichnissen beschrieben. Dateien und Verzeichnisse ermöglichen es Ihnen, Daten auf dem Server zu speichern, um sie aufzubewahren und für mehrere Benutzer zur Verfügung zu stellen. Das UNIX-Dateisystem Um zu verstehen, wie man in PHP mit Dateien und Verzeichnissen arbeitet, müssen Sie das UNIX-Dateisystem verstehen. Dies gilt auch, wenn Sie PHP unter Microsoft Windows einsetzen, weil das Modell von PHP, das dem Arbeiten mit Dateien und Verzeichnissen zugrunde liegt, auf UNIX basiert. In diesem Abschnitt wird erklärt, wie das UNIX-Dateisystem aufgebaut ist und wie Dateien und Verzeichnisse mit UNIX-Befehlen manipuliert werden. Wenn Sie unter Microsoft Windows arbeiten, werden die Befehle, die in diesem Abschnitt beschrieben werden, im Allgemeinen nicht funktionieren. Jedoch werden Sie unter Windows wahrscheinlich eher den Windows Explorer als DOS benutzen, um Dateien und Verzeichnisse zu bearbeiten. Deshalb müssen Sie wahrscheinlich nicht die DOS-Befehle kennen, die den UNIX-Befehlen ähneln, die in diesem Abschnitt erklärt werden. Tipp Um mit Dateien und Verzeichnissen arbeiten zu können, müssen Sie bei dem System eingeloggt sein, auf dem sich diese Dateien und Verzeichnisse befinden. Wenn Sie keinen Zugang zu einer lokalen Konsole haben, können Sie möglicherweise per Telnet oder SSH, zwei gebräuchlichen Internet-Protokollen, auf das System zugreifen. Fragen Sie den Administrator des Systems, um zu erfahren, wie Sie auf die Dateien und Verzeichnisse des Systems zugreifen können. Mit UNIX-Dateien arbeiten Eine Datei besteht aus einer Reihe von Bytes, die auf einer Festplatte, auf einer CD-ROM oder auf einem anderen Medium gespeichert sind. Dateien haben Namen, damit sie bequem referenziert werden können. Ein UNIX-Dateiname kann fast beliebig lang sein und fast jedes Zeichen enthalten. Dennoch ist es praktischer, Dateinamen zu verwenden, die so kurz sind, dass sie leicht eingetippt werden können und nur sichtbare Zeichen enthalten, die in der UNIX-Shell keine spezielle Bedeutung haben. Im Gegensatz zu Dateinamen unter Microsoft Windows spielt bei UNIX-Dateinamen die Schreibweise eine Rolle. Deshalb beziehen sich a und A auf verschiedene UNIX-Dateien. Um Probleme – insbe- Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 231 sondere beim Übertragen von Dateien zwischen UNIX und Windows – zu vermeiden, sollten Sie in Dateinamen Kleinbuchstaben, Ziffern, Punkte, Unterstreichungszeichen und Bindestriche verwenden. Außerdem sollten die Dateinamen mit einem Kleinbuchstaben oder einer Ziffer beginnen. Hinweis Ein Byte ist etwa dasselbe wie ein Zeichen. Jedoch ist es bei manchen menschlichen Sprachen, deren Alphabet viele Zeichen umfasst, erforderlich, ein einziges Zeichen durch mehrere Bytes zu repräsentieren. Häufig spielt dieser Unterschied keine Rolle. Dateiinformationen anzeigen Um Informationen anzuzeigen, die eine Datei beschreiben, geben Sie den Befehl ls -l dateiname wobei dateiname für den Namen der Datei steht. Abbildung 11.1 zeigt den typischen Output des ls-Befehls. 11 Abbildung 11.1 Der Output des ls-Befehls Der Output enthält die folgenden Felder: ● Dateityp und Berechtigungen: der Typ der Datei und die Zugriffsberechtigungen. Diese Dateieigenschaften werden später in diesem Kapiteln in den Unterabschnitten Dateitypen und Dateiberechtigungen beschrieben. ● Links: die Anzahl der Hard-Links, die mit dieser Datei verbunden sind. Jeder Hard-Link definiert einen Namen, unter dem diese Datei referenziert werden kann. Im Allgemeinen können Sie dieses Feld ignorieren. ● Benutzer: der Name des Benutzers, dem die Datei gehört ● Gruppe: der Name der Gruppe, der die Datei gehört ● Dateigröße: die Größe der Datei in Bytes 232 PHP 4 IT-Tutorial ● Änderungszeitpunkt: das Datum und die Zeit, an dem die Datei zum letzen Mal geändert wurde. Wenn die Datei in jüngerer Zeit nicht geändert wurde, werden stattdessen das Datum und das Jahr angezeigt ● Dateiname: der Name der Datei Eine Datei anzeigen Um den Inhalt einer Datei anzuzeigen, geben Sie den Befehl more dateiname ein, wobei dateiname für den Namen der Datei steht. Wenn die Datei mehr Zeilen enthält, als auf den Bildschirm oder in das Fenster passen, zeigt der moreBefehl nur die passende Anzahl von Zeilen an. Um vorwärts durch die Datei zu blättern, drücken Sie auf die Leertaste. Um seitenweise zurückzublättern, geben Sie den Buchstaben b ein. Um die Anzeige zu verlassen, geben Sie den Buchstaben q ein. Tipp Der Output des more-Befehls wird nur verständlich sein, wenn die Datei ASCII-Daten enthält. Um eine binäre Datei anzuzeigen, können Sie den odBefehl verwenden. Eine Datei editieren UNIX unterstützt eine Reihe von Editoren, mit denen Sie eine Datei editieren können. Fragen Sie Ihren Systemadministrator, welche Editoren auf Ihrem System zur Verfügung stehen. Viele Anfänger arbeiten gern mit dem Editor Pico, der mit dem beliebten E-Mail-Client Pine verbunden ist. Pico verfügt über eine eingebaute Hilfe. Die Bedienung des Editors ist einfach und ist leicht zu erlernen. Außerdem steht dieser Editor, weil er mit Pine verbunden ist, auf vielen UNIXSystemen zur Verfügung. Um eine Datei mit Pico zu editieren, geben Sie den Befehl pico dateiname ein, wobei dateiname für den Namen der Datei steht, die Sie editieren wollen. Wenn Sie eine neue Datei erstellen wollen, lassen Sie einfach den Dateinamen weg. Der Bildschirm von Pico sieht etwa folgendermaßen aus: Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 233 Abbildung 11.2 Der Bildschirm von Pico Das Pico-Fenster zeigt am unteren Rand in zwei Zeilen mehrere nützliche Befehle an. Jedem Befehl ist eine Tastenkombination zugeordnet, die aus der (Strg)-Taste und einem Buchstaben besteht. Die (Strg)-Taste wird durch ein ^ repräsentiert, das vor dem Buchstaben steht. Tabelle 11.1 fasst mehrere nützliche Pico-Befehle zusammen. Befehl Beschreibung (Strg)-(C) Die aktuelle Cursorposition (Zeilen- und Spaltenzahl) anzeigen (Strg)-(G) Die Pico-Hilfe anzeigen (Strg)-(J) Den aktuellen Absatz ausrichten (Strg)-(K) Die aktuelle Zeile ausschneiden (Strg)-(O) Den Dateipuffer (Edit-Puffer) auf die Festplatte speichern (Strg)-(R) Eine Datei in den Dateipuffer einlesen (Strg)-(T) Die Rechtschreibprüfung von Pico starten (Strg)-(U) Text einfügen (Strg)-(V) Vorwärts blättern (Strg)-(W) Text durchsuchen (Strg)-(X) Pico verlassen. Pico zeigt eine Warnung an, wenn der Dateipuffer nicht gespeichert wurde. (Strg)-(Y) Rückwärts blättern Tabelle 11.1 Nützliche Pico-Befehle 11 234 PHP 4 IT-Tutorial Eine Datei löschen Um eine Datei zu löschen, geben Sie den Befehl rm dateiname ein, wobei dateiname für den Namen der Datei steht. Achtung Im Gegensatz zu Windows werden gelöschte Dateien unter UNIX im Allgemeinen nicht in einem „Papierkorb“ gespeichert. Deshalb kann das Löschen einer UNIX-Datei im Allgemeinen nicht rückgängig gemacht werden. Eine Datei kopieren Um eine Datei zu kopieren, geben Sie den Befehl cp altedatei neuedatei ein, wobei altedatei den Namen der Datei angibt, die Sie kopieren wollen (die Quelldatei), und neuedatei den Namen der Kopie angibt (die Zieldatei). Der cp-Befehl ändert die Quelldatei nicht. Achtung Je nach Konfiguration des UNIX-Systems ist es möglich, dass der cp-Befehl eine vorhandene Datei überschreibt. Achten Sie darauf, dass Sie nicht unabsichtlich eine wichtige Datei überschreiben. Eine Datei umbenennen Um eine Datei umzubenennen, geben Sie den Befehl mv altedatei neuedatei ein, wobei altedatei den aktuellen Namen und neuedatei den gewünschten Namen der Datei angibt. Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 235 Tipp Einige UNIX-Systeme schränken die Möglichkeiten der Benutzer ein, Dateien eines Geräts oder bestimmter Partitionen umzubenennen. Um zu erfahren, welche Einschränkungen für Ihr System gelten, sollten Sie Ihren Systemadministrator fragen. Dateitypen Abbildung 11.1 zeigte den typischen Output des ls-Befehls. Das erste Feld des Outputs zeigt den Typ der Datei und die Berechtigungen an, die mit der Datei verbunden sind. Das erste Zeichen des Felds zeigt den Dateityp an. Die möglichen Werte sind: Typ Beschreibung - Gewöhnliche Datei b Gerätedatei (Device), die keine Blocktransfers ausführen kann d Verzeichnis (Directory) l Symbolischer Link p Benannte Pipe (fifo) s Socket Die wichtigsten Dateitypen sind die gewöhnliche Datei und das Verzeichnis. Die anderen Dateitypen spielen für unser Thema keine Rolle. Dateibesitz Jede Datei ist mit einem Benutzerkonto verbunden, das als Besitzer (auch Eigentümer) der Datei bezeichnet wird. Mit dem ls-Befehl können Sie den Besitzer einer Datei feststellen. Der Benutzer, der eine Datei erstellt, wird zum Besitzer der Datei. Mit dem chown-Befehl kann ein Systemadministrator einer Datei jedoch einen anderen Eigentümer zuweisen. UNIX-Systemadministratoren können mehrere Benutzer zu so genannten Benutzergruppen oder einfach Gruppen zusammenfassen. Ein Benutzer kann Mitglied einer unbegrenzten Anzahl von Gruppen sein. Jede Datei ist mit einer Gruppe verbunden, die auch als Gruppenbesitzer der Datei bezeichnet wird. Mit dem ls-Befehl können Sie den Gruppenbesitzer einer Datei feststellen. Einige UNIX-Systeme weisen jedem Benutzer automatisch eine private Gruppe zu. Auf solchen Systemen ist es üblich, dass Besitzer und Gruppenbesitzer einer Datei denselben Namen haben. Mit dem chgrp- 11 236 PHP 4 IT-Tutorial Befehl kann der Besitzer einer Datei der Datei einen neuen Gruppenbesitzer zuweisen. Dieser Befehl hat die folgende Form: chgrp gruppe dateiname Dabei steht dateiname für den Namen der Datei und gruppe für den Namen der Gruppe. Der Benutzer, der diese Anweisung gibt, muss nicht nur Besitzer der Datei, sondern auch Mitglied der Gruppe gruppe sein. Dateiberechtigungen Die Berechtigungen, die mit einer Datei verbunden sind, legen fest, welche Operationen ein Benutzer mit der Datei ausführen kann. Mit dem ls-Befehl können Sie feststellen, welche Berechtigungen mit einer Datei verbunden sind. Das erste Feld des Outputs des ls-Befehls Output zeigt den Dateityp und die Berechtigungen einer Datei an (vergleiche Abbildung 11.1). Das erste Zeichen des Felds gibt den Dateityp an; die restlichen neun Zeichen enthalten die Berechtigungen. Die Berechtigungen werden in Form von drei Gruppen aus jeweils drei Zeichen, also in drei Triaden, dargestellt. Die erste Triade zeigt die Berechtigungen des Besitzers der Datei an. Die zweite Triade zeigt die Berechtigungen der Mitglieder der Gruppe an, der die Datei gehört. Die dritte Triade zeigt die Berechtigungen der anderen Benutzer an, die weder Besitzer der Datei noch Mitglieder der Gruppe sind, der die Datei gehört. Nehmen wir beispielsweise an, dass das erste Feld des Outputs des ls-Befehls folgendermaßen aussieht: -rwxr-xr-- Wenn wir das erste Zeichen ignorieren, das den Dateityp anzeigt, können wir an diesem Output die folgenden Berechtigungen ablesen: ● Besitzer: rwx ● Gruppenmitglied: r-x ● Andere: r- Jedes Zeichen einer Berechtigungstriade kann aus einem Buchstaben oder einem Bindestrich bestehen. Die Buchstaben haben die folgenden Bedeutungen: ● r – Die Datei kann gelesen werden. ● w – Die Datei kann geschrieben werden. ● x – Die Datei kann ausgeführt werden. Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 237 Hinweis Die -Berechtigung hat nur bei Dateien einen Sinn, die einen ausführbaren x Inhalt enthalten, wie beispielsweise ausführbare Binärdateien oder bestimmte Arten von Skripts. Die Zeichen einer Triade werden immer in der Reihenfolge rwx angezeigt. Wenn anstelle eines Buchstabens ein Bindestrich steht, steht die entsprechende Berechtigung nicht zur Verfügung. Betrachten Sie beispielsweise die vorher gezeigten Berechtigungen: -rwxr-xr-- Diese Berechtigungen haben die folgende Bedeutung: ● rwx – D er Besitzer der Datei kann die Datei lesen, schreiben oder ausfüh- ren. ● r-x – Die Mitglieder der Gruppe, die die Datei besitzt, können die Datei lesen oder ausführen, aber nicht schreiben. ● r-- – Andere Benutzer können die Datei lesen, aber nicht schreiben oder ausführen. Mit dem chmod-Befehl kann der Besitzer einer Datei die Berechtigungen ändern, die mit einer Datei verbunden sind. Dieser Befehl hat zwei Formen. Bei der einen Variante können die Berechtigungen mit Oktalziffern angeben werden, die andere Variante verwendet zu diesem Zweck Buchstaben. Um Berechtigungen mit Oktalziffern anzugeben, müssen Sie den numerischen Wert jeder Triade berechnen. Zu diesem Zweck müssen Sie die Zahlen addieren, die den verfügbaren Berechtigungen innerhalb der Triade entsprechen. Den Berechtigungen sind folgende Zahlen zugeordnet: Berechtigung Wert r 4 w 2 x 1 Beispielsweise hat die Berechtigung rwx den Wert 4 + 2 + 1 = 7. Analog entspricht der Berechtigung r-x der Wert 4 + 1 = 5, und die Berechtigung r- hat den Wert 4. Nachdem Sie den numerischen Wert jeder Triade berechnet haben, bilden Sie eine dreistellige Oktalzahl, die aus den numerischen Werten der Berechtigungen des Benutzers, der Gruppenmitglieder und der anderen Benut- 11 238 PHP 4 IT-Tutorial zer besteht. Beispielsweise entsprechen die Berechtigungen rwxr-xr- dem Oktalwert 754. Die Form des chmod-Befehls, der mit Oktalziffern arbeitet, sieht folgendermaßen aus: chmod modus dateiname Dabei ist modus die dreistellige Oktalzahl, die die Berechtigungen angibt, und dateiname ist der Name der Datei, auf die die Berechtigungen angewendet werden. Um beispielsweise dem Besitzer einen vollständigen Zugriff auf die Datei test zu gewähren und anderen Benutzern nur das Lesen zu erlauben, geben Sie den Befehl chmod 744 test Die meisten Benutzer finden es bequemer, die Form des chmod-Befehls zu verwenden, die Berechtigungen mit Buchstaben angibt. Mit dieser alternativen Form können Sie Berechtigungen einer Datei festlegen, hinzufügen oder widerrufen. Diese alternative Form hat die folgende Syntax: chmod benutzer operation berechtigungen Zwischen den Argumenten des Befehls dürfen keine Leerzeichen stehen. Das benutzer-Argument enthält einen der drei folgenden Buchstaben: ● u – (= user) bezeichnet den Benutzer, der die Datei besitzt ● g – (= group) bezeichnet die Mitglieder der Gruppe, die die Datei besitzt ● o – (= owner) bezeichnet Benutzer, die weder Besitzer der Datei noch Mitglieder der Gruppe sind, die die Datei besitzt Das operation-Argument enthält eines der folgenden Zeichen: ● = – ersetzt die aktuellen Berechtigungen durch die angegebenen Berechti- gungen ● + – erweitert die angegebenen Berechtigungen ● - – widerruft die angegebenen Berechtigungen Das berechtigungen-Argument enthält einen der drei folgenden Buchstaben: ● r – Die Datei kann gelesen werden. ● w – Die Datei kann geschrieben werden. ● x – Die Datei kann ausgeführt werden. Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 239 Es ist möglich, mehrere Benutzer, Operationen und Gruppen anzugeben. Benachbarte Angaben müssen jeweils durch ein Komma getrennt werden. Der folgende Befehl setzt die Berechtigungen der Datei test auf rwxr--r-: chmod u=rwx,g=r,o=r test Das folgende Beispiel zeigt einen Befehl, der die Schreibberechtigungen aller Benutzer außer denen des Besitzers der Datei widerruft und die Berechtigungen des Besitzers der Datei um die Ausführungsberechtigung erweitert: chmod u+x,go-w test Dieser Befehl ändert weder die Lese- und Schreibberechtigungen des Dateibesitzers noch die Lese- und Ausführungsberechtigungen der anderen Benutzer. Hinweis UNIX-Systeme verfügen über ein spezielles Benutzerkonto namens root oder superuser, das ohne Einschränkungen auf Dateien zugreifen und diese manipulieren kann. Der Administrator eines System ist im Allgemeinen die einzige Person, die dazu autorisiert ist, das root-Konto zu verwenden. Frage an den Experten Frage: Der Output des ls-Befehls zeigt manchmal andere Berechtigungen als r, w und x an. Was bedeuten diese? Antwort: Systemadministratoren verwenden manchmal mehrere spezielle Berechtigungen. Beispielsweise verändert eine spezielle Berechtigung, die so genannte setuid, temporär die Identität des Benutzers, der eine Programmdatei ausführt, der diese Berechtigung zugewiesen ist. Solche speziellen Berechtigungen werden von PHP-Anwendungsprogrammierern im Allgemeinen nicht verwendet. Mit UNIX-Verzeichnissen arbeiten Um das Arbeiten mit Dateien zu vereinfachen, können Sie die Dateien unter UNIX mit Hilfe von Verzeichnissen organisieren. Unter Microsoft Windows werden Verzeichnisse als Ordner bezeichnet. Ein Verzeichnis kann andere Verzeichnisse, so genannte Unterverzeichnisse, enthalten; das Verzeichnis wird dann als Elternverzeichnis oder als übergeordnetes Verzeichnis seiner Unterverzeichnisse 11 240 PHP 4 IT-Tutorial bezeichnet. Die Verzeichnisse und Unterverzeichnisse eines UNIX-Systems bilden einen einzigen Baum oder eine Hierarchie. Das oberste Verzeichnis des Baumes wird als Stamm-, Wurzel- oder Root-Verzeichnis bezeichnet und als / geschrieben. Alle anderen Verzeichnisse sind Unterverzeichnisse des Root-Verzeichnisses. Üblicherweise verfügt das Root-Verzeichnis über Unterverzeichnisse wie beispielsweise bin, sbin, home und tmp. Der absolute Pfad eines Verzeichnisses ist die Liste der Verzeichnisse (angefangen bei dem Root-Verzeichnis), die durchlaufen werden müssen, um zu diesem Verzeichnis zu gelangen. Jedes Verzeichnis in der Liste wird von dem folgenden Verzeichnis durch einen Schrägstrich (/) getrennt. Beispielsweise hat das bin-Unterverzeichnis des Root-Verzeichnisses den absoluten Pfad /bin. Wenn das /bin-Verzeichnis über ein Unterverzeichnis namens there verfügen würde, hätte dieses den absoluten Pfad /bin/there. Hinweis Microsoft-Windows-Systeme verwenden Backslashes ( ; rückwärts gerichtete \ Schrägstriche), um Pfadkomponenten zu trennen. Die Windows-Versionen von PHP sind jedoch in der Lage, auch solche Pfade korrekt zu interpretieren, die mit normalen Schrägstrichen angegeben werden. Dennoch sollten Sie, wenn Sie ein PHP-Programm schreiben, das Windows-Pfade verarbeitet, daran denken, dass ein Backslash in einem PHP-String als einleitendes Zeichen einer Escape-Sequenz interpretiert werden kann. Möglicherweise müssen Sie jeden Backslash durch ein Paar Backslashes ersetzen, um zu verhindern, dass PHP den String falsch interpretiert. Auch Dateien verfügen über absolute Pfade. Eine Datei namens donethat, die sich in dem /bin/there-Verzeichnis befindet, hätte den absoluten Pfad /bin/ there/donethat. Im Allgemeinen verfügt jeder UNIX-Benutzer über ein eigenes Verzeichnis, das als home-Verzeichnis des Benutzers bezeichnet wird. Üblicherweise ist das home-Verzeichnis ein Unterverzeichnis von /home. Zu jedem Zeitpunkt ist ein Programm oder die Command-Shell mit einem Verzeichnis verbunden, das als aktuelles Arbeitsverzeichnis oder kurz als Arbeitsverzeichnis bezeichnet wird. Wenn sich ein Benutzer bei einem UNIX-System einloggt, wird im Allgemeinen das home-Verzeichnis des Benutzers als Arbeitsverzeichnis der Sitzung eingerichtet. Dateien und Unterverzeichnisse können relativ zu dem Arbeitsverzeichnis anstatt durch einen absoluten Pfad referenziert werden. Diese Form der Referenzierung wird als relativer Pfad bezeichnet. Ein relativer Pfad beginnt nie mit einem Schrägstrich, weil der Schrägstrich für das Root-Verzeichnis steht. Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 241 Nehmen wir beispielsweise an, dass das aktuelle Arbeitsverzeichnis /home/ bill ist. Dann kann die Datei test innerhalb dieses Verzeichnisses durch den absoluten Pfad /home/bill/test oder den relativen Pfad test referenziert werden. Offensichtlich ist es viel einfacher, den relativen Pfad einzutippen. Deshalb wird diese Form häufig vorgezogen. Nehmen wir noch einmal an, dass das aktuelle Arbeitsverzeichnis /home/bill ist. Nehmen wir weiter an, dass dieses Verzeichnis das Unterverzeichnis archiv enthält, in dem die Datei gezahlte-rechnungen gespeichert ist. Die Datei könnte dann durch den absoluten Pfad /home/bill/archiv/gezahlterechnungen oder den relativen Pfad archiv/gezahlte-rechnungen referenziert werden. Jedes Verzeichnis verfügt über zwei spezielle Unterverzeichnisse namens . und .. (ein Punkt bzw. zwei Punkte). Das Unterverzeichnis namens . ist ein Alias für das Verzeichnis selbst. Das Unterverzeichnis namens .. ist ein Alias für das übergeordnete Verzeichnis. Sie können diese speziellen Unterverzeichnisse verwenden, um relative Pfade zu bilden. Nehmen wir beispielsweise an, dass das aktuelle Arbeitsverzeichnis /home/bill ist. Dann könnten Sie die Datei /home/ test als ../test referenzieren, weil .. auf das /home-Verzeichnis, das übergeordnete Verzeichnis von /home/bill, verweist. Hinweis Obwohl das Root-Verzeichnis über kein übergeordnetes Verzeichnis verfügt, enthält es ein Unterverzeichnis namens ... In diesem speziellen Fall ist das ..Verzeichnis ein Alias für das Root-Verzeichnis. Das aktuelle Arbeitsverzeichnis ermitteln und ändern Um das aktuelle Arbeitsverzeichnis zu ermitteln, geben Sie den folgenden Befehl ein: pwd Um das aktuelle Arbeitsverzeichnis zu ändern, geben Sie den Befehl cd pfad ein, wobei pfad ein absoluter oder relativer Pfad ist, der das gewünschte Verzeichnis angibt. 11 242 PHP 4 IT-Tutorial Tipp Die meisten UNIX-Systeme zeigen den Pfad des aktuellen Arbeitsverzeichnisses, oder wenigsten einen Teil dieses Pfads, in der Eingabeaufforderung (dem Befehlsprompt) an. Wenn dies bei Ihrem System nicht der Fall sein sollte, bitten Sie den Systemadministrator, das System entsprechend zu konfigurieren. Dadurch wird es für Sie einfacher, das aktuelle Arbeitsverzeichnis jederzeit im Blick zu behalten. Verzeichnisinhalte anzeigen Um die Namen der Dateien und der Verzeichnisse anzuzeigen, die im aktuellen Arbeitsverzeichnis enthalten sind, geben Sie den folgenden Befehl ein: ls Wenn Sie die Dateien und Verzeichnisse anzeigen wollen, die in einem anderen Verzeichnis enthalten sind, geben Sie den Befehl ls pfad ein, wobei pfad für den absoluten oder relativen Pfad des betreffenden Verzeichnisses steht. Wenn Sie neben den Namen der Dateien und Verzeichnisse auch deren Eigenschaften anzeigen wollen, fügen Sie dem ls-Befehl das Flag -l hinzu: ls -l oder ls -l pfad Standardmäßig zeigt der ls-Befehl Dateien oder Verzeichnisse, deren Name mit einem Punkt beginnt, nicht an; solche Dateien und Verzeichnisse werden als verborgene Dateien und Verzeichnisse bezeichnet. Um verborgene Dateien und Verzeichnisse und ihre nicht verborgenen Gegenstücke anzuzeigen, fügen Sie dem ls-Befehl das Flag -a hinzu: ls -a oder ls -al pfad Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 243 Hinweis Der ls-Befehl und andere Befehle, die mit Verzeichnissen arbeiten, funktionieren nur, wenn der Benutzer über die passenden Berechtigungen für den Zugriff auf das Verzeichnis verfügt. Mehr darüber finden Sie in dem Unterabschnitt Verzeichnisberechtigungen. Ein Verzeichnis erstellen Mit dem mkdir-Befehl können Sie ein Verzeichnis erstellen: mkdir pfad Dabei ist pfad ein absoluter oder relative Pfad, der das Verzeichnis angibt, das erstellt werden soll. Ein Verzeichnis löschen Mit dem rmdir-Befehl können Sie ein Verzeichnis löschen: rmdir pfad Dabei ist pfad ein absoluter oder relativer Pfad ist, der das Verzeichnis angibt, das gelöscht werden soll. Das Verzeichnis muss leer sein, andernfalls scheitert der Befehl. Verzeichnisberechtigungen Verzeichnisse sind – wie Dateien – mit Berechtigungen verbunden. Diese Berechtigungen werden mit denselben Buchstaben wie Dateiberechtigungen bezeichnet; jedoch haben die Buchstaben bei Verzeichnissen eine etwas andere Bedeutung: ● r – Das Verzeichnis kann gelesen werden, d.h. seine Unterverzeichnisse und Dateien können mit dem ls-Befehl und ähnlichen Mitteln angezeigt werden. ● w – Das Verzeichnis kann geschrieben werden, d.h. in dem Verzeichnis können Dateien und Unterverzeichnisse erstellt und gelöscht werden. ● x – Das Verzeichnis kann benutzt werden, d.h. ein Zugriff auf die Dateien und Unterverzeichnisse des Verzeichnisses ist möglich. 11 244 PHP 4 IT-Tutorial Frage an den Experten Frage: Ein Verzeichnis zu löschen, das viele Unterverzeichnisse und Dateien enthält, ist mühsam. Gibt es eine einfachere Methode? Antwort: Um ein Verzeichnis und seinen gesamten Inhalt zu löschen, geben Sie den Befehl rm -rf pfad ein, wobei pfad ein absoluter oder relativer Pfad ist, der das Verzeichnis bezeichnet, das gelöscht werden soll. Gehen Sie mit diesem Befehl sehr vorsichtig um, weil gelöschte Verzeichnisse und Dateien im Allgemeinen nicht wiederhergestellt werden können. Wenn der ls-Befehl mit dem Argument -l ausgeführt wird, zeigt der lsBefehl die Berechtigungen an, die mit einem Verzeichnis verbunden sind. Benutzer, die über die passenden Berechtigungen verfügen, können die Berechtigungen ändern, die mit einem Verzeichnis verbunden sind. Zu diesem Zweck können Sie den chmod-Befehl verwenden, der weiter oben in diesem Kapitel beschrieben wurde. 1-Minuten-Test ● Mit welchem UNIX-Befehl kann der Inhalt einer Datei angezeigt werden? ● Mit welchem UNIX-Befehl kann eine Datei gelöscht werden? ● Welche Operationen darf der Besitzer einer Datei ausführen, die mit den Berechtigungen r-xr----- verbunden ist? ● Welcher UNIX-Befehl zeigt das aktuelle Arbeitsverzeichnis an? ● ● ● ● more rm lesen, ausführen pwd Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 245 Mit Dateien arbeiten Dieser Abschnitt baut auf den Grundlagen auf, die in dem vorangegangenen Abschnitt behandelt wurden, und erklärt, wie in PHP mit Dateien gearbeitet wird. Weil sich das Dateisystemmodell von Microsoft Windows von dem UNIXDateisystemmodell unterscheidet, funktionieren einige PHP-Funktionen unter Windows nicht korrekt. Um die Sache noch zu komplizieren, wurden in PHP 4.02 einige Änderungen an der Art und Weise eingeführt, wie PHP mit Dateien und Verzeichnissen arbeitet. In diesem Abschnitt werden PHP 4.02 und neuere Versionen unter UNIX beschrieben. Dabei wird auch auf wichtige Inkompatibilitäten hingewiesen. Wenn Sie mit Windows oder mit einer älteren Version von PHP arbeiten, sollten Sie damit rechnen, dass einige Beispiele wahrscheinlich nicht richtig funktionieren. Besitz- und Berechtigungsfragen Obwohl viele PHP-Programmierer Dateien verwenden, um Daten zu speichern, sollten dieser Entscheidung einige Überlegungen vorangehen. Das Speichern von Daten in Dateien kann dazu führen, dass die Vertraulichkeit der in ihnen enthaltenen Informationen verletzt wird oder dass die Dateien selbst geändert oder zerstört werden. Sie erinnern sich, dass die Berechtigungen, die mit einer Datei oder einem Verzeichnis verbunden sind, festlegen, welche Operationen ein Benutzer mit der Datei oder dem Verzeichnis ausführen kann. Wenn PHP ausgeführt wird, erfolgt die Ausführung unter einem bestimmten Benutzerkonto. Die Berechtigungen, die mit der Datei oder dem Verzeichnis verbunden sind, legen fest, welche Operationen PHP ausführen kann. Ein Systemadministrator kann das Benutzerkonto konfigurieren, unter dem PHP ausgeführt wird. Häufig konfigurieren Systemadministratoren PHP so, dass es unter einem speziellen Benutzerkonto ausgeführt wird, dass über sehr beschränkte Berechtigungen verfügt; häufig wird dieses Konto als nobody bezeichnet. PHP unter einem Konto auszuführen, das über beschränkte Berechtigungen verfügt, unterstützt Administratoren dabei, PHP vor Sicherheitsbedrohungen zu schützen, und wird als empfehlenswerte Vorgehensweise eingestuft. Wenn Ihr Systemadministrator PHP jedoch so konfiguriert hat, dass PHP unter einem Konto wie beispielsweise nobody ausgeführt wird, haben Sie möglicherweise Schwierigkeiten, Ihre Dateien für PHP zugänglich zu machen. Ein Ansatz besteht darin, allen Benutzern den Zugriff auf die Dateien zu erlauben. Wenn Sie PHP erlauben wollen, die Dateien zu lesen, könnte dieser Ansatz brauchbar sein. Aber wenn die Dateien geheime Informationen enthalten oder Sie PHP erlauben wollen, Daten in die Dateien zu schreiben, ist ein solches Vor- 11 246 PHP 4 IT-Tutorial gehen nicht ratsam. Dann kann dieser Ansatz dazu führen, dass die Vertraulichkeit der Informationen verletzt wird, die in den Dateien enthalten sind, oder dass die Dateien selbst geändert oder zerstört werden. Ein weiterer Ansatz besteht darin, Ihren Systemadministrator zu bitten, den Besitzer der Dateien zu ändern, auf die PHP zugreifen können soll. Beispielsweise könnte der Systemadministrator die Dateien der Gruppe nobody zuordnen. Als Besitzer der Dateien könnten Sie die vollen Berechtigungen behalten, und PHP könnte über die Berechtigungen verfügen, die Gruppenmitgliedern eingeräumt wurden. Jedoch kann jeder Benutzer bei diesem Ansatz ein PHP-Skript schreiben und mit denselben Berechtigungen auf die Dateien zugreifen, die PHP eingeräumt wurden. Im Allgemeinen werden Sie auch mit diesem Ansatz nicht zufrieden sein. Wenn Sie nicht selbst Systemadministrator sind und wenn nicht nur vertrauenswürdige Benutzer auf das System zugreifen können, können Sie wahrscheinlich kein Verfahren entwickeln, mit dem Sie geheime oder variable Daten sicher in Dateien speichern können, ohne die Sicherheit der Dateien oder des Systems selbst zu gefährden. Eine bessere Methode, um vertrauliche oder empfindliche Daten sicher zu speichern, besteht darin, eine Datenbank zu verwenden. Im Allgemeinen eignen sich nur Dateien für einen Zugriff mit PHP, deren Daten öffentlich und konstant sind. Die Attribute einer Datei ermitteln PHP stellt mehrere Funktionen zur Verfügung, mit denen Sie Informationen abfragen können, die eine Datei beschreiben. Tabelle 11.2 fasst die gebräuchlichsten Funktionen zusammen. Funktion Beschreibung file_exists() Gibt true zurück, wenn die angegebene Datei existiert; gibt andernfalls false zurück fileatime() Gibt den letzten Zugriffszeitpunkt auf die Datei als UNIX-Zeitstempel zurück filectime() Gibt den Änderungszeitpunkt des I-Nodes der Datei als UNIX-Zeitstempel zurück filegroup() Gibt die numerische Gruppen-ID der Datei zurück filemtime() Gibt den Änderungszeitpunkt der Datei als UNIX-Zeitstempel zurück fileowner() Gibt die numerische Benutzer-ID der Datei zurück fileperms() Gibt die Berechtigungen der Datei zurück filesize() Gibt die Größe der Datei in Bytes zurück Tabelle 11.2 PHP-Funktionen zur Abfrage von Dateiattributen Kapitel 11: Mit Dateien und Verzeichnissen arbeiten Funktion Beschreibung filetype() Gibt den Typ der Datei zurück: "fifo", "char", "dir", "block", "link", "file" oder "unknown" is_dir() Gibt true zurück, wenn die angegebene Datei existiert und ist ein Verzeichnis; gibt andernfalls false zurück is_file() Gibt true zurück, wenn die angegebene Datei existiert und eine normale Datei ist; gibt andernfalls false zurück is_readable() Gibt true zurück, wenn die angegebene Datei existiert und im Lesezugriff ist; gibt andernfalls false zurück is_writable() Gibt true zurück, wenn die angegebene Datei existiert und im Schreibzugriff ist; gibt andernfalls false zurück 247 Tabelle 11.2 PHP-Funktionen zur Abfrage von Dateiattributen Die Funktionen fileowner() und filegroup() geben jeweils eine numerische ID zurück. Sie können die numerische ID in einen String umwandeln, indem Sie posix_getpwuid() zur Ermittlung einer Benutzer-ID oder posix_getgrgid() zur Ermittlung einer Gruppen-ID anwenden. Ein Beispiel, das zeigt, wie diese Funktionen aufgerufen werden, befindet sich auf der Website dieses Buches (http://www.mitp.de), sodass Sie die Datei herunterladen und selbst ausführen können. Die Datei hat den Namen p-11-a.php. Sie hat den folgenden Inhalt: <?php $dateiname = "p-11-a.txt"; $ergebnis = file_exists($dateiname); echo "<br>file_exists(): $ergebnis"; $ergebnis = posix_getpwuid(fileowner($dateiname)); $ergebnis = $ergebnis["name"]; echo "<br>fileowner(): $ergebnis"; $ergebnis = posix_getgrgid(filegroup($dateiname)); $ergebnis = $ergebnis["name"]; echo "<br>filegroup(): $ergebnis"; $ergebnis = filetype($dateiname); echo "<br>filetype(): $ergebnis"; $ergebnis = filesize($dateiname); echo "<br>filesize(): $ergebnis"; $ergebnis = fileatime($dateiname); $ergebnis = date ("m/d/Y H:i", $ergebnis); 11 248 PHP 4 IT-Tutorial echo "<br>fileatime(): $ergebnis"; $ergebnis = filectime($dateiname); $ergebnis = date("m/d/Y H:i", $ergebnis); echo "<br>filectime(): $ergebnis"; $ergebnis = filemtime($dateiname); $ergebnis = date ("m/d/Y H:i", $ergebnis); echo "<br>filemtime(): $ergebnis"; $ergebnis = fileperms($dateiname); $ergebnis = decoct($ergebnis); echo "<br>fileperms(): $ergebnis"; $ergebnis = is_Datei($dateiname); echo "<br>is_file(): $ergebnis"; $ergebnis = is_dir($dateiname); echo "<br>is_dir(): $ergebnis"; $ergebnis = is_readable($dateiname); echo "<br>is_readable(): $ergebnis"; $ergebnis = is_writable($dateiname); echo "<br>is_writable(): $ergebnis"; ?> Wenn Sie das Beispiel selbst ausführen wollen, müssen Sie darauf achten, dass sich die Datei, deren Name durch die Variable $dateiname angegeben wird, in demselben Verzeichnis wie das Skript befindet. Der Output des Beispiels könnte (unter UNIX bzw. Linux) etwa wie folgt aussehen: file_exists(): 1 fileowner(): nobody filegroup(): nobody filetype(): file filesize(): 0 fileatime(): 04/12/2005 10:04 filectime(): 04/11/2005 11:28 filemtime(): 04/10/2005 10:36 fileperms(): 100644 is_file(): 1 is_dir(): 0 is_readable(): 1 is_writable(): 1 Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 249 Dateiberechtigungen ändern Um Dateiberechtigungen zu ändern, rufen Sie chmod() auf, eine Funktion, die ähnliche Argumente hat, wie sie auf der UNIX-Befehlszeile verwendet werden: chmod (dateiname, modus) Das Argument dateiname legt den Namen oder den Pfad der Datei fest, deren Berechtigungen geändert werden sollen, und das Argument modus gibt die gewünschten Berechtigungen an. Im Allgemeinen ist es praktisch, die Berechtigungen als Oktalzahl anzugeben. Zu diesem Zweck stellen Sie dem Wert die Ziffer 0 voran. Beispielsweise hat das Literal 010 den Wert 8, nicht den Wert 10. Deshalb können Sie einer Datei die Berechtigungen rw-r----- zuweisen, indem Sie den Wert 0640 angeben. Damit die chmod()-Funktion Erfolg haben kann, muss PHP unter dem Benutzer ausgeführt werden, der Besitzer der Datei ist. Im Erfolgsfall gibt die Funktion true, andernfalls false zurück. Achtung Die chmod()-Funktion funktioniert unter Microsoft Windows nicht. Den Besitz einer Datei ändern Um den Gruppenbesitzer einer Datei zu ändern, können Sie die chgrp()-Funktion verwenden. Sie hat die folgende Form: chgrp(dateiname, gruppe) Dabei ist dateiname der Name oder der Pfad der Datei, und gruppe gibt den Namen oder die numerische Gruppen-ID der Gruppe an. Damit die Funktion Erfolg haben kann, muss das Benutzerkonto, unter dem PHP ausgeführt wird, die Datei besitzen und ein Mitglied der Gruppe sein, die durch gruppe bezeichnet wird. Im Erfolgsfall gibt die Funktion true, andernfalls false zurück. Achtung Die chgrp()-Funktion funktioniert unter Microsoft Windows nicht. 11 250 PHP 4 IT-Tutorial Hinweis Obwohl PHP eine chown()-Funktion enthält, mit der der Besitzer einer Datei geändert werden kann, funktioniert diese Funktion nur, wenn PHP unter dem root-Konto ausgeführt wird. Weil ein solches Vorgehen jedoch unsicher ist, wird es nur selten angewendet, sodass die chown()-Funktion im Allgemeinen nicht zur Verfügung steht. Eine Datei öffnen Der Vorgang, der die Möglichkeit schafft, auf eine Datei zuzugreifen, wird als Öffnen bezeichnet. Bevor man eine Datei lesen oder schreiben kann, muss die Datei mit der fopen()-Funktion geöffnet werden: fopen(dateiname, modus) Dabei gibt dateiname den Namen oder den Pfad der Datei an, die geöffnet werden soll, und modus legt die Art des gewünschten Zugriffs fest. Beispielsweise öffnet der folgende Befehl die Datei abook.txt zum Lesen: $fh = fopen("abook.txt", "r"); Beachten Sie, dass fopen() einen Wert zurückgibt. Dieser Wert ist false, wenn PHP die Datei nicht öffnen konnte. Andernfalls enthält dieser Wert eine Ganzzahl, die als Datei-Handle oder kurz als Handle bezeichnet wird. Das Handle wird dazu verwendet, die Datei in Funktionen zu identifizieren, die Dateioperationen ausführen. Manchmal wird dieser Wert auch als Dateizeiger (engl. file pointer) bezeichnet. Jedoch ist die Bezeichnung Datei-Handle passender, weil mit einem Handle genau genommen eine Ganzzahl und mit einem Zeiger genau genommen ein Speicherplatz identifiziert wird. In Tabelle 11.3 werden die Werte von modus zusammengefasst, die an fopen() übergeben werden können. Die Buchstaben, mit denen Modi bezeichnet werden, entsprechen den Wörtern read (lesen), write (schreiben) und append (anhängen). Ein Modus ("r") erlaubt einen Lesezugriff. Zwei Modi ("w" und "a") erlauben einen Schreibzugriff. Drei Modi (die ein + enthalten) ermöglichen beides. Einige Modi haben zur Folge, dass PHP versucht, die Datei zu erstellen, falls diese nicht existiert. Zwei Modi schneiden eine vorhandene Datei ab, d.h. sie löschen den Inhalt der Datei, aber nicht die Datei selbst. Kapitel 11: Mit Dateien und Verzeichnissen arbeiten Modus Lesen "r" X "r+" X "w" "w+" X "a" "a+" X Schreiben Erstellen Abschneiden 251 Zeiger Anfang X Anfang X X X Anfang X X X Anfang X X Ende X X Ende Tabelle 11.3 Die Modi von fopen() Achtung Damit fopen() Erfolg haben kann, muss PHP unter einem Benutzer ausgeführt werden, der über hinreichende Berechtigungen verfügt, um die Operationen auszuführen, die in dem Modus angegeben werden. Ein Beispiel: Um eine Datei erstellen zu können, muss PHP unter einem Benutzer ausgeführt werden, der über Schreibzugriff auf das Verzeichnis verfügt, in dem die Datei erstellt werden soll. Jede Datei verfügt über einen Zeiger, der anzeigt, an welcher Byte-Position innerhalb der Datei die nächste Operation (lesen oder schreiben) ausgeführt werden wird. Der modus-Wert von fopen() legt die anfängliche Position des Dateizeigers fest. In einem der folgenden Abschnitte, In einer Datei navigieren, wird erklärt, wie Sie auf den Dateizeiger zugreifen und diesen manipulieren können. PHP enthält auch eine alternative Form von fopen(), die über drei Argumente verfügt: fopen(dateiname, modus, pfad) Wenn das pfad-Argument den Wert "1" hat, sucht PHP die Datei in einem speziellen Verzeichnis, das als Include-Pfad bezeichnet wird. Der PHP-Administrator legt die Identität des Include-Pfads fest. Wenn Sie das pfad-Argument angeben, sollte das Argument dateiname aus einem Dateinamen oder einem relativen Pfad und nicht aus einem absoluten Pfad bestehen. Achtung Standardmäßig berichtet PHP 4.04pl1, dass der Include-Pfad gesetzt ist. Jedoch ist es notwendig, den Wert der include_path-Variablen in der Datei php.ini manuell zu setzen; andernfalls wird der Include-Pfad nicht verwendet. 11 252 PHP 4 IT-Tutorial Achtung Unter Microsoft Windows werden ASCII- und Binär-Dateien unterschiedlich behandelt. Wenn Sie unter Windows eine binäre Datei öffnen wollen, müssen Sie ein b als zweites Zeichen beim Modus angeben – beispielsweise "rb". Falls Sie dies nicht tun, können Lese- und andere Dateioperationen vorzeitig abgebrochen werden oder scheitern. Den Abschluss einer Dateioperation prüfen Dateioperationen – einschließlich solcher Operationen wie dem Öffnen, Lesen und Schreiben einer Datei – können aus einer Reihe von Gründen scheitern. Deshalb ist es wichtig zu prüfen, dass jede Operation erfolgreich abgeschlossen wurde. Das folgende Beispiel zeigt eine Möglichkeit, dies zu tun: $fh = fopen("abook.txt", "r"); if (!$fh) { die("Öffnen von <i>abook.txt</i> gescheitert"); } Die fopen()-Funktion gibt false zurück, wenn sie die Datei nicht öffnen konnte. In diesem Fall ruft das Skript die die()-Funktion auf, um eine Nachricht anzuzeigen und die Ausführung zu beenden. Erfahrene PHP-Programmierer verwenden mehrere andere, kompaktere, aber möglicherweise verwirrendere Formen dieses Befehls. Ein Beispiel: ($fh = fopen("abook.txt", "r")) || die("Öffnen von <i>abook.txt</i> gescheitert"); Mit Klammern und Whitespace-Zeichen kann die Funktion dieses Befehls verdeutlicht werden. Der Befehl ruft fopen() auf und weist das Ergebnis der Variablen $fh zu. Dann führt er (mit dem ||-Operator) eine logische OR-Operation mit den beiden Operanden $fh und die() aus. Wenn $fh den Wert true zurückgibt, hat das Ergebnis des logischen OR immer den Wert true. In diesem Fall wertet PHP deshalb den anderen Operanden des logischen OR, den Aufruf von die(), nicht aus. Deshalb wird die() nur ausgeführt, wenn $fh den Wert false hat, d.h. wenn fopen() scheitert. Eine einfachere, alternative Form verwendet den OR-Operator: $fh = fopen("abook.txt", "r") OR die("Öffnen von <i>abook.txt</i> gescheitert"); Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 253 Diese Form funktioniert wie die vorangegangene Form. Jedoch hat der OROperator eine niedrigere Präzedenz als der ||-Operator, sodass es möglich ist, den Befehl mit weniger Klammern zu schreiben. Tipp Sie erinnern sich, dass PHP Warnungen und andere Nachrichten unterdrückt, die beim Ausführen der Funktion generiert werden, wenn vor dem Namen einer aufgerufenen Funktion ein @ steht. Wenn Sie das Ergebnis jeder Dateioperation sorgfältig testen, können Sie Fehlermeldungen gefahrlos unterdrücken und dadurch verhindern, dass der Output Ihres Skripts mit PHP-Nachrichten vermischt wird, die anderenfalls den Benutzer verwirren könnten. Eine Datei schließen Eine geöffnete Datei bindet Systemressourcen. Wenn ein Skript eine Datei nicht mehr benötigt, sollte es die Datei schließen und damit diese Ressourcen wieder freigeben. PHP schließt Dateien automatisch, wenn ein Skript beendet wird. Es gilt jedoch als guter Programmierstil, Dateien bereits früher zu schließen, wenn dies möglich ist. Zu diesem Zweck können Sie die fclose()-Funktion verwenden: fclose(dateihandle) Dabei ist dateihandle das Datei-Handle, das beim Öffnen der Datei zurückgegeben wurde. Das folgende Beispiel zeigt ein typisches Muster dafür, wie eine Datei geöffnet, genutzt und geschlossen wird: $fh = @fopen("abook.txt", "r"); if (!$fh) { die("Öffnen von <i>abook.txt</i> gescheitert"); } // Befehle, die die geöffnete Datei verwenden @fclose($fh); Tipp Die fclose()-Funktion gibt den Wert true zurück, wenn die Datei erfolgreich geschlossen wurde. Es ist selten erforderlich, diesen Wert zu testen, weil im Allgemeinen wenig getan werden kann, wenn der Versuch scheitert, eine Datei zu schließen. 11 254 PHP 4 IT-Tutorial Eine Datei lesen PHP verfügt über eine Reihe von Funktionen, um Dateien zu lesen. Die grundlegendste dieser Funktionen ist fread(). Sie hat die folgende Form: fread(dateihandle, laenge) Das dateihandle-Argument ist der Wert, der von fopen() zurückgegeben wurde. Das laenge-Argument legt die maximale Anzahl von Bytes fest, die gelesen werden sollen. Die Bytes, die von der Datei eingelesen werden, werden als Stringwert zurückgegeben. Wenn die Leseoperation auf das Ende der Datei stößt, gibt PHP weniger Bytes zurück, als der Wert laenge angibt. Tipp PHP enthält eine verwandte Funktion namens fgetc(), die ein Byte der angegebenen Datei einliest. Das folgende Beispiel zeigt, wie Text einer Datei eingelesen und angezeigt wird: $fh = fopen("abook.txt", "r"); if (!$fh) { die("Öffnen von <i>abook.txt</i> gescheitert"); } $s = fread($fh, 256); echo "<br>Gelesen: $s"; fclose($fh); Das Beispiel liest maximal 256 Bytes der Datei ein. Wenn Sie mehr oder weniger Bytes einlesen wollen, ändern Sie den Wert des laenge-Arguments von fread(). Tipp Wenn Sie dieses Beispiel selbst ausprobieren wollen, müssen Sie die Datei abook.txt in demselben Verzeichnis wie das Skript speichern. Außerdem muss PHP die Berechtigung haben, die Datei zu lesen. Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 255 Um die gesamte Datei zu lesen und anzuzeigen, können Sie als laenge-Argument den Rückgabewert der filesize()-Funktion verwenden: $dateiname = "abook.txt"; $fh = fopen($dateiname, "r"); if (!$fh) { die("Öffnen von <i>$dateiname</i> gescheitert"); } $s = fread($fh, filesize($dateiname)); echo "<br>Gelesen: $s"; fclose($fh); Eine Textzeile lesen Eine Textzeile besteht aus einer Reihe von Zeichen, gefolgt von einem Zeilenendezeichen. Es ist üblich, den Text einer Datei zeilenweise einzulesen. Die fgets()-Funktion liest eine Zeile einer Datei ein. Die Funktion hat die folgende Form: fgets(dateihandle, laenge) Das dateihandle-Argument enthält wie bei fread() den Wert, der von fopen() zurückgegeben wird. Das laenge-Argument enthält jedoch einen Wert, der um eins kleiner ist als die maximale Anzahl von Bytes, die gelesen werden, um das Zeilenendezeichen zu berücksichtigen. Die eingelesenen Bytes werden als Stringwert zurückgegeben. Das folgende Beispiel zeigt, wie Sie die erste Zeile einer Datei lesen und ausgeben können: $fh = fopen("abook.txt", "r"); if (!$fh) { die("Öffnen von <i>abook.txt</i> gescheitert"); } $s = fgets($fh, 256); echo "<br>Gelesen: $s"; fclose($fh); Das Beispiel geht davon aus, dass die längste Zeile in der Datei weniger als 256 Bytes enthält. Wenn Sie längere Zeilen einlesen wollen, ändern Sie einfach den Wert des laenge-Arguments von fgets(). 11 256 PHP 4 IT-Tutorial Eine komplette Datei zeilenweise einlesen Im Allgemeinen ist es erforderlich, mehr als nur die erste Zeile einer Datei einzulesen. Zu diesem Zweck muss ein Skript feststellen können, wann die Datei vollständig eingelesen worden ist. Dieser Zweck wird mit der feof()-Funktion erfüllt, die einen Wert zurückgibt, der anzeigt, ob das Ende der Datei erreicht worden ist. Die Funktion hat die folgende Form: feof(dateihandle) Das dateihandle-Argument enthält den Wert, der von fopen() zurückgegeben wird. Die feof()-Funktion gibt true zurück, wenn der Dateizeiger der angegebenen Datei auf das Ende der Datei zeigt; andernfalls gibt sie false zurück. Das folgende Beispiel zeigt, wie Sie mit feof() das zeilenweise Einlesen einer kompletten Datei steuern können: $fh = fopen("abook.txt", "r"); if (!$fh) { die("Öffnen von <i>abook.txt</i> gescheitert"); } $s = fgets($fh, 256); while (!feof($fh)) { echo "<br>Gelesen: $s"; $s = fgets($fh, 256); } fclose($fh); Der while-Befehl stellt sicher, dass fgets()wiederholt aufgerufen wird, bis alle Zeilen gelesen worden sind. Eine einfachere Methode, eine komplette Datei zeilenweise einzulesen, besteht darin, die file()-Funktion zu verwenden. Diese Funktion gibt ein Array zurück, in dem jedes Element eine Zeile der angegebenen Textdatei enthält. Das folgende Beispiel zeigt, wie Sie mit der file()-Funktion den Inhalt einer Datei lesen und ausgeben können: $array = file("abook.txt"); foreach ($array as $s) { echo "<br>Gelesen: $s"; } Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 257 Achtung Diese Methode eignet sich nicht für sehr große Dateien, weil der Inhalt der gesamten Datei in das Array geladen wird. Dies kann mehr Speicherplatz erfordern, als verfügbar ist. Den Inhalt einer Datei ausgeben PHP verfügt über zwei Funktionen, mit denen der Inhalt einer Datei leicht ausgegeben werden kann. Eine Funktion, fpassthru(), benötigt ein Argument, das das Datei-Handle der Datei angibt, die ausgegeben werden soll: $fh = fopen("abook.txt", "r"); fpassthru($fh); Die Funktion schließt die Datei nach der Ausgabe automatisch. Die andere Funktion, readfile(), benötigt nur den Namen oder Pfad der Datei: readfile("abook.txt"); In einer Datei navigieren Wie bereits erwähnt wurde, verfügt jede Datei über einen Zeiger, der die BytePosition markiert, an der die nächste Operation stattfinden wird. Mit der rewind()-Funktion können Sie den Zeiger auf den Anfang der Datei zurücksetzen. Die Funktion hat die folgende Form: rewind(dateihandle) Das dateihandle-Argument enthält den Wert, der von fopen() zurückgegeben wird. Hinweis Es ist nicht möglich, den Zeiger einer Datei an den Anfang der Datei zu setzen, wenn die Datei im append-Modus, d.h. mit "a" oder "a+" geöffnet wurde. Das folgende Beispiel zeigt, wie Sie den Inhalt einer Datei mit rewind() zweimal ausgeben können: 11 258 PHP 4 IT-Tutorial $fh = fopen("abook.txt", "r"); if (!$fh) { die("Öffnen von <i>abook.txt</i> gescheitert"); } $s = fgets($fh, 256); while (!feof($fh)) { echo "<br>\$s: $s"; $s = fgets($fh, 256); } // zurücksetzen und erneut anzeigen rewind($fh); $s = fgets($fh, 256); while (!feof($fh)) { echo "<br>\$s: $s"; $s = fgets($fh, 256); } fclose($fh); Die rewind()-Funktion gibt null zurück, wenn ein Fehler auftritt. Obwohl die rewind()-Funktion recht nützlich ist, kommt es eher selten vor, dass man Dateizeiger an den Anfang einer Datei zurücksetzen muss. Die fseek()Funktion bietet eine größere Flexibilität: Sie können damit den Dateizeiger gezielt positionieren und damit eine beliebige Position einer Datei lesen oder schreiben. Die Funktion hat zwei Formen. Die grundlegendste Form lautet: fseek(dateihandle, offset) Das dateihandle-Argument enthält den Wert, der von fopen() zurückgegeben wird. Das offset-Argument gibt die gewünschte Position des Dateizeigers an, die in Bytes vom Anfang der Datei an gemessen wird. Wenn die fseek()-Funktion erfolgreich ausgeführt wird, gibt sie null zurück, andernfalls -1. Eine alternative Form der Funktion bietet eine noch größere Flexibilität: fseek(dateihandle, offset, basis) Die Argumente dateihandle und offset haben dieselbe Bedeutung wie zuvor. Das basis-Argument nimmt einen der folgenden Werte an: ● SEEK_SET – setzt den Dateizeiger relativ zum Anfang der Datei ● SEEK_CUR – setzt den Dateizeiger relativ zum aktuellen Zeigerwert ● SEEK_END – setzt den Dateizeiger relativ zum Ende der Datei Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 259 Der Wert des offset-Arguments kann positiv, negativ oder null sein. Beispielsweise wird der Zeiger mit dem folgenden Befehl auf die Position gesetzt, die 1000 Bytes vom Ende der Datei entfernt ist: fseek($fh, -1000, SEEK_END) Dabei enthält $fh das Handle der Datei, deren Zeiger Sie setzen wollen. Mit der ftell()-Funktion können Sie den aktuellen Wert des Dateizeigers abfragen: ftell(dateihandle) Die Funktion gibt den aktuellen Wert des Dateizeigers oder den Wert null zurück, falls die Funktion scheitert. In eine Datei schreiben Im Gegensatz zu der Vielzahl von Funktionen, über die PHP zum Lesen von Dateien verfügt, enthält es nur eine einzige Funktion, um in Dateien zu schreiben: die fwrite()-Funktion. Die Funktion hat die folgende Form: fwrite(dateihandle, daten) Das dateihandle-Argument enthält den Wert, der von fopen() zurückgegeben wird. Das daten-Argument enthält die Daten, die in die Datei geschrieben werden sollen. Wenn die Funktion erfolgreich ausgeführt wird, gibt sie die Anzahl der geschriebenen Bytes zurück; andernfalls gibt sie den Wert -1 zurück. Das folgende Beispiel zeigt, wie Sie Daten in eine Datei schreiben können: $fh = fopen("log.txt", "a"); if (!$fh) { die("Öffnen von <i>log.txt</i> gescheitert"); } $ok = fwrite($fh, "Die Daten sind in Ordnung.\n"); echo "<br>Ergebnis von fwrite: $ok"; fclose($fh) In diesem Beispiel wird eine Textzeile in die Datei geschrieben. Weil die Datei im Modus "a" geöffnet wurde, werden die Daten an das Ende der Datei angefügt, d.h. die Daten werden nach den möglicherweise schon vorhandenen Daten geschrieben. Beachten Sie, dass außerdem ein Zeilenendezeichen („\n") geschrieben wird, sodass die Datei später zeilenweise gelesen werden kann. Wenn 11 260 PHP 4 IT-Tutorial Sie mit einer Textdatei arbeiten, sollten Sie im Allgemeinen am Ende jeder Zeile, die Sie in die Datei schreiben, ein Zeilenendezeichen einfügen. In diesem Beispiel wird nur eine einzige Textzeile in die Datei geschrieben. Sie können jedoch auch mehrere Zeilen schreiben. Wenn Sie fwrite()innerhalb einer Schleife aufrufen, können Sie mehrere Zeilen schreiben. Nachdem Sie alle gewünschten Zeilen geschrieben haben, sollten Sie die Datei mit fclose() schließen. Daneben verfügt PHP auch über eine alternative Form der fwrite()-Funktion: fwrite(dateihandle, daten, laenge) Diese Form enthält ein drittes Argument, laenge, mit dem Sie die maximale Anzahl von Bytes angeben, die geschrieben werden sollen. Tipp Wenn Sie binäre Dateien unter Microsoft Windows schreiben, müssen Sie fwrite() mit dem laenge-Argument verwenden. Außerdem werden unter Windows Zeilen mit der Zeichenfolge "\r\n" beendet. Wenn Sie PHP-Code für Windows-Systeme schreiben, sollten Sie diese Windows-Konvention zum Beenden von Zeilen verwenden. Tipp PHP enthält eine weitere Funktion zum Schreiben von Dateien, fputs(). Doch abgesehen von ihrem Namen ist die fputs()-Funktion mit fwrite() identisch. Deshalb können Sie fputs() und fwrite() auch als eine Funktion mit zwei Namen betrachten. Projekt 11–1: Ein Seitenzugriffszähler ctr.php ctr-test.php In diesem Projekt werden Sie ein Skript erstellen, das die Anzahl der Zugriffe auf eine Webseite zählt. Projektziele ● Demonstrieren, wie eine Datei mit PHP gelesen und geschrieben wird ● Zeigen, wie ein Zugriffszähler für eine Webseite erstellt wird Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 261 Schritt für Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen ctr.php, und laden Sie diese Datei auf Ihren PHP-Server herauf: <?php // Projekt 11–1 $cfile = basename($PHP_SELF) . ".dat"; $fh = fopen($cfile, "r+"); if (!$fh) { die("<br>Öffnen von <i>$cfile</i> gescheitert"); } $s = fgets($fh, 6); $count = (int) $s; $count = $count + 1; $count = str_pad($count, 6); rewind($fh); fwrite($fh, $count); echo "$count"; fclose($fh); ?> 2. Speichern Sie das folgende PHP-Skript unter dem Dateinamen ctrtest.php, und laden Sie diese Datei auf Ihren Server in dasselbe Verzeichnis wie die Datei ctr.php herauf: <html> <!-- Projekt 11–1 --> <head> <title>ctr-test.php</title> </head> <body> Auf diese Seite wurde <b> <?php include "ctr.php" ?> </b> Mal zugegriffen. </body> </html> 3. Erstellen Sie die Datei ctr-test.php in demselben Verzeichnis, in das Sie die Skripts heraufgeladen haben. Unter UNIX oder Linux können Sie die Datei erstellen, indem Sie den folgenden Befehl eingeben: touch ctr-test.php.dat. (Unter Windows können Sie die Datei mit dem Editor anlegen.) 11 262 PHP 4 IT-Tutorial Stellen Sie sicher, dass PHP Lese- und Schreibzugriff auf die Datei hat. Wenn Sie nicht genau wissen, wie dies geht, fragen Sie Ihren Systemadministrator. 4. Nehmen Sie sich Zeit, um das PHP-Skript ctr.php zu studieren. Beachten Sie, wie das Skript mit Hilfe der PHP-Variablen $PHP_SELF den Namen der Datei bestimmt, in der es enthalten ist, und dann die Erweiterung .dat an den Namen anhängt, um den Namen der Datei zu bilden, die den Zugriffszähler enthält. Beachten Sie auch die Funktionen, mit denen die Dateioperationen ausgeführt werden. 5. Nehmen Sie sich Zeit, um das PHP-Skript ctr-test.php zu studieren. Beachten Sie, dass das Skript hauptsächlich aus HTML-Code besteht. Es enthält nur eine einzige PHP-Zeile. Der include-Befehl bewirkt, dass PHP den Inhalt der Datei ctr.php in die Datei ctr-test.php einbindet, wenn auf letztere Datei zugegriffen wird. 6. Zeigen Sie mit einem Webbrowser auf den URL des Skripts ctrtest.php. Der Browser sollte anzeigen, wie oft auf die Seite zugegriffen wurde. Mit jeder Aktualisierung der Seite sollte der Seitenzugriffszähler erhöht werden. Exklusiven Zugriff auf eine Datei erhalten Das Web stellt für Software-Entwickler eine spezielle Herausforderung dar, weil mehrere Benutzer gleichzeitig auf ein einziges PHP-Skript zugreifen können. Manchmal kann ein gleichzeitiger Zugriff zu einer Zerstörung einer Datei führen. Um zu demonstrieren, wie dies passieren kann, wollen wir den Prozess betrachten, der abläuft, wenn auf den Zugriffszähler einer Webseite zugegriffen und sein Wert aktualisiert wird. Nehmen wir an, dass die Seite anfänglich den Wert 100 hat. Bei diesem Prozess werden nacheinander die folgenden Aktionen ausgeführt: 1. Die Datei mit dem Wert des Zählers wird geöffnet. 2. Der aktuelle Wert des Zählers (100) wird aus der Datei gelesen. 3. Der Zähler wird erhöht (101). 4. Der aktualisierte Wert des Zählers (101) wird in der Datei gespeichert. 5. Die Datei wird geschlossen. Wir wollen jetzt betrachten, was passieren kann, wenn zwei Prozesse gleichzeitig auf die Webseite und ihren Zähler zugreifen, sodass sich die Schritte der beiden Prozesse überlappen. Tabelle 11.4 zeigt das Ergebnis: Kapitel 11: Mit Dateien und Verzeichnissen arbeiten Prozess 1 263 Prozess 2 1. Die Datei mit dem Wert des Zählers wird geöffnet. 1. Die Datei mit dem Wert des Zählers wird geöffnet. 2. Der aktuelle Wert des Zählers (100) wird aus der Datei gelesen. 2. Der aktuelle Wert des Zählers (100) wird aus der Datei gelesen. 3. Der Zähler wird erhöht (101). 3. Der Zähler wird erhöht (101). 4. Der aktualisierte Wert des Zählers (101) wird in der Datei gespeichert. 4. Der aktualisierte Wert des Zählers (101) wird in der Datei gespeichert. 5. Die Datei wird geschlossen. 5. Die Datei wird geschlossen. Tabelle 11.4 In Konflikt liegende Dateizugriffe Beachten Sie, dass Prozess 2 die Datei liest, bevor Prozess 1 den aktualisierten Wert des Zählers schreibt. Deshalb lesen beide Prozesse 100 als Anfangswert des Zählers ein, erhöhen den Zähler auf 101 und speichern 101 als fortgeschriebenen Wert des Zählers wieder in die Datei. Deshalb wird der Zähler nur um eins erhöht, obwohl zwei Prozesse auf die Seite zugegriffen haben. Wenn Sie auf der Basis der Besucherzahl einer Seite bezahlt werden, ist dies ein ziemlich ernstes Problem. Um dieses Problem zu vermeiden, ist es erforderlich, jedem Prozess einen exklusiven Zugriff auf die Datei des Zugriffszählers zu ermöglichen. Auf diese Weise wird der Zugriff auf die Datei serialisiert: Zunächst verwendet der eine Prozess die Datei und dann der andere. Solange verhindert wird, dass die Prozesse gleichzeitig auf die Datei zugreifen, wird dem Zähler kein falscher Wert zugewiesen. Mit der flock()-Funktion kann ein Prozess einen exklusiven Zugriff auf eine Datei erhalten, weil diese Funktion die Datei für diesen Prozess reserviert, indem Sie die Datei für andere Prozesse temporär sperrt. Die Funktion hat die folgende Form: flock (dateihandle, operation) Das dateihandle-Argument enthält den Wert, der von fopen() zurückgegeben wird. Das operation-Argument ist eine Konstante oder ein Ausdruck, die bzw. der die gewünschte Operation wie folgt festlegt: 11 264 PHP 4 IT-Tutorial Operation Beschreibung LOCK_SH Eine geteilte Sperre (engl. shared lock) für die angegebene Datei errichten. An einer geteilten Sperre können mehrere Prozesse beteiligt sein. Jedoch kann kein Prozess eine Datei geteilt sperren, während ein anderer Prozess die Datei exklusiv gesperrt hat. Der Prozess muss dann warten, bis er die angeforderte Sperre errichten kann. LOCK_EX Die angegebene Datei exklusiv sperren. Jeweils nur ein Prozess kann eine Datei exklusiv sperren. Der Prozess wartet, bis er die angeforderte Sperre errichten kann. LOCK_SH + LOCK_NB Versuchen, die angegebene Datei geteilt zu sperren; jedoch soll der Prozess nicht warten, wenn die Sperre nicht sofort verfügbar ist. LOCK_EX + LOCK_NB Versuchen, die angegebene Datei exklusiv zu sperren; jedoch soll der Prozess nicht warten, wenn die Sperre nicht sofort verfügbar ist. LOCK_UN Die Sperre der angegebenen Datei aufheben. Die flock()-Funktion gibt bei Erfolg den Wert true zurück; wenn die geforderte Sperre nicht errichtet (LOCK_SH und LOCK_EX) oder nicht aufgehoben (LOCK_UN) werden kann, gibt sie false zurück. Achtung Das Sperren ist eine kooperative Aktivität. Den Prozessen wird niemals der Zugriff auf Dateien, sondern nur der Zugriff auf Sperren verwehrt. Deshalb kann ein Prozess, der nicht versucht, eine Datei zu sperren, auf die Datei zugreifen, selbst wenn ein anderer Prozess eine exklusive Sperre der Datei angefordert und gewährt bekommen hat. Achtung Einige Webserver, einschließlich des IIS von Microsoft, führen einen einzigen Multi-threaded-Prozess aus. In solchen Fällen kann die flock()-Funktion keinen exklusiven Zugriff auf Dateien zur Verfügung stellen. Projekt 11–2: Ein verbesserter Seitenzugriffszähler lctr.php lctrtest.php In diesem Projekt werden Sie ein Skript erstellen, das die Anzahl der Zugriffe auf eine Webseite zählt. Dieses Skript verbessert das Skript des letzten Projekts. Das Skript sperrt die Datei, die den Seitenzähler enthält, sodass gleichzeitige Zugriffe nicht zu einer fehlerhaften Zählung führen. Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 265 Projektziele ● Demonstrieren, wie Dateien gesperrt werden ● Zeigen, wie ein verlässlicher Seitenzugriffszähler implementiert wird Schritt für Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen lctr.php, und laden Sie diese Datei auf Ihren PHP-Server herauf: <?php // Projekt 11–2 $fh = @fopen($cfile, "r+") or die("<br>Öffnen von <i>$cfile</i> gescheitert"); @flock($fh, LOCK_EX) or die("<br>Sperren von <i>$cfile</i> gescheitert"); $s = @fgets($fh, 6); $count = (int) $s + 1; $count = str_pad($count, 6); @rewind($fh) or die("<br>Rücksetzen von <i>$cfile</i> gescheitert"); if (@fwrite($fh, $count) == -1) { die("<br>Schreiben in <i>$cfile</i> gescheitert "); } echo "$count"; @flock($fh, LOCK_UN) or die("<br>Unlock von <i>$cfile</i> gescheitert"); fclose($fh) or die("<br>Schließen von <i>$cfile</i> gescheitert"); ?> 2. Speichern Sie das folgende PHP-Skript unter dem Dateinamen lctrtest.php, und laden Sie diese Datei auf Ihren Server in dasselbe Verzeichnis wie die Datei lctr.php herauf: <html> <!-- Projekt 11–2 --> <head> <title>lctrtest.php</title> </head> <body> <?php $cfile="lctrtest.php.dat" ?> Auf diese Seite wurde <b> <?php include "lctr.php" ?> 11 266 PHP 4 IT-Tutorial </b> Mal zugegriffen. </body> </html> 3. Erstellen Sie die Datei lctrtest.php.dat in demselben Verzeichnis, in dem die heraufgeladenen Skripts gespeichert sind. Unter UNIX oder Linux können Sie die Datei erstellen, indem Sie den folgenden Befehl eingeben: touch lctrtest.php.dat. 4. 5. 6. 7. (Unter Windows können Sie die Datei mit dem Editor anlegen.) Stellen Sie sicher, dass PHP Lese- und Schreibzugriff auf die Datei hat. Wenn Sie nicht genau wissen, wie dies geht, fragen Sie Ihren Systemadministrator. Nehmen Sie sich Zeit, um das PHP-Skript lctr.php zu studieren. Beachten Sie, wie die Datei gesperrt und entsperrt wird. Nehmen Sie sich Zeit, um das PHP-Skript lctrtest.php zu studieren. Beachten Sie, dass es sich nur sehr geringfügig von dem entsprechenden Skript in Projekt 11–1 unterscheidet. Zeigen Sie mit einem Webbrowser auf den URL des Skripts lctrtest.php. Der Browser sollte anzeigen, wie oft auf die Seite zugegriffen wurde. Mit jeder Aktualisierung der Seite sollte der Seitenzugriffszähler erhöht werden. Zeigen Sie mit zwei Webbrowsern auf den URL des Skripts lctrtest.php. Versuchen Sie, mit beiden Browsern gleichzeitig auf die Seite zuzugreifen. Selbst wenn Ihnen dies gelingen sollte, sollten die Dateisperren sicherstellen, dass der Zugriffszähler korrekt aktualisiert wird. Eine Datei kopieren Mit der copy()-Funktion von PHP können Sie eine Datei einfach kopieren. Die Funktion hat die folgende Form: copy (quelle, ziel) Dabei gibt quelle den Namen oder Pfad der Datei an, die kopiert werden soll, und ziel den Namen oder Pfad, der die Kopie enthält. Die Funktion gibt true zurück, wenn die copy-Operation erfolgreich ausgeführt wird, andernfalls gibt sie false zurück. Das folgende Beispiel zeigt die Funktion in Aktion: Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 267 $ok = copy("test.txt", "test.txt.bak"); if (!$ok) { die("<br>Das Kopieren der Datei ist gescheitert."); } In diesem Beispiel wird eine Sicherungskopie der Datei test.txt namens test.txt.bak erstellt. Hinweis Denken Sie daran, dass PHP über einen Schreibzugriff auf das Verzeichnis verfügen muss, in das die Kopie eingefügt werden soll; andernfalls kann PHP die Kopie nicht erstellen. Achtung Die copy()-Funktion überschreibt die Zieldatei, falls diese existiert. Eine Datei umbenennen Mit der rename()-Funktion von PHP können Sie eine Datei umbenennen. Die Funktion hat die folgende Form: rename (altername, neuername) Dabei ist altername der ursprüngliche Name oder Pfad der Datei und neuername der gewünschte neue Name oder Pfad. Die Funktion gibt true zurück, wenn die rename-Operation erfolgreich ausgeführt worden ist; andernfalls gibt sie false zurück. Das folgende Beispiel zeigt die Funktion in Aktion: $ok = rename("test.txt", "TEST.txt"); if (!$ok) { die("<br>Das Umbenennen der Datei ist gescheitert."); } Das Beispiel benennt die Datei test.txt in TEST.txt um. 11 268 PHP 4 IT-Tutorial Hinweis Denken Sie daran, dass PHP über einen Schreibzugriff auf das Verzeichnis verfügen muss, in dem die umbenannte Datei stehen soll; andernfalls kann PHP die Datei nicht umbenennen. Achtung Ähnlich wie der mv-Befehl von UNIX überschreibt die rename()-Funktion die Zieldatei, falls diese existiert. Eine Datei löschen Mit der unlink()-Funktion von PHP können Sie eine Datei löschen. Die Funktion hat die folgende Form: unlink(dateiname) Dabei gibt dateiname den Namen oder Pfad der Datei an, die gelöscht werden soll. Die Funktion gibt true zurück, wenn die unlink-Operation erfolgreich ausgeführt worden ist; andernfalls gibt sie false zurück. Das folgende Beispiel zeigt die Funktion in Aktion: $ok = unlink("test.txt"); if ($ok === false) { die("<br>Das Löschen der Datei ist gescheitert."); } Das Beispiel löscht die Datei test.txt. Hinweis Denken Sie daran, dass PHP über einen Schreibzugriff auf das Verzeichnis verfügen muss, in dem sich die Datei befindet; andernfalls kann PHP die Datei nicht löschen. Hinweis Laut PHP-Handbuch funktioniert die unlink()-Funktion möglicherweise nicht unter Microsoft-Windows-Systemen. Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 269 Frage an den Experten Frage: Ich habe HTML-Formulare gesehen, mit denen der Benutzer eine Datei auf den Server heraufladen kann. Wie kann ich ein solches Formular erstellen und mit PHP verwenden? Antwort: Um ein Formular zum Heraufladen von Dateien zu erstellen, müssen Sie in das form-Tag das Attribut enctype="multipart/ form-data" sowie ein Input-Control vom Typ type="FILE" einfügen. Ein Beispiel: <html> <head> <title>upload.html</title> </head> <body> <h2>Datei heraufladen</h2> <form method="POST" action="upload.php" enctype="multipart/form-Daten"> Laden Sie diese Datei herauf: <input name="benutzerdatei" type="FILE"> <br><br> <input type="SUBMIT" value="Datei senden"> </form> </body> </html> Wenn der Benutzer auf die SUBMIT-Schaltfläche (DATEI SENDEN) klickt, lädt der Browser die Datei auf den Server herauf. Ihr PHP-Skript kann mit $HTTP_POST_FILES["benutzerdatei"]["tmp_name"] auf den Pfad der heraufgeladenen Datei zugreifen, ein, wobei benutzerdatei den Wert des name-Attributs enthält, das in dem input-Control die heraufzuladende Datei bezeichnet. PHP löscht die heraufgeladene Datei automatisch, wenn das Skript beendet wird. Wenn Sie die Datei speichern wollen, können Sie die move_uploaded_file()-Funktion verwenden. Ein Beispiel: 11 270 PHP 4 IT-Tutorial $ergebnis = move_uploaded_file( $HTTP_POST_FILES["benutzerdatei"]["tmp_name"], "/home/bill/test.txt"); $ergebnis = $ergebnis ? "true" : "false"; echo "<br>move_uploaded_file(): $ergebnis"; Bei der move_uploaded_file()-Funktion müssen Sie den Pfad der heraufgeladenen Datei und den Pfad des Ziels angeben, zu dem die Datei verschoben werden soll. Die Funktion gibt true zurück, wenn die Operation erfolgreich ausgeführt worden ist; andernfalls gibt sie false zurück. 1-Minuten-Test ● Mit welchem Modus-Wert wird ein Lesezugriff auf eine Datei angefordert? ● Mit welcher Funktion wird eine Datei geschlossen? ● Mit welcher Funktion wird eine Textzeile einer Datei gelesen? ● Mit welcher Funktion wird in eine Datei geschrieben? Mit Verzeichnissen arbeiten Neben den Funktionen für das Arbeiten mit Dateien verfügt PHP über entsprechende Funktionen für das Arbeiten mit Verzeichnissen, mit denen Sie unter anderem die folgenden häufig vorkommenden Aufgaben lösen können: das Arbeitsverzeichnis ermitteln oder setzen, Pfade manipulieren, Verzeichnisinhalte lesen, Verzeichnisberechtigungen anzeigen und ändern und Verzeichnisse erstellen und löschen. Das Arbeitsverzeichnis ermitteln und setzen Mit der getcwd()-Funktion können Sie das aktuelle Arbeitsverzeichnis ermitteln. Die Funktion hat keine Argumente und gibt das Arbeitsverzeichnis als String zurück. Ihre Form lautet: ● ● ● ● "r" oder einer der Modi "r+", "w+" oder "a+" fclose() fgets() fwrite() Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 271 $cdir = getcwd(); Mit der chdir()-Funktion können Sie das aktuelle Arbeitsverzeichnis ändern. Ihre Form lautet: chdir(dirname) Dabei gibt dirname den Pfad oder Namen des gewünschten Arbeitsverzeichnisses an. Die Funktion gibt true zurück, wenn die Operation erfolgreich ausgeführt worden ist; andernfalls gibt sie false zurück. Beispielsweise macht der folgende Befehl das /tmp-Verzeichnis zum aktuellen Arbeitsverzeichnis: $ok = chdir("/tmp"); if (!$ok) { die("Ändern des Arbeitsverzeichnisses gescheitert"); } Pfade manipulieren PHP enthält mehrere Funktionen, um Pfade zu manipulieren. Mit der dirname() -Funktion können Sie den Pfad ermitteln, der zur letzten Komponente einer kompletten Pfadangabe führt. Wenn es sich bei der letzten Komponente um eine Datei handelt, können Sie mit dieser Funktion den Dateinamen von dem Pfad trennen. Wenn der Funktion beispielsweise der komplette Pfad "/ home/bill/bin/skript.php" als Argument übergeben wird, gibt sie "/home/ bill/bin" zurück. Die Funktion hat die folgende Form: dirname(pfad) Mit der basename()-Funktion können Sie die komplementäre Operation ausführen und nur die letzte Komponente des angegebenen Pfads ermitteln. Wenn der Funktion beispielsweise der komplette Pfad "/home/bill/bin/skript.php" als Argument übergeben wird, gibt sie "skript.php" zurück. Die Funktion hat die folgende Form: basename(pfad) Wenn Sie mehrere Operationen mit einem Pfad ausführen wollen, kann die pathinfo()-Funktion nützlich sein. Diese Funktion gibt ein assoziatives Array zurück, dessen drei Elemente die folgenden Informationen über den Pfad enthalten: den Rückgabewert von dirname(), den Rückgabewert von basename() und 11 272 PHP 4 IT-Tutorial (falls vorhanden) die Dateierweiterung. Das folgende Beispiel zeigt pathinfo() in Aktion: $info = pathinfo("/home/bill/bin/skript.php"); foreach ($info as $name=>$wert) { echo "<br>$name=>$wert"; } Das Beispiel erzeugt den folgenden Output: dirname=>/home/bill/bin basename=>skript.php extension=>php Achtung In PHP 4.04pl1 wird das Skript abgebrochen, wenn pathinfo() mit einem Pfad aufgerufen wird, der nicht in einer Dateierweiterung endet. Dieser Fehler wurde in PHP 4.05 behoben. Verzeichnisberechtigungen anzeigen und ändern Die Funktionen, die weiter oben in Tabelle 11.1 zusammenfasst wurden, können auf Dateien oder Verzeichnisse angewendet werden. Mit diesen Funktionen können Sie eine Reihe von Verzeichniseigenschaften einschließlich der Verzeichnisberechtigungen anzeigen, die von der Funktion fileperms() zurückgegeben werden. Auf ähnliche Weise können Sie auch die chmod()-Funktion, die weiter oben beschrieben wurde, auf Dateien oder Verzeichnisse anwenden. Mit dieser Funktion können Sie Verzeichnisberechtigungen genau wie Dateiberechtigungen setzen. Verzeichnisinhalte lesen PHP verfügt über drei Funktionen, mit denen Sie den Inhalt eines Verzeichnisses ähnlich wie den Inhalt einer Datei lesen können: ● opendir() – öffnet ein Verzeichnis zum Lesen ● readdir() – liest einen Verzeichniseintrag ● closedir() – schließt das Verzeichnis und gibt die Ressourcen frei, die von opendir() belegt wurden Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 273 Die Funktion readdir() gibt einen String zurück, der den Namen der nächsten Datei oder des nächsten Unterverzeichnisses des geöffneten Verzeichnisses enthält. Die Funktion gibt false zurück, wenn alle Verzeichniseinträge gelesen worden sind. Das folgende Beispiel zeigt, wie Sie die Inhalte eines Verzeichnisses mit dieser Funktion lesen können: $dh = @opendir("/home/bill/www"); if (!$dh) { die("Öffnen des Verzeichnisses gescheitert"); } $s = readdir($dh); while ($s) { echo "<br>$s"; $s = readdir($dh); } closedir($dh); Der Output dieses Beispiels könnte folgendermaßen aussehen: . .. php index.html phpinfo.php Ein Verzeichnis erstellen Mit der mkdir()-Funktion können Sie ein Verzeichnis erstellen: mkdir(dirname, modus) Dabei gibt dirname den Pfad oder den Namen des Verzeichnisses an, das erstellt werden soll, und modus die Berechtigungen, die dem neuen Verzeichnis zugewiesen werden sollen. Das modus-Argument sollte normalerweise mit einer führenden Null beginnen, damit PHP es als oktalen Wert interpretiert. Die Funktion gibt true zurück, wenn das Verzeichnis erstellt worden ist; andernfalls gibt sie false zurück. Beispielsweise können Sie mit dem folgenden Befehl ein Verzeichnis namens test erstellen und ihm die Berechtigungen rwxr-x-x zuweisen: mkdir("test", 0751) 11 274 PHP 4 IT-Tutorial Tipp Mit der rename()-Funktion können Sie auch ein Verzeichnis umbenennen. Ein Verzeichnis löschen Mit der rmdir()-Funktion können Sie ein Verzeichnis löschen, indem Sie dieser Funktion den Pfad oder den Namen des Verzeichnisses, das gelöscht werden soll, als Argument übergeben. Beispielsweise können Sie mit dem folgenden Befehl das Verzeichnis /home/bill/stale löschen: rmdir("/home/bill/stale") Nur ein leeres Verzeichnis kann gelöscht werden. Die Funktion gibt den Wert null zurück, wenn ein Fehler auftritt. 1-Minuten-Test ● Mit welcher Funktion wird ein Verzeichniseintrag gelesen? ● Mit welcher Funktion wird die Dateierweiterung ermittelt, die mit einem Pfad verbunden ist? ● Welche Funktion gibt den Pfad des aktuellen Arbeitsverzeichnisses zurück? Frage an den Experten Frage: Gibt es noch andere PHP-Funktionen, die sich auf Dateien und Verzeichnisse beziehen und die ich kennen sollte? Antwort: Obwohl dies ein sehr langes Kapitel ist, können wir nicht alle PHP-Funktionen erklären, die das Arbeiten mit Dateien und Verzeichnissen betreffen. Darüber hinaus haben ziemlich viele Funktionen Eigenheiten, die im Interesse der Einfachheit und Kürze übergangen wurden. Weitere Informationen finden Sie unter www.php.net im PHP-OnlineHandbuch. ● readdir() mit opendir() und closedir() ● pathinfo() ● getcwd() Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 275 Es ist besonders wichtig, sich mit diesen Information vertraut zu machen, wenn Sie unter Microsoft Windows mit PHP arbeiten. Sie sollten sich auch mit der Fehler-Datenbank vertraut machen, die unter www.php.net verwaltet wird. Dort finden Sie die neuesten Informationen über Korrekturen und Hilfskonstruktionen (engl. workarounds), die das Arbeiten mit Datei- und Verzeichnisfunktionen betreffen können. Projekt 11–3: Ein Adressbuch-Browser In diesem Projekt werden Sie ein Skript erstellen, mit dem Sie in einer Textbrowser.php datei blättern können, die ein Adressbuch enthält. Mit diesem Skript kann der abook.txt Benutzer auch neue Einträge in das Adressbuch, ok.txt, einfügen. Projektziele ● Demonstrieren, wie das Navigieren in Dateien funktioniert ● Demonstrieren, wie mit PHP das value-Attribut des form-Controls gesetzt werden kann Schritt-für-Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen browser.php, und laden Sie diese Datei auf Ihren PHP-Server herauf: <html> <!-- Projekt 11–3 --> <head> <title>Adressbuch-Browser</title> </head> <body> <h2>Adressbuch-Browser</h2> <form method="POST" action="browser.php"> <?php $ADRESSEN = "abook.txt"; $NAMELAENGE = 24; $EMAILLAENGE = 24; $SATZLAENGE = $NAMELAENGE + $EMAILLAENGE + 1; if (isset($links)) { $offset -= $SATZLAENGE; if ($offset < 0) 11 276 PHP 4 IT-Tutorial { $offset = 0; } $fh = fopen($ADRESSEN, "r"); if (!$fh) { die("<br>Öffnen der Datei gescheitert"); } fseek($fh, $offset, SEEK_SET); $name = fread($fh, $NAMELAENGE); $email = fread($fh, $EMAILLAENGE); fclose($fh); } elseif (isset($rechts)) { $offset += $SATZLAENGE; if ($offset < 0) { $offset = 0; } $fh = fopen($ADRESSEN, "r"); if (!$fh) { die("<br>Öffnen der Datei gescheitert"); } fseek($fh, $offset, SEEK_SET); // Testen, ob Dateiende erreicht ist $tmp = fgets($fh, $SATZLAENGE + 1); if (feof($fh)) { $offset -= $SATZLAENGE; } else { $name = fread($fh, $NAMELAENGE); $email = fread($fh, $EMAILLAENGE); } fclose($fh); } elseif (isset($suchen)) { $muster = $name; $name = ""; $email = ""; Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 277 $offset = 0; $fh = fopen($ADRESSEN, "r"); if (!$fh) { die("<br>Öffnen der Datei gescheitert"); } fseek($fh, $offset, SEEK_SET); // Testen, ob Dateiende erreicht ist $tmp = fgets($fh, $SATZLAENGE + 1); while (!feof($fh)) { $file_name = fread($fh, $NAMELAENGE); $file_email = fread($fh, $EMAILLAENGE); $match = stristr($file_name, $muster); if ($match !== false) break; $offset += $SATZLAENGE; } $name = $file_name; $email = $file_email; $offset += $SATZLAENGE; fclose($fh); } elseif (isset($einfuegen)) { $name = str_pad($name, $NAMELAENGE); $email = str_pad($email, $EMAILLAENGE); $fh = fopen($ADRESSEN, "a"); if (!$fh) { die("<br>Öffnen der Datei gescheitert"); } fwrite($fh, $name); fwrite($fh, $email); fwrite($fh, "\n"); $offset = ftell($fh) - $SATZLAENGE; fclose($fh); } @$name = trim($name); @$email = trim($email); @$offset = $offset; 11 278 PHP 4 IT-Tutorial ?> <br>Name: <br><input type="TEXT" name="name" <?php echo "value=\"$name\""; ?>> <br> <br>E-Mail-Adresse: <br><input type="TEXT" name="email" <?php echo "value=\"$email\""; ?>> <br> <br> <input type="SUBMIT" name="suchen" <input type="SUBMIT" name="links" <input type="SUBMIT" name="rechts" <input type="SUBMIT" name="einfuegen" <input type="HIDDEN" name="offset" <?php echo "value=\"$offset\""; ?>> value="Suchen"> value="<"> value=">"> value="Einfügen"> </form> </body> </html> 2. Laden Sie die folgende Textdatei unter dem Namen abook.txt auf den Server in dasselbe Verzeichnis wie das Skript herauf: Al Nall Bob Tale Chuck Stake Ed Nogg Xi Lentz Yo Hoho Zak Cloth [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] Jede Zeile der Datei sollte genau 48 Zeichen lang sein; die E-Mail-Adresse sollte in Spalte 25 beginnen. 3. Nehmen Sie sich Zeit, um das PHP-Skript zu studieren. Beachten Sie, dass das Skript ein HTML-Formular enthält und dass das action-Attribut des form-Tags den Namen der Skriptdatei enthält, die das HTML-Formular und die PHP-Befehle, die die Formulardaten verarbeiten, in einer einzigen Datei zusammenfasst. 4. Beachten Sie, wie mit $offset die aktuelle Position beim Blättern nachgehalten wird. Weil die beiden Felder (name und email), die in der Datei gespeichert sind, über feste Längen verfügen, ist die Programmlogik ein- Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 279 fach. Bei Feldern mit variablen Feldlängen wäre die Logik beträchtlich komplexer. 5. Beachten Sie auch, wie PHP die value-Attribute der Textfelder name und email anhand der Werte ähnlich benannter PHP-Variablen setzt. 6. Achten Sie darauf, dass PHP über Lese- und Schreibzugriff auf die Datei abook.txt verfügt. Wenn Sie nicht genau wissen, wie dies geht, sollten Sie sich an Ihren Systemadministrator wenden. 7. Geben Sie den URL der Skriptdatei in das Adressfeld Ihres Webbrowsers ein. Die Anzeige des Browsers sollte Abbildung 11.3 ähneln. Mit den Schaltflächen können Sie die Datei seitenweise vorwärts und rückwärts durchblättern, einen eingegebenen Namen suchen oder einen neuen Eintrag in die Adressliste einfügen. 11 Abbildung 11.3 Das Eingabeformular des Adressbuch-Browsers 280 PHP 4 IT-Tutorial 9Übungsaufgaben 1. Welcher UNIX-Befehl würde das (leere) Verzeichnis test löschen? 2. Welche numerischen Berechtigungen würden Sie einer Datei zuweisen, um ihrem Besitzer Read-only-Zugriff und anderen Benutzern überhaupt keine Zugriffsrechte zuzuweisen? 3. Welcher Funktionsaufruf öffnet die Datei test.txt und ermöglicht einen Append- und Read-Zugriff auf die Datei? 4. Welcher Funktionsaufruf setzt den Dateizeiger der Datei, die mit dem Handle $f verbunden ist, auf das Ende der Datei? 5. Welcher Funktionsaufruf gibt die Berechtigungen zurück, die mit dem Verzeichnis /test verbunden sind? Kapitel 12 E-Mail senden und empfangen Lernziele ● Wie E-Mail per SMTP versandt wird ● Wie auf E-Mail zugegriffen werden kann, die auf einem IMAP-Server gespeichert ist ● Wie IMAP-Nachrichten und -Ordner manipuliert werden können 282 PHP 4 IT-Tutorial In diesem Kapitel lernen Sie, wie Sie mit PHP E-Mail senden und empfangen können. Damit Sie mit den Funktionen arbeiten können, die in diesem Kapitel erklärt werden, muss Ihr PHP-Server so konfiguriert werden, dass er IMAP unterstützt. Darüber hinaus müssen Ihre PHP-Skripts auf SMTP- (Simple Mail Transfer Protocol) und IMAP-Dienste (Interim Mail Access Protocol) zugreifen können. Sie sollten deshalb Ihren PHP-Systemadministrator fragen, bevor Sie versuchen, Probleme zu beheben, die Sie mit unserem Beispiel haben könnten. Das Problem könnte bei Ihrem PHP-Server und nicht bei Ihnen oder dem Beispiel liegen. E-Mail senden Die standardmäßige PHP-Konfiguration unterstützt das Senden von E-Mail per SMTP. Dies ist das Standardprotokoll, mit dem E-Mail von System zu System über das Internet übertragen wird. E-Mail-Nachrichten bestehen aus zwei Teilen: einer Reihe von Nachrichten-Headern (engl. message headers) und einem Körper (engl. body). Die Nachrichten-Header zeigen die Adresse, den Betreff der Nachricht und andere Informationen an. Der Körper enthält die Nachricht selbst. Um eine E-Mail-Nachricht per SMTP zu senden, wird die mail()-Funktion verwendet, die die folgende Form hat: mail(an, betreff, koerper) Das Argument an gibt die E-Mail-Adresse des Empfängers an, betreff legt den Betreff der E-Mail-Nachricht fest, und koerper enthält den Körper der Nachricht. Üblicherweise wird in einer E-Mail-Nachricht auch die E-MailAdresse des Absenders angegeben. Zu diesem Zweck wird die folgende Form der mail()-Funktion verwendet: mail(an, betreff, koerper, header) Dabei gibt header die zusätzlichen E-Mail-Header an, wie beispielsweise den Von:-Header. Das folgende Beispiel zeigt, wie eine E-Mail-Nachricht gesendet wird, die einen Header enthält, der die E-Mail-Adresse des Absenders angibt: mail("[email protected]", "Dies ist der Betreff der Nachricht", "Dies ist der Körper einer sehr kurzen Nachricht", "Von: [email protected]") Sie können mehrere Empfänger angeben, indem Sie benachbarte Empfänger jeweils durch ein Komma trennen: Kapitel 12: E-Mail senden und empfangen 283 mail("[email protected],[email protected]", "Dies ist der Betreff der Nachricht", "Dies ist der Körper einer sehr kurzen Nachricht", "Von: [email protected]") Die mail()-Funktion gibt true zurück, wenn der SMTP-Server die Nachricht annimmt; andernfalls gibt sie false zurück. Denken Sie daran, dass die Annahme durch den SMTP-Server nicht die Auslieferung einer E-Mail an den Empfänger bedeutet. Ebenso, wie es keine absolut sichere Methode gibt, um zu verifizieren, dass der Empfänger eine E-Mail gelesen, verstanden und ihrem Inhalt zugestimmt hat, gibt es keine absolut sichere Methode, um zu prüfen, ob eine Nachricht ausgeliefert worden ist. Einige SMTP-Server haben Probleme mit Adressen und Headern, die am Ende Whitespace-Zeichen enthalten. Falls Ihr Skript davon abhängt, dass der Benutzer diese Werte eingibt, sollten Sie die Eingaben mit der trim()-Funktion bearbeiten. Ein Beispiel: mail(trim($an), trim($quelle), $koerper, "Von: " . trim($von)) 1-Minuten-Test ● Mit welcher PHP-Funktion wird E-Mail per SMTP gesendet? ● Mit welchem Zeichen werden mehrere Empfängeradressen getrennt, wenn eine E-Mail mit PHP versendet wird? Frage an den Experten Frage: Ist es möglich, mit PHP E-Mail-Nachrichten zu senden, die Anhänge (engl. attachments) enthalten? Antwort: Ja, aber die PHP-Library enthält keine Funktionen, die diese Aufgabe erleichtern. Wenn der Anhang nicht nur aus einfachem Text besteht, müssen Sie den Anhang im MIME-Format (Multipurpose Internet Mail Extensions) codieren. Dann können Sie die MIME-codierten Daten in spezielle Header einfügen. Verschiedene Programmierer und Autoren haben PHP-Funktionen und -Klassen geschrieben, mit denen dieser Prozess vereinfacht werden kann. Weitere Informationen über Anhänge und MIME finden Sie unter http://www.phpbuilder.com. ● mail() ● mit einem Komma 12 284 PHP 4 IT-Tutorial Projekt 12–1: Skript zur Übermittlung von E-Mail-Daten mailform.php mailfrm1.html mailfrm2.html In diesem Projekt werden Sie ein Skript erstellen, das Daten mit einem HTML-Formular erhebt und sie per E-Mail an den eingegebenen Benutzer sendet. Das Skript ist so aufgebaut, dass es mit HTML-Formularvariablen gesteuert werden kann. Sie können eine Reihe von HTML-Formularen erstellen, die dieses Skript verwenden, ohne dass Sie das Skript ändern müssten. Projektziele ● Demonstrieren, wie E-Mail mit PHP versandt wird ● Zeigen, wie ein wiederverwendbares Skript erstellt wird, das HTML-Formulardaten verarbeitet Schritt für Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen mailform.php, und laden Sie diese Datei auf Ihren PHP-Server herauf: <?php $body = ""; foreach ($_POST as $name=>$value) { $body = $body . "$name=$value\n"; } mail($formular_an, $formular_betreff, $body, "Von: " . $formular_von); header("Location: $formular_url"); ?> 2. Nehmen Sie sich Zeit, um das PHP-Skript zu studieren. Das Skript greift mittels des assoziativen Arrays $_POST_ auf die Werte der Formularfelder zu. Es fasst die Werte aller Felder in der Stringvariablen $body zusammen, mit der der Wert des E-Mail-Nachrichtenkörpers gesetzt wird. Beachten Sie auch die anderen Formularvariablen, formular_an, formular_von und formular_betreff. Indem Sie die Werte der zugehörigen Formular-Controls setzen, können Sie die E-Mail-Adresse des Absenders, des Empfängers und der Betreffzeile der E-Mail-Nachricht festlegen. Kapitel 12: E-Mail senden und empfangen 285 Das Skript verwendet die PHP-header()-Funktion, um den HTTP-Header an den Browser zu übertragen. Der Location-Header bewirkt, dass der Browser das Dokument von dem angegebenen URL einliest und anzeigt. Der URL selbst wird durch ein verborgenes Feld des HTML-Formulars angegeben, das die Daten an das Skript überträgt. Indem Sie den Wert dieses Felds setzen, können Sie die Seite festlegen, die dem Benutzer angezeigt wird, nachdem die Formulardaten verarbeitet worden sind. Üblicherweise enthält eine solche Seite eine Nachricht, in der dem Benutzer für den Input oder die Transaktion gedankt wird. 3. Speichern Sie die folgende HTML-Seite unter dem Dateinamen mailfrm1.html, und laden Sie diese Datei auf Ihren Server in dasselbe Verzeichnis wie die Datei mailform.php herauf: <html> <head> <title>mailfrm1.html</title> </head> <body> <form method="POST" action="mailform.php"> <h2>Formular zur Übermittlung von E-Mail-Daten</h2> Geben Sie hier Ihre Daten ein: <br> <input type="TEXT" name="daten" size="24"> <br><br> <input type="SUBMIT" value="Absenden"> <input type="HIDDEN" name="formular_an" value="[email protected]"> <input type="HIDDEN" name="formular_von" value="[email protected]"> <input type="HIDDEN" name="formular_betreff" value="Der Betreff"> <input type="HIDDEN" name="formular_url" value="mailfrm2.html"> </form> </body> </html> 4. Beachten Sie, dass das HTML-Formular nur ein einziges Feld für Benutzereingaben namens daten enthält. Das Skript kann jedoch so viele Felder verarbeiten, wie Sie definieren. 12 286 PHP 4 IT-Tutorial 5. Speichern Sie die folgende HTML-Seite unter dem Dateinamen mailfrm2.html, und laden Sie diese Datei auf Ihren Server in dasselbe Verzeichnis wie die Datei mailform.php herauf: <html> <head> <title>mailfrm2.html</title> </head> <body> <h2>E-Mail-Empfangsquittung</h2> Danke! Ihre Daten sind übermittelt worden! </body> </html> 6. Geben Sie den URL von mailfrm1.html in das Adressfeld Ihres Webbrowsers ein. Der Browser zeigt den folgenden Bildschirm an: Abbildung 12.1 Das E-Mail-Eingabeformular 7. Geben Sie Daten in das Formular ein, und klicken Sie auf die SUBMITSchaltfläche (ABSENDEN). Der Browser sollte den folgenden Bildschirm anzeigen: Kapitel 12: E-Mail senden und empfangen 287 Abbildung 12.2 Die Übermittlungsbestätigung 8. Die E-Mail, die der Empfänger erhält, sollte etwa folgendermaßen aussehen: Date: Sun, 15 Apr 2005 16:27:11 -0700 From: [email protected] To: [email protected] Subject: The Subject daten=Dies sind meine Eingabedaten. [email protected] [email protected] formular betreff=Der Betreff formular_url=mailfrm2.html E-Mail empfangen In diesem Abschnitt werden die grundlegenden Verfahren beschrieben, mit denen E-Mail-Nachrichten per IMAP, dem Interim Mail Access Protocol, empfangen werden können. Leider ist das Empfangen von E-Mail etwas komplexer als das Senden von E-Mail. Deshalb ist dieser Abschnitt wesentlich länger als der vorangegangene. Außerdem gehört IMAP im Gegensatz zu SMTP nicht zur PHP-Standardkonfiguration. Deshalb werden die Beispiele in diesem Abschnitt nur funktionieren, wenn Ihr PHP-Administrator PHP so konfiguriert hat, dass es mit IMAP arbeitet. 12 288 PHP 4 IT-Tutorial Eine Mailbox öffnen Der Zugriff auf einen IMAP-Server erfolgt ähnlich wie der Zugriff auf eine Datei. Zunächst müssen Sie eine Verbindung zu einem Server öffnen. Dann können Sie Anfragen an den Server senden und dessen Antworten empfangen. Wenn die Übertragung beendet ist, müssen Sie die Verbindung schließen. Mit der imap_open()-Funktion können Sie eine Verbindung zu einem IMAP-Server öffnen. Die Funktion hat die folgende Form: imap_open(mailbox, userid, passwort) Das Argument mailbox besteht aus vier Einträgen: ● dem Host-Namen oder der IP-Adresse des IMAP-Servers ● dem Protokoll, das verwendet werden soll (IMAP) ● dem Port, der für die Verbindung zu dem Server verwendet werden soll (im Allgemeinen 143) ● der Mailbox, die geöffnet werden soll (im Allgemeinen INBOX) Das Argument verwendet mehrere Trennzeichen, um die Einträge zu trennen. Ein typischer Wert dieses Arguments könnte beispielsweise folgendermaßen aussehen: {localhost/imap:143}INBOX In diesem Beispiel wird localhost als Host-Name verwendet. Diese Angabe beschreibt den Fall, dass der PHP-Server und der IMAP-Server auf demselben Host ausgeführt werden. Andernfalls sollten Sie den Namen des Hosts angeben, auf dem der IMAP-Server ausgeführt wird. Ein Beispiel: {mail.osborne.com/imap:143}INBOX Die restlichen Argumente von imap_open(), userid und passwort geben die Benutzer-ID und das Passwort an, mit denen der Zugriff auf den IMAP-Server erfolgt. Ähnlich wie die fopen()-Funktion ein Handle zurückgibt, mit dem Sie auf eine Datei zugreifen können, gibt die imap_open()-Funktion ein Handle zurück, das den Zugriff auf den IMAP-Server ermöglicht. Wenn PHP keine Verbindung zu dem IMAP-Server herstellen kann, gibt imap_open() den Wert false zurück. Kapitel 12: E-Mail senden und empfangen 289 Tipp Wenn ein Skript mit der Nachricht Call to undefined function: imap_open() beendet wird, ist PHP nicht für den Einsatz von IMAP konfiguriert worden. Ziehen Sie Ihren PHP-Administrator zu Rate, um dieses Problem zu lösen. Das folgende Beispiel zeigt, wie die Funktion imap_open() aufgerufen und wie ihr Rückgabewert getestet wird: function open_mailbox($server, $userid, $password) { echo "\n\n"; echo "<h4>IMAP-Verbindung zu $server öffnen.</h4>"; $handle = imap_open($server . "INBOX", $userid, $password); if ($handle === false) { echo "Öffnen der IMAP-Mailbox INBOX gescheitert"; print_error_stack(); die(); } return $handle; } Das Beispiel wird in Form einer benutzerdefinierten Funktion namens open_mailbox() präsentiert. Sie können diese Funktion in Ihren eigenen PHPSkripts verwenden. Die open_mailbox()-Funktion erzeugt einen Output, der Ihnen hilft, den Ablauf eines Programms zu verfolgen. Außerdem führt sie einige Fehlerprüfungen durch. Wenn Sie open_mailbox() benutzen, anstatt imap_open() direkt aufzurufen, können Sie etwas Arbeit einsparen. Natürlich können Sie, wenn Ihnen der Output oder die Fehlerprüfungen von open_mailbox() nicht gefallen, die Funktion ändern, eine eigene benutzerdefinierte Funktion schreiben oder imap_open() direkt aufrufen. Tipp Wenn Sie sich nicht so genau an benutzerdefinierte PHP-Funktionen erinnern, sollten Sie noch einmal Kapitel 7 lesen. 12 290 PHP 4 IT-Tutorial Beachten Sie, dass open_mailbox() die Funktion print_error_stack() aufruft, wenn imap_open() scheitert. Die Funktion print_error_stack() ist eine weitere benutzerdefinierte Funktion. Sie ist folgendermaßen definiert: function print_error_stack() { echo "\n\n"; echo "<h4>IMAP-Fehler-Stack</h4>"; $errs = imap_errors(); if ($errs) { foreach ($errs as $key=>$value) { echo "\n$key: $value"; } } } Die Funktion ruft die IMAP-Library-Funktion imap_errors() auf, die ein Array mit Fehlermeldungen zurückgibt. Dann durchläuft sie mit einem foreach-Befehl das Array elementweise und gibt alle Fehler aus. Ordner wechseln Zusätzlich zu dem standardmäßigen INBOX-Ordner kann ein Benutzer unter IMAP Ordner definieren, mit denen er Nachrichten speichern und ordnen kann. Zu jedem gegebenen Zeitpunkt ist einer der IMAP-Ordner – INBOX oder ein anderer Ordner – der aktuelle Ordner. Nachdem Sie eine Verbindung zu einem IMAP-Server hergestellt haben, können Sie den Server anweisen, einen anderen Ordner als aktuellen Ordner zu verwenden. Das folgende Beispiel ist eine benutzerdefinierte Funktion, die einen solchen Wechsel ausführt: function switch_to_folder($handle, $server, $prefix, $folder) { if ($folder == "INBOX") { $folder = $server . "INBOX"; } else { $folder = $server . $prefix . "INBOX." . $folder; } echo "\n\n"; echo "<h4>Wechsel zu Ordner $folder</h4>"; $ok = imap_reopen($handle, $folder); Kapitel 12: E-Mail senden und empfangen 291 if ($ok === false) { echo "\nÖffnen des angegebenen Ordners gescheitert"; print_error_stack(); } } Die benutzerdefinierte Funktion ruft die IMAP-Funktion imap_reopen() auf, die zwei Argumente hat: das Handle, das von imap_open() (oder von der benutzerdefinierten Funktion open_mailbox(), die imap_open() aufruft) zurückgegeben wird, und den Namen des Ordners, der geöffnet werden soll. Die benutzerdefinierte Funktion hat neben dem Handle mehrere andere Argumente, aus denen sie den Ordnernamen zusammensetzt. Beispielsweise könnten Sie switch_to_folder() folgendermaßen aufrufen: switch_to_folder("{localhost/imap:143}", "~/mail/", "derOrdner") Hinweis Es ist üblich, IMAP-Ordner so zu benennen, dass dem Ordnernamen die Präfixe ~/mail und INBOX vorangestellt werden – eine Konvention, die auch von switch_to_folder() und dem Beispielaufruf vorausgesetzt wird. Jedoch kann ein Systemadministrator andere Regeln für die Namensbildung festlegen. Wenn Sie beim Arbeiten mit switch_to_folder() Schwierigkeiten haben, sollten Sie die Benennungsregeln mit Ihrem Systemadministrator abstimmen. Eine Mailbox schließen Wenn die Arbeit mit dem IMAP-Server beendet ist, sollten Sie die Verbindung schließen, so wie Sie eine Datei schließen, die Sie nicht mehr benötigen. Das folgende Beispiel zeigt eine benutzerdefinierte Funktion zum Schließen einer IMAP-Verbindung: function close_mailbox($handle) { echo "\n\n"; echo "<h4>IMAP-Verbindung schließen</h4>"; $ok = imap_close($handle); if ($ok === false) { echo "\nSchließen der Mailbox gescheitert"; print_error_stack(); 12 292 PHP 4 IT-Tutorial } } Die Funktion verwendet die IMAP-Library-Funktion imap_close() sowie die benutzerdefinierte Funktion print_error_stack(), die weiter oben gezeigt wurde. Informationen über eine Mailbox abfragen Nach dem Öffnen einer IMAP-Verbindung können Sie auf Informationen zugreifen, die die aktuelle Mailbox beschreiben. Das folgende Beispiel zeigt eine benutzerdefinierte Funktion, die die Anzahl der Nachrichten in der aktuellen Mailbox zurückgibt: function get_message_count($handle) { return imap_num_msg($handle); } Die benutzerdefinierte Funktion ruft einfach die IMAP-Library-Funktion imap_num_ msg() auf. Sie können den Code der benutzerdefinierten Funktion jedoch erweitern, indem Sie beispielsweise einen Befehl hinzufügen, der die Anzahl der Nachrichten ausgibt. Das folgende Beispiel zeigt eine komplexere benutzerdefinierte Funktion, die diverse Informationen über die aktuelle Mailbox ausgibt: function print_mailbox_status($handle) { echo "\n\n"; echo "<h4>Mailbox-Status</h4>"; $n = imap_num_msg($handle); echo "\nDie Mailbox enthält $n Nachrichten."; $n = imap_num_recent($handle); echo "\nDie Mailbox enthält $n neue Nachrichten."; echo "\n\n"; $mailbox_objekt = imap_mailboxmsginfo($handle); if ($mailbox_objekt) { $mailbox_array = get_object_vars($mailbox_objekt); foreach ($mailbox_array as $key=>$value) { echo "\n$key: $value"; } } } Kapitel 12: E-Mail senden und empfangen 293 Diese Funktion gibt die Anzahl der Nachrichten und die Anzahl der neuen Nachrichten in der Mailbox aus. Danach zeigt sie eine Reihe von Informationen an, unter anderem: ● das Datum, an dem die Mailbox zuletzt geändert wurde ● der Name der Mailbox ● die Anzahl der Nachrichten in der Mailbox ● die Anzahl der neuen Nachrichten in der Mailbox ● die Anzahl der ungelesenen Nachrichten in der Mailbox ● die Anzahl der gelöschten Nachrichten in der Mailbox ● die Mailboxgröße in Bytes Der Rückgabewert der IMAP-Library-Funktion imap_mailboxmsginfo() wird der Variablen $mailbox_objekt zugewiesen. Die Variable ist vom Typ object. In Kapitel 15 werden Objekte und das Arbeiten mit ihnen beschrieben. Jedoch können Sie diesen Wert auch verwenden, ohne das Arbeiten mit Objekten zu beherrschen. Wenn Sie diesen Wert als Argument an die Funktion get_object_vars() übergeben, gibt diese ein assoziatives Array zurück, das die Daten des Objekts enthält. Die benutzerdefinierte Funktion print_mailbox_status() verwendet dieses Verfahren, um Mailbox-Statusinformationen abzufragen und auszugeben. Das folgende Beispiel zeigt einen typischen Output der print_mailbox_status()-Funktion: Mailbox Status INBOX enthält 3 Nachrichten. INBOX enthält 0 neue Nachrichten. Unread: 0 Deleted: 0 Nmsgs: 3 Size: 1078 Date: Fri, 25 May 2001 08:57:53 -0700 (PDT) Driver: imap Mailbox: {localhost.localdomain:143/imap/user="bmccarty"}INBOX Recent: 0 Die benutzerdefinierte Funktion dump_mailbox_status() verwendet einen anderen Ansatz, um mit imap_mailboxmsginfo() umzugehen: 12 294 PHP 4 IT-Tutorial function dump_mailbox_status($handle) { echo "\n\n"; echo "<h4>Mailbox-Status-Ausgabe</h4>"; echo "\n\n"; $mailbox_objekt = imap_mailboxmsginfo($handle); print_r($mailbox_objekt); } Die PHP-Funktion print_r() gibt den Wert eines Objekts aus. Dieser Ansatz ist viel einfacher als der von print_mailbox_status(), aber das Format des Outputs lässt sich wesentlich schlechter lesen: Mailbox-Status-Ausgabe stdClass Object ( [Unread] => 0 [Deleted] => 0 [Nmsgs] => 3 [Size] => 1078 [Date] => Fri, 25 May 2001 08:57:53 -0700 (PDT) [Driver] => imap [Mailbox] => {localhost.localdomain:143/imap/user="bmccarty"}INBOX [Recent] => 0 ) Tipp Wir präsentieren die IMAP-Funktionen deshalb zusammen mit den benutzerdefinierten Funktionen, damit Sie die benutzerdefinierten Funktionen als IMAP-Programmkonstruktionskit einsetzen können. Die benutzerdefinierten Funktionen erzeugen Output und Fehlermeldungen, die Ihnen helfen können, korrekte Programme zu entwickeln. Wenn das Programm tut, was Sie wollen, können Sie die benutzerdefinierten Funktionen anpassen, den Output umformatieren oder andere Änderungen durchführen. Dabei sollten Sie auch in Betracht ziehen, dem Funktionsaufruf ein @-Zeichen voranzustellen, damit Ihre Seiten nicht durch Standardfehlermeldungen verunstaltet werden, wenn etwas schief gehen sollte. Kapitel 12: E-Mail senden und empfangen 295 Eine Liste von Nachrichten abfragen Das folgende Beispiel zeigt eine benutzerdefinierte Funktion, die eine Liste der Nachrichten in dem aktuellen Ordner ausgibt: function list_messages($handle) { echo "\n\n"; echo "<h4>Nachrichten-Header in Aktuelle Mailbox</h4>"; $headers = imap_headers ($handle); if ($headers == false) { echo "\nAuflisten der Nachrichten gescheitert"; print_error_stack(); } else { foreach ($headers as $key=>$value) { echo "\n$value"; } } } Die benutzerdefinierte Funktion ruft die IMAP-Funktion imap_headers() auf, die ein Array zurückgibt, dessen Elemente jeweils eine Nachricht in dem aktuellen Ordner beschreiben. Mit Nachrichten-IDs arbeiten Eine Besonderheit von IMAP besteht darin, dass jede Nachricht in einem Ordner sowohl über eine Nummer als auch über eine ID verfügt. Die Nummer repräsentiert die Position der Nachricht in dem Ordner. Dieser Wert kann sich ändern, wenn Nachrichten in den Ordner eingefügt oder aus ihm gelöscht werden. Die ID einer Nachricht ändert sich dagegen niemals. IMAP stellt Funktionen zur Verfügung, mit denen Sie die ID einer Nachricht bestimmen können, wenn ihre Nummer bekannt ist, und umgekehrt. Die folgenden benutzerdefinierten Funktionen rufen die entsprechenden IMAP-Library-Funktionen auf: function get_message_id($handle, $num) { return imap_uid($handle, $num); } 12 296 PHP 4 IT-Tutorial function get_message_num($handle, $id) { return imap_msgno($handle, $id); } Informationen über eine Nachricht abfragen Eine Beschränkung der imap_headers()-Funktion, die in der benutzerdefinierten Funktion list_messages() verwendet wird, besteht darin, dass sie die Eigenschaften einer Nachricht nicht so in separate Felder aufteilt, dass ein Skript leicht auf sie zugreifen kann. Die IMAP-Library-Funktion imap_fetch_overview() gibt ein assoziatives Array zurück, das eine Nachricht beschreibt. Das folgende Beispiel zeigt eine benutzerdefinierte Funktion, die imap_fetch_overview() verwendet, um Informationen über eine Nachricht auszugeben: function print_overview($handle, $num) { echo "\n\n"; echo "<h4>Nachricht $n: Überblick</h4>"; $message_nums = "" . $num; $nachrichten = imap_fetch_overview($handle, $message_nums, 0); foreach ($nachrichten as $nachricht) { $n = $nachricht->msgno; foreach ($nachricht as $eigenschaft=>$wert) { echo "\n$eigenschaft: $wert"; } } } Im zweiten Argument der imap_fetch_overview()-Funktion können Sie eine Liste oder einen Bereich von Nachrichten angeben, für die die Funktion einen Überblick zurückgeben soll. Die benutzerdefinierte Funktion print_overview() bildet eine Liste mit einem Element und übergibt die Liste an imap_fetch_overview(). Der Output enthält die folgenden Informationen: ● den Betreff der Nachricht ● den Namen und die E-Mail-Adresse des Absenders ● das Datum, an dem die Nachricht gesendet wurde ● die Nachrichtennummer Kapitel 12: E-Mail senden und empfangen ● die Nachrichten-ID ● die Größe der Nachricht (in Bytes) ● Flags, die anzeigen, ob ● die Nachricht neu ist ● die Nachricht gelesen wurde ● die Nachricht beantwortet wurde ● die Nachricht zum Löschen gekennzeichnet wurde ● die Nachricht ein Entwurf ist 297 Den Körper einer Nachricht abrufen Der Körper einer Nachricht enthält den eigentlichen Inhalt der Nachricht. Das folgende Beispiel zeigt ein Paar benutzerdefinierter Funktionen, die den Körper einer Nachricht ausgeben: function print_body_by_num($handle, $num) { $id = get_message_id($handle, $num); print_body_by_id($handle, $id); } function print_body_by_id($handle, $id) { echo "\n\n"; $num = get_message_num($handle, $id); echo "<h4>Nachrichten-ID $id (Nummer $num) Body</h4>"; $s = imap_body($handle, $id, FT_UID); echo "\n$s"; } Mit der einen Funktion können Sie die Nachricht mit Hilfe Ihrer Nummer angeben, mit der anderen können Sie zu diesem Zweck die ID der Nachricht verwenden. Beachten Sie, wie print_body_by_num() implementiert wurde. Die Funktion wandelt die Nachrichtennummer in eine Nachrichten-ID um und ruft dann ihre Schwesterfunktion, print_body_by_id(), auf, die ihrerseits die IMAP-Funktion imap_body() aufruft. Nachrichten-Header abrufen Nachrichten-Header (engl. message headers) enthalten wichtige Informationen, die im Allgemeinen nicht im Körper der Nachricht erscheinen, wie beispielsweise 12 298 PHP 4 IT-Tutorial das Datum und der Betreff der Nachricht. Das folgende Beispiel zeigt eine benutzerdefinierte Funktion, die den Header einer Nachricht ausgibt, wenn die Nachrichtennummer gegeben ist. function print_headers($handle, $num) { echo "\n\n"; echo "<h4>Nachricht $n: Header</h4>"; $header_object = imap_headerinfo($handle, $num); $headers = get_object_vars($header_object); foreach ($headers as $property=>$value) { if (!is_array($value)) { echo "\n$property: $value"; } else { foreach ($value as $subvalue) { echo "\n$property: "; $subvalues = get_object_vars($subvalue); foreach ($subvalues as $item=>$itemvalue) { echo "\n $item=>$itemvalue"; } } } } } Wie die benutzerdefinierte Funktion print_mailbox_status() verwendet auch print_ headers() die Funktion get_object_vars(), um aus einem Objekt ein assoziatives Array zu erzeugen. Das Objekt, das von der IMAPLibrary-Funktion imap_headerinfo() zurückgegeben wird, enthält die folgenden Informationen: ● das Datum, an dem die Nachricht abgesandt wurde ● den Betreff der Nachricht ● falls zutreffend: die ID der Nachricht, die mit dieser Nachricht beantwortet wird ● Nachrichten-Flags, ähnlich den Flags, die von imap_fetch_overview() zurückgegeben werden Kapitel 12: E-Mail senden und empfangen ● 299 Namen und E-Mail-Adressen ● des Absenders ● der Antwort auf die Nachricht (reply-to; falls angegeben) ● des Empfängers ● möglicher Empfänger von Kopien (cc:) ● möglicher Empfänger von Blindkopien (bcc:), falls vorhanden Mehrere Elemente des assoziativen Arrays enthalten Array-Werte. Das Array kann mit einer verschachtelten Schleife elementweise durchlaufen werden, um die Werte dieser Elemente anzuzeigen. Bei weniger anspruchsvollen Anwendungen formatiert die dump_headers()Funktion denselben Output wie print_headers, verwendet dabei aber die print_r()-Funktion, die einen weniger lesbaren Output erzeugt: function dump_headers($handle, $num) { $headers = imap_headerinfo($handle, $num); echo "\n\n"; echo "<h4>Nachricht $n: Header-Dump</h4>"; print_r($headers); } Eine Nachricht zum Löschen kennzeichnen Um eine IMAP-Nachricht zu löschen, müssen Sie sie zunächst die Nachricht markieren, die gelöscht werden soll. Nachrichten, die zum Löschen markiert sind, aber noch nicht entfernt worden sind, stehen immer noch für einen Zugriff zur Verfügung. Mit den beiden folgenden benutzerdefinierten Funktionen können Sie eine Nachricht per Nachrichtennummer oder per ID löschen: function delete_message_by_num($handle, $num) { $id = get_message_id($handle, $num); delete_message_by_id($handle, $id); } function delete_message_by_id($handle, $id) { echo "\n\n"; $num = get_message_num($handle, $id); 12 300 PHP 4 IT-Tutorial echo "<h4>Nachrichten-ID $id (Nummer $num) zum Löschen markieren</h4>"; $ok = imap_delete($handle, $id, FT_UID); if ($ok == false) { echo "\nLöschmarkierung der Nachricht gescheitert"; print_error_stack(); } } Mit der folgenden Funktion können Sie zum Löschen markierte Nachrichten endgültig entfernen: function expunge_messages($handle) { echo "\n\n"; echo "<h4>Zum Löschen markierte Nachrichten entfernen</ h4>"; $ok = imap_expunge($handle); if ($ok == false) { echo "\Löschen der Nachrichten gescheitert"; print_error_stack(); } } Frage an den Experten Frage: Mein Internet Service Provider stellt einen POP-Server anstelle eines IMAP-Servers zur Verfügung. Kann ich mit PHP auf meine POP-Mailbox zugreifen? Antwort: Ja. Tatsächlich können Sie zu diesem Zweck ebenfalls die IMAP-Library verwenden. Öffnen Sie einfach eine Verbindung zu dem POP-Server und geben Sie dabei eine POP-Mailbox an: $mbox = imap_open ("{localhost/pop3:110}INBOX", $user_id, $password); Der Host-Name, das Protokoll und die Portnummer entsprechen den Werten, die Sie für eine Verbindung mit einem IMAP-Server verwenden. Anstelle des IMAP-Servers müssen Sie den Mailbox-Namen verwenden, der von Ihrem Systemadministrator festgelegt wurde. Kapitel 12: E-Mail senden und empfangen 301 Sie können die IMAP-Library auch für eine Verbindung zu einem News-Server nutzen, die mit dem NNTP (Network News Transfer Protocol) arbeitet. Die Verbindung wird mit dem folgenden Befehl hergestellt: $nntp = imap_open("{localhost/ nntp:119}comp.test","",""); Unter http://www.php.net finden Sie im PHP-Online-Handbuch weitere Informationen darüber, wie Sie mit den IMAP-Library-Funktionen auf einen POP- oder News-Server zugreifen können. 1-Minuten-Test ● Was müssen Sie tun, bevor Sie auf eine IMAP-Mailbox zugreifen können? ● Verschwinden IMAP-Nachrichten, wenn sie zum Löschen markiert werden? ● Welcher Bezeichner ist dauerhafter: eine IMAP-Nachrichtennummer oder eine Nachrichten-ID? ● Welche Informationen sind in einem E-Mail-Nachrichten-Header enthalten? Projekt 12–2: Ein E-Mail-Browser reader.php reader.inc reader.html ● ● ● ● In diesem Projekt werden Sie ein Skript erstellen, mit dem Sie in einem IMAP-Ordner browsen können. Projektziele ● Demonstrieren, wie IMAP-Funktionen mit den benutzerdefinierten Funktionen aufgerufen werden können, die in diesem Kapitel beschrieben wurden ● Demonstrieren, wie der Zugriff auf IMAP-Ordner und Nachrichten erfolgt Eine Verbindung zu dem IMAP-Server herstellen. Nein, IMAP-Nachrichten bleiben in dem Ordner, bis sie entfernt werden. Eine Nachrichten-ID. Das Datum, an dem die Nachricht gesendet wurde, der Betreff der Nachricht, die Nachrichten-ID der Nachricht, auf die diese Nachricht antwortet (falls sie das tut), Nachrichten-Flags und die Namen und E-Mail-Adressen der Personen, die von dieser E-Mail betroffen sind, wie beispielsweise der Absender und der Empfänger. 12 302 PHP 4 IT-Tutorial Schritt für Schritt 1. Speichern Sie das folgende PHP-Skript unter dem Dateinamen reader.php, und laden Sie diese Datei auf Ihren PHP-Server herauf: <?php require("reader.inc"); echo "<pre>"; $server = "{" . $host . "/imap:143}"; $imap = open_mailbox($server, $userid, $password); list_messages($imap); $n = get_message_count($imap); for ($i = 1; $i <= $n; $i++) { print_headers($imap, $i); print_body_by_num($imap, $i); } close_mailbox($imap); echo "</pre>"; ?> 2. Speichern Sie das folgende längere PHP-Skript unter dem Dateinamen reader.inc, und laden Sie diese Datei auf Ihren Server in dasselbe Verzeichnis wie die Datei reader.php herauf: function open_mailbox($server, $userid, $password) { echo "\n\n"; echo "<h4>IMAP-Verbindung zu $server öffnen</h4>"; $handle = imap_open($server . "INBOX", $userid, $password); if ($handle === false) { echo "Öffnen der IMAP-Mailbox INBOX gescheitert"; print_error_stack(); die(); } return $handle; } function print_error_stack() { Kapitel 12: E-Mail senden und empfangen 303 echo "\n\n"; echo "<h4>IMAP-Fehler-Stack</h4>"; $errs = imap_errors(); if ($errs) { foreach ($errs as $key=>$value) { echo "\n$key: $value"; } } } function list_messages($handle) { echo "\n\n"; echo "<h4>Nachrichten-Header in INBOX</h4>"; $headers = imap_headers($handle); if ($headers == false) { echo "\nAuflisten der Nachrichten gescheitert"; print_error_stack(); } else { foreach ($headers as $key=>$value) { echo "\n$value"; } } } function get_message_count($handle) { return imap_num_msg($handle); } function print_headers($handle, $num) { echo "\n\n"; echo "<h4>Nachricht $n: Header</h4>"; $header_object = imap_headerinfo($handle, $num); $headers = get_object_vars($header_object); foreach ($headers as $property=>$value) { if (!is_array($value)) 12 304 PHP 4 IT-Tutorial { echo "\n$property: $value"; } else { foreach ($value as $subvalue) { echo "\n$property: "; $subvalues = get_object_vars($subvalue); foreach ($subvalues as $item=>$itemvalue) { echo "\n $item=>$itemvalue"; } } } } } function print_body_by_num($handle, $num) { $id = get_message_id($handle, $num); print_body_by_id($handle, $id); } function print_body_by_id($handle, $id) { echo "\n\n"; $num = get_message_num($handle, $id); echo "<h4>Nachrichten-ID $id (Nummer $num) Body</h4>"; $s = imap_body($handle, $id, FT_UID); echo "\n$s"; } function get_message_id($handle, $num) { return imap_uid($handle, $num); } function get_message_num($handle, $id) { return imap_msgno($handle, $id); } function close_mailbox($handle) { Kapitel 12: E-Mail senden und empfangen 305 echo "\n\n"; echo "<h4>IMAP-Verbindung schließen</h4>"; $ok = imap_close($handle); if ($ok === false) { echo "\nSchließen der Mailbox gescheitert"; print_error_stack(); } } ?> 3. Speichern Sie die folgende HTML-Seite unter dem Dateinamen reader.html, und laden Sie diese Datei auf Ihren PHP-Server in dasselbe Verzeichnis wie die Skripts reader.php und reader.inc herauf: <html> <head> <title>reader.html</title> </head> <body> <form method="POST" action="reader.php"> <h2>Formular für den Zugriff auf eine IMAP-Mailbox</h2> Benutzer-ID: <br> <input type="TEXT" name="userid" size="24"> <br> Passwort: <br> <input type="password" name="password" size="24"> <br> Server: <br> <input type="TEXT" name="host" size="24" value="localhost"> <br><br> <input type="SUBMIT" value="Absenden"> </form> </body> </html> 12 306 PHP 4 IT-Tutorial 4. Nehmen Sie sich Zeit, um die HTML-Seite reader.html zu studieren. Beachten Sie, dass der Benutzer auf dieser Seite die Informationen eingeben kann, die mindestens benötigt werden, um auf eine IMAP-Mailbox zugreifen zu können: den Host-Namen des IMAP-Servers sowie die Benutzer-ID und das Passwort des Benutzers. 5. Studieren Sie auch das PHP-Skript reader.php. Beachten Sie, wie einfach das Skript ist. Das Skript ● öffnet eine Verbindung zu dem IMAP-Server, ● listet die Nachrichten in dem Standardordner auf, ● fragt die Anzahl der Nachrichten in dem Standardordner ab, ● druckt den Header und den Body jeder Nachricht und ● schließt die Verbindung zu dem IMAP-Server. Beachten Sie, dass das Skript einen require-Befehl verwendet, um den Inhalt der Datei reader.inc einzubinden. 6. Studieren Sie das Skript reader.inc. Dieses Skript besteht nur aus einer Sammlung benutzerdefinierter Funktionen, die weiter oben in diesem Kapitel beschrieben wurden. Keine dieser Funktionen wurde verändert. Wenn Sie wissen, was diese Funktionen tun, müssen Sie sich nicht wirklich mit diesem Skript befassen. Sie können die Anwendung verstehen, indem Sie nur reader.php studieren. Um Ihnen zu helfen, eigene E-Mail-Skripts zu schreiben, wird auf der Website dieses Buches die Datei imap.inc zur Verfügung gestellt, die alle benutzerdefinierten Funktionen enthält, die in diesem Kapitel beschrieben wurden. Fügen Sie einfach eine Kopie dieser Datei in Ihr Skriptverzeichnis ein, schreiben Sie einen require-Befehl, um das Skript in Ihr Skript einzubinden, und rufen Sie die benutzerdefinierten Funktionen auf, die in diesem Skript definiert werden. 7. Geben Sie den URL von reader.html in das Adressfeld Ihres Webbrowsers ein. Die Anzeige des Browsers sollte Abbildung 12.3 ähneln. 8. Geben Sie die Informationen ein, die auf Ihren IMAP-Server zutreffen, und klicken Sie auf die SUBMIT-Schaltfläche (ABSENDEN). Das Skript sollte auf Ihre IMAP-Mailbox zugreifen und deren Inhalt anzeigen. Das Ergebnis sollte Abbildung 12.4 ähneln. Kapitel 12: E-Mail senden und empfangen 307 Abbildung 12.3 Das IMAP-Mailbox-Zugriffsformular 12 Abbildung 12.4 Der Inhalt der IMAP-Mailbox 308 PHP 4 IT-Tutorial Ordner manipulieren Mit der IMAP-Library können Sie nicht nur auf Ordner und Nachrichten zugreifen, sondern auch Ordner manipulieren. In diesem Abschnitt werden die entsprechenden Verfahren beschrieben. Vorhandene Ordner anzeigen Das folgende Beispiel zeigt eine benutzerdefinierte Funktion, die die verfügbaren IMAP-Ordner anzeigt: function list_folders($handle, $server, $prefix) { echo "\n\n"; echo "<h4>Liste der Ordner</h4>"; echo "\nServer=$server, Präfix=$prefix"; $folders = imap_listmailbox($handle, $server, $prefix . "*"); if ($folders == false) { echo "\nimap-listmailbox() gescheitert"; } else { foreach ($folders as $key=>$value) { echo "\n$key=>$value"; } } } Sie können diese Funktion beispielsweise mit den folgenden Argumenten aufrufen: list_folders($handle, "{localhost/imap:143}", "~/mail/") Das $handle-Argument ist natürlich der Wert, der von der Funktion zurückgegeben wurde, die die IMAP-Verbindung hergestellt hat. Wie bereits weiter oben in diesem Kapitel erklärt wurde, muss der Wert des $prefix-Arguments mit den Vorschriften zur Benennung von Ordnern übereinstimmen, die von dem IMAP-Administrator aufgestellt wurden. Kapitel 12: E-Mail senden und empfangen 309 Ordner erstellen Mit der folgenden Funktion können Sie einen neuen IMAP-Ordner erstellen: function create_folder($handle, $server, $prefix, $folder) { $folder = $server . $prefix . "INBOX." . $folder; echo "\n\n"; echo "<h4>Ordner $folder erstellen </h4>"; $ok = imap_createmailbox($handle, $folder); if ($ok === false) { echo "\nErstellen des Ordners gescheitert"; print_error_stack(); } } Das vierte Argument dieser Funktion legt den Namen des Ordners fest, der erstellt werden soll. Tipp Der Name eines IMAP-Ordners sollte nur Buchstaben, Ziffern und Unterstreichungszeichen enthalten. Wenn Sie einen Unterordner erstellen wollen, können Sie einen Punkt in den Ordnernamen einfügen. Der Punkt dient – ähnlich wie der Schrägstrich bei Dateisystempfaden – als Pfadtrennzeichen. Einen Ordner umbenennen Mit der folgenden benutzerdefinierten Funktion können Sie einen Ordner umbenennen: function rename_folder($handle, $server, $prefix, $old_folder, $new_folder) { $old_folder = $server . $prefix . "INBOX." . $old_folder; $new_folder = $server . $prefix . "INBOX." . $new_folder; echo "\n\n"; echo "<h4>Ordner $old_umbenennen in $new_folder</h4>"; $ok = imap_renamemailbox($handle, $old_folder, $new_folder); 12 310 PHP 4 IT-Tutorial if ($ok === false) { echo "\nUmbenennen des Ordners gescheitert"; print_error_stack(); } } Wie bereits erwähnt, müssen Sie möglicherweise das Verfahren anpassen, mit dem der Ordnername aus dem Host-Namen des Servers und dem Mailbox-Präfix gebildet wird. Einen Ordner löschen Mit der folgenden Funktion können Sie einen IMAP-Ordner löschen: function delete_folder($handle, $server, $prefix, $folder) { $folder = $server . $prefix . "INBOX." . $folder; echo "\n\n"; echo "<h4>Ordner $folder löschen</h4>"; imap_deletemailbox($handle, $folder); if ($ok === false) { echo "\nLöschen des Ordners gescheitert"; print_error_stack(); } } Achtung Im Gegensatz zu IMAP-Nachrichten, die in der Mailbox bleiben, bis sie entfernt werden, ist ein gelöschter IMAP-Ordner sofort und unwiderruflich weg. Sie sollten deshalb sehr vorsichtig vorgehen, wenn Sie Code schreiben, der Ordner löscht, oder wenn Sie Skripts verwenden, die solchen Code enthalten. Nachrichten in einen Ordner kopieren Mit IMAP können Sie eine Nachricht des aktuellen Ordners in einen anderen Ordner kopieren. Die folgende benutzerdefinierte Funktion führt diese Operation aus, wenn ihr die IMAP-Nachrichtennummer und der Zielordner angegeben werden: Kapitel 12: E-Mail senden und empfangen 311 function copy_message($handle, $prefix, $num, $folder) { $folder = $prefix . "INBOX." . $folder; echo "\n\n"; echo "<h4>Nachricht $num in Ordner $folder kopieren</h4>"; $message_nums = "" . $num; $ok = imap_mail_copy($handle, $message_nums, $folder); if ($ok === false) { echo "\nKopieren der Nachricht in den angegebenen Ordner gescheitert"; print_error_stack(); } } Beachten Sie, dass diese Funktion kein Argument hat, das den Host-Namen des Servers angibt. Weil IMAP-Server das Kopieren von Nachrichten von einem Server auf einen anderen nicht unterstützen, ist es beim Kopieren von IMAPNachrichten weder notwendig noch möglich, den Host-Namen des Servers anzugeben. Nachrichten in einen Ordner verschieben Das folgende Beispiel zeigt eine benutzerdefinierte Funktion, die eine IMAPNachricht aus dem aktuellen Ordner in einen anderen Ordner verschiebt, wenn ihr die IMAP-Nachrichtennummer und der Zielordner angegeben werden: function move_message($handle, $prefix, $num, $folder) { $folder = $prefix . "INBOX." . $folder; echo "\n\n"; echo "<h4>Nachricht $num in Ordner $folder verschieben</ h4>"; $message_nums = "" . $num; $ok = imap_mail_move($handle, $message_nums, $folder); if ($ok === false) { echo "\nVerschieben der Nachricht in den angegebenen Ordner gescheitert"; print_error_stack(); } } 12 312 PHP 4 IT-Tutorial Die ursprünglichen Nachrichten werden nur zum Löschen markiert und bleiben in der Mailbox, bis sie entfernt werden. Frage an den Experten Frage: In diesem Kapitel wurden viele IMAP-Funktionen erklärt. Gibt es noch andere IMAP-Funktionen, dir für mich nützlich sein könnten? Antwort: Die IMAP-Library enthält neben den Funktionen, die in diesem Kapitel beschrieben wurden, noch viele weitere Funktionen. Beispielsweise können Sie mit den Funktionen imap_search() und imap_scanmailbox() nach Nachrichten suchen, die bestimmte Kriterien erfüllen. Beispielsweise können Sie nach Nachrichten suchen, die in ihren Körpern einen bestimmten Text enthalten. Außerdem enthalten die IMAP-Funktionen, die in diesem Kapitel verwendet wurden, häufig Optionen und Fähigkeiten, die nicht vollständig beschrieben wurden. Weitere Informationen über die PHP-IMAP-Library finden Sie in dem PHP-Online-Handbuch unter www.php.net. Kapitel 12: E-Mail senden und empfangen 313 9Übungsaufgaben 1. Welches Protokoll wird benutzt, um Internet-Mail zu übertragen? 2. Wieso vereinfachen benutzerdefinierte Funktionen das Programmieren? 3. Schreiben Sie unter Verwendung der geeigneten benutzerdefinierten Funktion, die in diesem Kapitel beschrieben wurde, einen Befehl, der die IMAPNachricht Nummer 101 aus dem aktuellen Ordner in den Ordner "test" kopiert. Nehmen Sie an, dass der Wert der Variablen $mb das Handle einer offenen IMAP-Verbindung und die Variable $pfx das IMAP-Mailbox-Präfix enthält. 4. Schreiben Sie unter Verwendung der geeigneten benutzerdefinierten Funktion, die in diesem Kapitel beschrieben wurde, einen Befehl, der den Ordner "test1" in "test2" umbenennt. Nehmen Sie an, dass der Wert der Variablen $mb das Handle einer offenen IMAP-Verbindung enthält, dass die Variable $server den IMAP-Server-String (einschließlich der Klammern, des ServerHost-Namens, des Protokolls und der Portnummer) enthält, dass die Variable $pfx das IMAP-Mailbox-Präfix enthält und dass die Variablen $old und $new die Ordnernamen enthalten. 5. Schreiben Sie unter Verwendung der geeigneten benutzerdefinierten Funktion, die in diesem Kapitel beschrieben wurde, einen Befehl, der die Header der IMAP-Nachricht ausgibt, deren Nummer durch den Wert von $n angegeben wird. Nehmen Sie an, dass der Wert der Variablen $mb das Handle einer offenen IMAP-Verbindung enthält. 12 Kapitel 13 Leitfaden für relationale Datenbanken und SQL Lernziele ● Wie relationale Datenbanken aufgebaut sind ● Warum relationale Datenbanken sich besser zum Speichern von Daten eignen als Dateien ● Wie SQL-Abfragen gebildet werden, um auf relationale Daten zuzugreifen und diese zu manipulieren ● Wie relationale Datenbanken entworfen und erstellt werden 316 PHP 4 IT-Tutorial In diesem Kapitel wird beschrieben, wie relationale Datenbanken aufgebaut sind und wie sie verwendet werden. Im Vergleich zu Dateien bieten relationale Datenbanken viele Vorteile, einschließlich einer größeren Datensicherheit und der Möglichkeit, Daten gemeinsam zu nutzen. Der Schwerpunkt dieses Kapitels liegt auf SQL, der Standardsprache, die dazu dient, relationale Datenbanken zu erstellen, auf sie zuzugreifen und sie zu manipulieren. Im folgenden Kapitel lernen Sie, wie Sie SQL-Befehle in PHP-Skripts einbetten können, damit Ihre PHPProgramme mit relationalen Datenbanken arbeiten können. Die Begriffe, die in diesem Kapitel erklärt werden, gelten für die meisten relationalen Datenbanken. Jedoch sind die Details – insbesondere der SQL-Syntax – spezifisch für MySQL, die Datenbank, die am häufigsten mit PHP verwendet wird. Grundbegriffe relationaler Datenbanken Noch vor wenigen Jahren waren relationale Datenbanken etwas Neues. Andere Arten von Datenbanken, wie beispielsweise Netzwerkdatenbanken und hierarchische Datenbanken, waren vorherrschend. Jedoch hat sich gezeigt, dass das relationale Datenbankmodell im Vergleich zu den konkurrierenden Modellen kostengünstiger ist. In diesem Abschnitt wird erklärt, wie relationale Datenbanken aufgebaut sind und warum das relationale Datenbankmodell so erfolgreich gewesen ist. Die Struktur einer relationalen Datenbank Eine relationale Datenbank speichert Daten in Tabellen, die den Datenblättern aus Tabellenkalkulationsprogrammen ähneln. Jede Tabelle speichert Informationen über eine bestimmte Art von Entity (deutsch etwa: Gegenstand). Sie können eine Tabelle ungefähr mit einer Datei gleichsetzen. Beispielsweise könnte eine relationale Datenbank für einen Verlag Tabellen wie beispielsweise titel und autoren enthalten. Abbildung 13.1 zeigt eine typische relationale Datenbanktabelle, die ehemalige US-Präsidenten enthält, die wir für unser Beispiel einmal als „Angestellte“ (engl. employee) der US-Regierung bezeichnen wollen. Die ersten Zeile der Tabelle beschreibt die Namen der Spalten. Jede weitere Zeile der Tabelle enthält einen einzelnen Angestellten. Beispielsweise beschreibt die zweite Zeile einen Angestellten namens George Washington. Jede Spalte beschreibt ein bestimmtes Attribut eines Angestellten. Beispielsweise gibt die zweite Spalte den Namen des Angestellten und die dritte Spalte sein Geburtsjahr an. Kapitel 13: Leitfaden für relationale Datenbanken und SQL 317 Um eine Möglichkeit zu haben, eine bestimmte Tabellenzeile zu bezeichnen, verfügt jede Tabelle normalerweise über ein Spalte, die jede Zeile eindeutig identifiziert. Diese Spalte wird als Primärschlüssel der Tabelle bezeichnet. In Abbildung 13.1 dient die Spalte EmployeeID als Primärschlüssel. Wenn eine einzelne Spalte nicht ausreicht, um jede Zeile eindeutig zu kennzeichnen, können die Werte mehrerer Spalten zu einem zusammengesetzten Primärschlüssel kombiniert werden. Abbildung 13.1 Eine typische Datenbanktabelle Eine relationale Datenbank leitet ihren Namen von ihrer Fähigkeit ab, Daten in mehreren Tabellen miteinander zu verbinden, also „in Relation zueinander“ zu setzen. Abbildung 13.2 zeigt zwei Tabellen und die Beziehung zwischen ihnen. Die neue Tabelle enthält Informationen über die speziellen Fähigkeiten der Angestellten. Genauer gesagt: Ein Eintrag dieser Tabelle identifiziert jeweils den Angestellten, der die genannte Fähigkeit am besten beherrscht. Die Bezeichnung der Fähigkeit dient als Primärschlüssel der Tabelle, die nur eine weitere Spalte enthält. Die andere Spalte speichert die EmployeeID (Mitarbeiter-ID) des Angestellten, der über die Fähigkeit verfügt, die in dieser Zeile gespeichert wird. Beispielsweise ist der Angestellte 0003 der befähigste Architekt. Beachten Sie, dass EmployeeID sowohl der Primärschlüssel der ursprünglichen Tabelle als auch eine Spalte der neuen Tabelle ist. Die EmployeeID-Spalte der neuen Tabelle wird als Fremdschlüssel bezeichnet. Diese Spalte ist zwar nicht der Primärschlüssel der neuen Tabelle, aber sie bildet den Primärschlüssel einer anderen Tabelle. 13 318 PHP 4 IT-Tutorial Abbildung 13.2 Eine typische Beziehung zwischen zwei Tabellen Die Software-Anwendung, mit der eine Datenbank bearbeitet wird, wird als Database Management System (DBMS; dt. Datenbankverwaltungssystem) bezeichnet. Es gibt viele Open-Source- und kommerzielle Datenbankverwaltungssysteme. Zu den gebräuchlichsten gehören: DBMS Typ DB2 Kommerziell Interbase Früher kommerziell, jetzt Open Soucre MySQL Open Source Oracle Kommerziell Postgresql Open Source SQL Server Kommerziell Sybase Kommerziell Das MySQL-DBMS ist das gebräuchlichste DBMS, das mit PHP verwendet wird. Der Grund dafür liegt hauptsächlich darin, dass es frei verfügbar ist. Mit PHP können Sie jedoch auf die meisten modernen Datenbanksysteme zugreifen. Dazu benötigen Sie nur einen so genannten Datenbanktreiber – ein Programm, das als Schnittstelle zwischen PHP und der Datenbank dient. Viele Datenbanksysteme verfügen über Treiber, die mit dem ODBC-Standard (Open Database Connectivity) konform sind. Mit der ODBC-Funktion von PHP können Sie auf diese Datenbanksysteme zugreifen. Warum relationale Datenbanken? Im Vergleich zu Dateien und nichtrelationalen Datenbanken haben relationale Datenbanken zahlreiche Vorteile und einige wenige Nachteile. Wenn Sie wissen, Kapitel 13: Leitfaden für relationale Datenbanken und SQL 319 welche Faktoren Sie gegeneinander abwägen müssen, können Sie je nach Aufgabe die geeignete Speicherform – Datei oder Datenbank – für Ihre Daten wählen. Gemeinsames Nutzen von Daten erleichtern Der entscheidende Vorteil eines relationalen Datenbankverwaltungssystems ist die Möglichkeit, Daten gemeinsam zu nutzen. Dies ist besonders bei webbasierten Anwendungen wichtig, weil mehrere Benutzer fast gleichzeitig auf dieselben Daten zugreifen können. Relationale Datenbanksysteme enthalten Vorkehrungen, die dazu dienen, den Verlust oder die Beschädigung von Daten zu verhindern, die andernfalls unter solchen Umständen vorkommen könnten. Darüber hinaus verfügen Datenbanksysteme über eine Client/Server-Architektur, die zentral gespeicherte Daten über ein Netzwerk für externe Benutzer zur Verfügung stellt. Deshalb ermöglichen relationale Datenbanken eine gemeinsame Nutzung von Daten sowohl über die Zeit als auch über den Raum hinweg. Die Unabhängigkeit von Daten gewährleisten Die Unabhängigkeit der Daten ist ein zweiter Hauptvorteil einer relationalen Datenbank. Wenn ein Programm auf eine Datei zugreift, werden die Daten in derselben Form an das Programm übertragen, in der sie gespeichert sind. Im Gegensatz dazu verwenden Programmierer eine spezielle Sprache, um Daten von einer relationalen Datenbank anzufordern. Programmierer können die Daten in jeder gewünschten Form anfordern, und zwar unabhängig davon, wie die Daten gespeichert sind. Insbesondere können Programmierer nur die Tabellenspalten anfordern, die sie in einer bestimmten Anwendung benötigen. Diese Fähigkeit ist wichtig, wenn neue Spalten zu einer Datenbank hinzugefügt werden. Wegen der Unabhängigkeit der Daten funktionieren bereits vorhandene Programme auch weiterhin korrekt, nachdem die Datenbank geändert wurde. Im Gegensatz dazu müssen im Allgemeinen alle Programme geändert werden, wenn ein Feld zu einer Datei hinzugefügt wird, auf die die Programme zugreifen. Ad-hoc-Abfragen Relationale Datenbanken verstehen SQL (Structured Query Language), eine relativ einfache Sprache, die dazu verwendet wird, Daten abzufragen. Doch trotz ihrer Einfachheit ist SQL eine leistungsstarke Sprache, mit der Sie auf Daten zugreifen können, die in mehreren Tabellen enthalten sind. Sie können die gewünschten Daten filtern, sortieren und zusammenfassen sowie die Ergebnisse anzeigen. 13 320 PHP 4 IT-Tutorial Im Allgemeinen ist es nicht möglich, alle Möglichkeiten vorwegzunehmen, wie Benutzer auf die Daten zugreifen und diese anzeigen wollen. Deshalb ist es nicht möglich, Anwendungsprogramme zu schreiben, die alle möglichen Informationsbedürfnisse befriedigen können. Mit Sicherheit treten immer unvorhergesehene oder Ad-hoc-Datenabfragen auf. Mit SQL können Sie auf Daten zugreifen, die in einer relationalen Datenbank gespeichert sind, ohne ein Anwendungsprogramm zu schreiben. Häufig ist es dadurch möglich, die Verzögerung und die Kosten zu vermeiden, die mit der Erstellung eines benutzerspezifischen Programms verbunden sind. Auf diese Weise schaffen relationale Datenbanken die Möglichkeit, Ad-hoc-Informationsanfragen zu befriedigen, die andernfalls unbeantwortet bleiben würden. Daten organisieren Im Allgemeinen speichern relationale Datenbanken ihre Daten in einer einzigen Datei oder in einem einzigen Verzeichnis. Diese Art der Datenorganisation erleichtert die Verwaltung der Daten, weil ist es einfacher ist, eine einzige Datei oder ein einziges Verzeichnis zu sichern oder wiederherzustellen als einen Satz von Dateien, die in mehreren Verzeichnissen gespeichert sind. Datensicherheit herstellen Im Allgemeinen schützen relationale Datenbanken Daten gegen unautorisierte Zugriffe. Beispielsweise können bestimmte Dateien, in denen relationale Tabellen gespeichert sind, nur für den Systemadministrator oder für ein spezielles Benutzerkonto zugänglich sein, das erstellt wurde, um die Datenbank zu verwalten. Die erforderlichen Programmkenntnisse minimieren Moderne Datenbanksysteme wenden ausgefeilte Programmiertechniken an, um nach außen hin die Illusion der Einfachheit zu schaffen. Wegen dieser ausgefeilten Technik ist es im Allgemeinen einfacher, Programme zu schreiben, die mit einer relationalen Datenbank arbeiten, als funktional gleichwertige Programme, die gewöhnliche Dateien verwenden. Darüber hinaus haben Anwendungen, die mit Hilfe eines Datenbanksystems geschrieben wurden, wahrscheinlich weniger Mängel als funktional gleichwertige Anwendungen, die mit gewöhnlichen Dateien arbeiten. Die Entwickler von Datenbanksystemen verfügen im Allgemeinen über große Programmiererfahrung und haben diese Erfahrung in die Entwicklung von wie- Kapitel 13: Leitfaden für relationale Datenbanken und SQL 321 derverwendbarem Code einfließen lassen, auf den andere Programmierer mittels definierter Funktionen mit einfachen Schnittstellen zugreifen können. Ähnlich wie ein Betriebssystem Programmierern die Last abnimmt, die Funktion von Hardware-Geräten im Detail verstehen zu müssen, befreit eine relationale Datenbank Programmierer von der Notwendigkeit, eine Reihe komplexer Probleme verstehen zu müssen, die mit einer gemeinsamen Nutzung von Daten verbunden sein können. Berechnungen effizient durchführen Weil Datenbanksysteme programmtechnisch so komplex sind, erfordern sie im Allgemeinen mehr Prozessorzyklen, um eine Datenabfrage zu beantworten, als der Zugriff auf eine gewöhnliche Datei. In dieser Hinsicht sind Datenbanksysteme ineffizient. Wenn man dieses Thema jedoch aus einer anderen Perspektive betrachtet, kann man zu einem anderen Schluss kommen. Nehmen wir beispielsweise an, dass Sie anhand bevölkerungsstatistischer Daten das Durchschnittseinkommen der Haushalte berechnen wollen. Wenn die Bevölkerungsdaten in einer gewöhnlichen Datei gespeichert wären, müssten Sie ein Programm schreiben, das eine Schleife enthielte, um jeden Datensatz der Datei zu lesen und Summenfelder mit dem Gesamteinkommen und der Anzahl der Haushalte fortzuschreiben. Nehmen wir an, dass die Statistikdatei auf einem Remote-Computer gespeichert ist, auf die Sie über ein Netzwerk zugreifen. In diesem Fall wird jeder Statistikdatensatz über das Netzwerk gesendet, wodurch der Netzwerkverkehr stark belastet wird. Wenn die Statistikdaten jedoch in einer relationalen Datenbank gespeichert wären, könnten Sie das Durchschnittseinkommen der Haushalte einfach mit SQL abfragen. Auf diese Weise werden nur die Ergebnisdaten selbst über das Netzwerk gesendet. Deshalb ist der Einsatz eines relationalen Datenbankverwaltungssystems nicht immer ineffizienter als das Arbeiten mit gewöhnlichen Dateien. Über den Einsatz eines relationalen DBMS entscheiden Von einem kaufmännischen Standpunkt aus ist es richtig, ein Verfahren dann einzusetzen, wenn seine Vorteile die damit verbundenen Kosten überwiegen. Bei einem relationalen DBMS werden die Grenzkosten (die zusätzlichen Kosten) im Vergleich zum Arbeiten mit gewöhnlichen Dateien hauptsächlich durch den Bedarf an größeren Rechnerressourcen verursacht. Dies setzt natürlich voraus, dass Sie ein kostenlos verfügbares Open-Source-DBMS einsetzen; andernfalls fallen zusätzlich die Kosten für den Erwerb und die Wartung des gewählten kommerziellen DBMS an. 13 322 PHP 4 IT-Tutorial Wir sagten bereits, dass ein relationales DBMS viele zusätzliche Vorteile bietet. Wenn diese Vorteile für Ihre Aufgabe wichtig sind, überwiegen die Vorteile eines DBMS im Allgemeinen dessen Kosten. Gewöhnliche Dateien eignen sich weiterhin für relativ statische Daten, die nicht gemeinsam genutzt werden, nicht für Ad-hoc-Abfragen benötigt werden, nicht geheim oder wertvoll sind und nur von wenigen Programmen verwendet werden. Anders ausgedrückt: Gewöhnliche Dateien eignen sich für sehr einfache Anwendungen; bei den meisten wichtigen Anwendungen ist wahrscheinlich ein DBMS kostengünstiger. Frage an den Experten Frage: Welches DBMS sollte ich für meine Anwendung verwenden? Antwort: Wie bereits erwähnt, ist MySQL das gebräuchlichste DBMS, das mit PHP verwendet wird. Daneben ist mit Postgresql ein weiteres Open-Source-DBMS kostenlos verfügbar. Im Vergleich zu MySQL verfügt Postgresql über zusätzliche Funktionen, die die Integrität der Daten bei Transaktionen sicherstellen und das Schreiben entsprechender Programme erleichtern. Sie sollten Postgresql in Betracht ziehen, wenn Ihre Datenbank häufig in großem Umfang aktualisiert wird. Wenn Ihre Datenbank auf einem kommerziellen System läuft, verfügen Sie möglicherweise über die Mittel, um ein kommerzielles DBMS zu kaufen. Die Wahl des geeigneten DBMS hängt von vielen Faktoren ab, dazu zählen auch Ihre Erfahrung mit dem Anbieter und Ihr Budget. 1-Minuten-Test ● Welche Komponente einer relationalen Datenbank speichert Informationen über eine bestimmte Art von Entity? ● Welche Komponente einer relationalen Datenbank speichert Informationen über eine bestimmte Instanz eines Entitys? ● Welche Komponente einer relationalen Datenbank speichert Werte für eine bestimmte Eigenschaft einer Menge von Entities? ● Tabelle (table) ● Zeile (row) ● Spalte (column) Kapitel 13: Leitfaden für relationale Datenbanken und SQL 323 Datenbanken implementieren Die Implementierung von relationalen Datenbanken ist ein umfangreiches Thema und Gegenstand vieler Bücher. In diesem Abschnitt erhalten Sie einen Überblick über dieses Thema, wobei aus einer einfachen, praxisorientierten Perspektive beschrieben wird, wie Datenbanken entworfen und erstellt werden. Das Ziel dieses Abschnitts besteht darin, Sie in die Lage zu versetzen, einfache MySQL-Datenbanken zu implementieren, auf die Sie mit PHP-Programmen zugreifen können. Datenbanken entwerfen Ein gebräuchliches Hilfsmittel für den Entwurf relationaler Datenbanken ist ein Verfahren, das als Entity-Relationship-Modellierung oder E-R-Modellierung bezeichnet wird. Bei diesem Verfahren entspricht ein Entity einer relationalen Tabelle; das heißt, das Entity enthält Daten, die eine Menge gleichartiger Individuen beschreiben. Die E-R-Modellierung ist ein Prozess, bei dem Spalten, Entities und Beziehungen zwischen Entities festgestellt und geordnet werden. Ein E-RModell kann problemlos in einen Datenbankentwurf übersetzt werden, der dann in einer relationalen Datenbank praktisch realisiert werden kann. E-R-Modellierung Der Prozess der E-R-Modellierung besteht aus vier Hauptphasen: 1. Spalten identifizieren 2. Spalten zu Entities zusammenfassen 3. Primärschlüssel identifizieren 4. Fremdschlüssel identifizieren Spalten identifizieren Der erste Schritt bei der E-R-Modellierung besteht darin, die Spalten zu identifizieren. Häufig wird diese Aktivität von einer Projektgruppe ausgeführt, die von einem Experten geleitet und unterstützt wird, der über Erfahrungen in der E-RModellierung verfügt. Sie erinnern sich, dass eine Spalte eine einzelne Eigenschaft eines Entitys festhält. Im Wesentlichen führt die Projektgruppe ein Brainstorming durch, um die Frage zu beantworten, welche Daten oder Eigenschaften das System speichern soll. Dabei werden zunächst die möglichen Spalten (die Kandidatenspalten) gesammelt. Häufig werden zu diesem Zweck Tafeln verwendet, damit die Teilnehmer die Entwicklung der Liste verfolgen und deren Einträge leicht ändern können. 13 324 PHP 4 IT-Tutorial Bei dem Versuch, Spalten zu identifizieren, ist es im Allgemeinen hilfreich, problemspezifische Fragen wie die folgenden zu stellen: ● Welche Entscheidungen muss das System treffen oder unterstützen? ● Welche Aktionen soll das System ausführen oder unterstützen? ● Welche Daten werden benötigt, um diese Entscheidungen zu treffen und diese Aktionen auszuführen? Wenn sich der Eindruck verfestigt, dass alle Kandidatenspalten identifiziert worden sind, wird der Prozess mit der nächsten Phase fortgesetzt, in der die Spalten zu Entities zusammengefasst werden. Spalten zu Entities zusammenfassen Normalerweise ist es offensichtlich, dass einige Spalten in dem Sinne verwandt sind, dass sie zu einer bestimmten Menge gleichartiger Individuen oder Dinge gehören. Beispielsweise könnten Spalten wie autor, titel und verkaufspreis Eigenschaften von Büchern beschreiben. Deshalb können diese Spalten zu einem Entity, beispielsweise buch, zusammengefasst werden. Manchmal gehört eine bestimmte Spalte auch zu mehreren Entities. In diesem Fall kann die Spalte mehrfach aufgelistet werden. Nachdem die Entities identifiziert worden sind, sollten sie passende Namen erhalten. In der Sprache SQL, die zum Arbeiten mit relationalen Datenbanken verwendet wird, gibt es einige Regeln zur Bildung von Namen. Namen, die diesen Regeln nicht entsprechen, sollten geändert werden, um Probleme beim späteren Entwurf der Datenbank zu vermeiden. Deshalb sollten Spalten- und Entity-Namen unter Beachtung der folgenden Regeln gebildet werden: ● Namen sollten mit einem Buchstaben beginnen. ● Namen sollten nur Buchstaben, Ziffern und das Unterstreichungszeichen (_) enthalten. ● Namen sollten nicht länger als 64 Zeichen sein. ● Namen sollten so behandelt werden, dass die Groß- oder Kleinschreibung keine Rolle spielt (d.h. die Spaltennamen abc und ABC sollten als gleich gelten). Nachdem die Spalten zu Entities zusammengefasst worden sind, können Sie mit der nächsten Phase fortfahren und die Primärschlüssel aller Entities identifizieren. Kapitel 13: Leitfaden für relationale Datenbanken und SQL 325 Hinweis Die meisten Datenbanksysteme einschließlich MySQL haben weniger restriktive Regeln für die Namensbildung als die hier empfohlenen. Aber wenn Sie die empfohlenen Einschränkungen beachten, können Sie viele Probleme in dem DBMS, in HTML und in PHP vermeiden. Primärschlüssel identifizieren Jedes Entity wird später in eine relationale Tabelle umgesetzt und sollte deshalb über einen Primärschlüssel verfügen. Untersuchen Sie jedes Entity, um festzustellen, ob eine seiner Spalten einen Wert enthält, der jede Instanz des Entitys eindeutig identifiziert. Wenn eine solche Spalte existiert, sollten Sie sie als Primärschlüssel des Entitys verwenden. Beispielsweise könnten Sie die Steuernummer als Primärschlüssel eines Entitys festlegen, das Informationen über einen Steuerzahler enthält. Möglicherweise stellen Sie fest, dass einige Entities keine Spalte enthalten, die als Primärschlüssel geeignet ist. In einem solchen Fall können Sie eine Reihe von Spalten suchen, die zusammen einen eindeutigen Wert ergeben. Wenn Sie eine solche Gruppe von Spalten identifizieren können, können Sie diese Gruppe als zusammengesetzten Primärschlüssel des Entitys verwenden. Beispielsweise könnten die Steuernummer und das Steuerjahr zusammen als Primärschlüssel eines Entitys verwendet werden, dass die Informationen der jährlichen Steuerklärungen eines Steuerzahlers enthält. Möglicherweise gibt es keine Spalte oder Gruppe von Spalten, die die Instanzen eines Entitys eindeutig identifiziert. In diesem Fall sollten Sie eine neue Spalte erstellen, die eine künstliche eindeutige Identifikation enthält und die neue Spalte als Primärschlüssel des Entitys identifiziert. Beispielsweise könnten Sie im Falle eines Entitys namens Mitarbeiter eine künstliche Identifikation namens MitarbeiterId oder PersonalNr schaffen, wobei die zweite Variante eine gebräuchliche Abkürzung für eine Spalte ist, die Personalnummern enthält. Tipp Manche Programmierer ziehen es vor, eine künstliche eindeutige Identifizierung auch dann zu verwenden, wenn eine oder mehrere Spalten als Primärschlüssel dienen könnten. Mit diesem Verfahren werden Probleme vermieden, wenn sich herausstellen sollte, dass die angeblich eindeutigen Bezeichner gar nicht eindeutig sind. Beispielsweise sollten Steuernummern eindeutig sein; aber ein Steuerzahler könnte aus Versehen falsche Informationen angeben, sodass der vorgeblich eindeutige Bezeichner in Konflikt mit dem Bezeichner eines anderen Steuerzahlers gerät. 13 326 PHP 4 IT-Tutorial Fremdschlüssel identifizieren Die letzte und anspruchsvollste Phase der E-R-Modellierung besteht darin, Fremdschlüssel zu identifizieren. Sie erinnern sich, dass Fremdschlüssel einfach Spalten sind, deren Werte sich auf die Primärschlüsselwerte anderer Entities beziehen. Der Prozess, Fremdschlüssel zu identifizieren, besteht darin, Spalten mit Primärschlüsseln zu vergleichen und für jede mögliche Kombination die Frage zu stellen, ob es eine Beziehung zwischen dem Wert der betreffenden Spalte und dem Wert des Primärschlüssels gibt. Die meisten E-R-Modellierer verwenden ein spezielles Diagramm, das so genannte E-R-Diagramm, um die Dokumentation von Fremdschlüsseln zu unterstützen. Abbildung 13.3 zeigt ein typisches E-R-Diagramm, das die relationalen Tabellen darstellt, die weiter oben in Abbildung 13.2 verwendet wurden. Ein ER-Diagramm repräsentiert Entities als Rechtecke und die Beziehungen zwischen Entities als Rauten. Eine Beziehung existiert überall dort, wo Fremdschlüssel identifiziert worden sind. Die Beziehung hasskill (hat Fähigkeit) in Abbildung 13.3 besteht zwischen den Entities employee (Angestellter) und skill (Fähigkeit). Manchmal zeigen E-R-Diagramme die Felder an, die mit den Entities verbunden sind. Weil dies jedoch häufig zu unübersichtlichen Diagrammen führt, ist dieses Verfahren unüblich. Dennoch mag es – besonders bei kleinen E-RModellen – hilfreich sein. Genau genommen umfasst die E-R-Modellierung mehr als die bloße Identifizierung von Fremdschlüsseln. Nachdem eine Beziehung identifiziert worden ist, muss sie klassifiziert und möglicherweise überarbeitet werden. Um eine Beziehung zu klassifizieren, müssen Sie die Zahl der Entity-Instanzen (null, eine oder mehr) ermitteln, die an der Beziehung beteiligt sein können. Bei der hasskillBeziehung verfügt jeder employee (Mitarbeiter) über genau eine skill (Fähigkeit). Eine solche Beziehung wird als 1:1-Beziehung bezeichnet. Es sind jedoch auch andere so genannte Beziehungskardinalitäten oder kurz Kardinalitäten möglich. Beispielsweise kann ein Buch mehrere Autoren haben. Deshalb handelt es sich bei der Beziehung zwischen den Entities buch und autor um eine Eins-zuViele-Beziehung, die üblicherweise auch als 1:N-Beziehung bezeichnet wird. Einige Beziehungen sind optional. Beispielsweise kann ein Mitarbeiter (employee) einen Ehepartner (spouse) haben oder nicht; deshalb ist die Beziehung zwischen employee und spouse eine 1:0-Beziehung. Das heißt, dass ein Mitarbeiter einen Ehepartner haben oder nicht haben kann; aber wenn ein Mitarbeiter einen Ehepartner hat, hat er genau einen. Kapitel 13: Leitfaden für relationale Datenbanken und SQL 327 Abbildung 13.3 Ein typisches E-R-Diagramm Interessanter sind N:N-Beziehungen (Viele-zu-Viele-Beziehungen). Ein Beispiel für ein solche Beziehung ist die Beziehung zwischen Vorlesung und Student. Es handelt sich um eine N:N-Beziehung, weil sich für eine Vorlesung mehrere Studenten einschreiben können und weil jeder Student mehrere Vorlesungen belegen kann. Eine solche Beziehung ist nicht begrenzt und deutet auf ein fehlendes Entity hin – in diesem Fall das Entity Einschreibung. Wenn Sie auf eine N:N-Beziehung stoßen, sollten Sie das fehlende Entity identifizieren, zu dem Modell hinzufügen und die Beziehungen entsprechend ergänzen. Häufig ist das fehlende Entity mit einer oder mit mehreren fehlenden Spalten verbunden. Beispielsweise ist anzunehmen, dass in Falle des fehlenden Entities Einschreibung die Spalte Note fehlt, da diese weder einer Vorlesung noch einem Studenten vernünftig zugeordnet werden kann. Die Notenspalte ist eine Eigenschaft der Beziehung zwischen einer Vorlesung und einem Studenten und nicht allein eine Eigenschaft einer Vorlesung oder eines Studenten. Wenn Sie alle fehlenden Entities zu dem Modell hinzugefügt haben, sollten alle N:N-Beziehungen verschwunden sein. Beispielsweise ist die Beziehung zwischen Vorlesung und Einschreibung eine 1:N-Beziehung, weil es zu einer Vorlesung viele Einschreibungen geben kann, aber jede Einschreibung zu einer bestimmten Vorlesung gehört. Auf ähnliche Weise ist die Beziehung zwischen Einschreibungen und Studenten N:1, weil jede Einschreibung zu einem bestimmten Studenten gehört, der sich für mehrere Vorlesungen einschreiben kann. Nachdem Sie die N:N-Beziehungen eliminiert haben, können Sie prüfen, ob die Datenbank, die durch Ihr E-R-Modell beschrieben wird, normalisiert werden muss. Eine Datenbank normalisieren Eine normalisierte Datenbank ist eine Datenbank, die so umgeformt wurde, dass sie bestimmte Regeln erfüllt. Die Regeln der Normalisierung von Datenbanken werden als Eigenschaften beschrieben, über die eine regelkonforme Datenbank verfügen muss. Diese Eigenschaften werden auch als Normalformen bezeichnet. Der gebräuchlichste Satz von Regeln zur Datenbanknormalisierung enthält drei Regeln, die die erste, die zweite und die dritte Normalform beschreiben. 13 328 PHP 4 IT-Tutorial Diese Formen dienen dazu, Probleme zu vermeiden, die bei Datenbanken auftreten können, die diese Regeln nicht befolgen. Jedoch halten viele Leute diese Regeln für verwirrend und unzugänglich. In diesem Unterabschnitt erhalten Sie ein kurzen, verständlichen Überblick über die Normalisierung von Datenbanken, sodass Sie viele häufige Probleme beim Entwerfen von Datenbanken vermeiden können. Entwickler, die sehr einfache Datenbanken entwerfen, können den Schritt der Datenbanknormalisierung gefahrlos überspringen, da Entwurfsprobleme später beim Programmieren oder beim Einsatz der Datenbank leicht korrigiert werden können. Jedoch ist die Datenbanknormalisierung bei großen Datenbanken unverzichtbar, bei denen die Kosten und Mühen, die mit dem Entdecken und Korrigieren von Fehlern verbunden sind, die Kosten und Mühen einer Datenbanknormalisierung weit übersteigen können. Regel 1: Es dürfen nur atomare Werte vorkommen Eine Datenbanktabelle sollte nur atomare Werte enthalten. Das heißt, keine Spalte sollte einen zusammengesetzten Wert enthalten. Außerdem sollte keine Spalte eine so genannte Wiederholungsgruppe enthalten. (Eine Wiederholungsgruppe ist ein Feld, das mehrere gleichartige Einträge – beispielsweise E-MailAdressen – enthält.) Diese Regel schließt Spalten wie beispielsweise Namen aus, die aus dem Vornamen, einem abgekürzten weiteren Vornamen und dem Nachnamen bestehen. Eine Spalte enthält einen zusammengesetzten Wert und sollte in drei separate Spalten zerlegt werden: firstname (Vorname), middleinitial (Kürzel) und lastname (Nachname). Diese Regel wird häufig ohne größere Nachteile gebrochen. Ein Nachteil eines Verstoßes gegen diese Regel besteht darin, dass es schwieriger wird, mit SQL auf die Komponenten einer zusammengesetzten Spalte zuzugreifen. Das Verbot von Wiederholungsgruppen ist schwerwiegender. Betrachten wir beispielsweise eine Tabelle, die eine Wiederholungsgruppe mit E-Mail-Adressen enthält. Wie viele Wiederholungen pro Gruppe sollte erlaubt sein: zwei, drei, fünf, zehn? Um zu vermeiden, dass eine künstliche Obergrenze für die Anzahl der Wiederholungen festgelegt wird, sollte der Entwurf der Datenbank so überarbeitet werden, dass die Wiederholungsgruppe in eine separate Tabelle eingefügt wird. Beispielsweise sollte der Entwurf contact table: contactid (Primärschlüssel) name email1 email2 email3 Kapitel 13: Leitfaden für relationale Datenbanken und SQL 329 durch den folgenden Entwurf ersetzt werden: contact table: contactid (Primärschlüssel) name email table: emailid (Primärschlüssel) contactid (Fremdschlüssel) email Tipp Um nicht gegen diese Regel zu verstoßen, sollten Sie alle Wiederholungsgruppen entfernen, indem Sie eine oder mehrere neue Tabellen definieren, um diese Gruppen zu speichern. Regel 2: Spalten müssen vom kompletten Primärschlüssel abhängen Die Spalten einer Tabelle sollten von dem kompletten Primärschlüssel abhängig sein. Die folgende Tabelle der Einschreibungen (enrollment table), die gegen die Regel verstößt, soll illustrieren, wie diese Regel funktioniert: enrollment table; studentid courseid studentname Nehmen wir an, dass studentid und courseid den zusammengesetzten Primärschlüssel der Tabelle bilden. Die Spalte studentname ist mit einem Studenten, nicht mit einer Einschreibung verbunden. Deshalb hängt der Name nur von dem Wert studentid, nicht aber von dem Wert courseid ab. Wenn sich ein Student für mehrere Vorlesungen einschreibt, enthält die Einschreibungstabelle (enrollment table) für diesen Studenten mehrere Einschreibungszeilen, die jeweils eine studentname-Spalte enthalten. Wenn festgestellt wird, dass der Name des Studenten falsch geschrieben wurde, müssen mehrere Tabellenzeilen korrigiert werden; andernfalls würden einige Zeilen falsche Spaltenwerte enthalten. Da Inkonsistenzen in einer Datenbank vermieden werden sollten, sind Entwürfe, bei denen eine Spalte nur von einem Teil des Primärschlüssels abhängt, durch diese Regel verboten. 13 330 PHP 4 IT-Tutorial Tipp Diese Regel betrifft nur Tabellen mit einem zusammengesetzten Primärschlüssel. Eine geeignete Methode, um Verstöße gegen diese Regel zu vermeiden, besteht darin, einen künstlichen Primärschlüssel zu verwenden, anstatt mit einem ansonsten brauchbaren zusammengesetzten Primärschlüssel zu arbeiten. Regel 3: Spalten dürfen nur von dem Primärschlüssel abhängen Die Spalten in einer Tabelle sollten nur von dem Primärschlüssel abhängen. Die Tabelle im folgenden Beispiel verstößt gegen diese Regel: course table: courseid (Primärschlüssel) coursename deptid deptname Dieser Tabelle speichert die Vorlesungs-ID (courseid), den Vorlesungsnamen (coursename), die Lehrstuhl-ID (deptid) und den Lehrstuhlnamen (deptname) der Vorlesung. Jedoch hängt die Spalte deptname nicht von der courseid, sondern von der deptid ab. Anders ausgedrückt: Die Tabelle beschreibt sowohl Vorlesungen als auch Lehrstühle. Als Folge davon erscheint der Lehrstuhlname redundanterweise in jeder Zeile, die zu einer Vorlesung dieses Lehrstuhls gehört. Der Entwurf sollte folgendermaßen überarbeitet werden: course table: courseid (Primärschlüssel) coursename deptid (Fremdschlüssel) department table: deptid (Primärschlüssel) deptname Tipp Um Verstöße gegen diese Regel zu vermeiden, sollten Sie auf Tabellen achten, die Informationen über mehrere Arten von Entities enthalten. Derartige Tabellen sollten in separate Tabellen zerlegt werden, die durch einen Fremdschlüssel miteinander verbunden sind. Kapitel 13: Leitfaden für relationale Datenbanken und SQL 331 E-R-Modelle verfeinern Die letzte Verfeinerung eines E-R-Modells besteht darin, die Datentypen der Spalten festzulegen. Die meisten relationalen Datenbanken unterstützen die folgenden allgemeinen Datentypen: ● Zeichen (character) ● Ganzzahl (integer) ● Dezimalzahl (decimal) ● Datum und Zeit (date and time) ● Binär (binary) Tabelle 13.1 fasst mehrere gebräuchliche Datentypen zusammen, die von MySQL und den meisten anderen relationalen Datenbanken akzeptiert werden. MySQL unterstützt jedoch noch viele andere Datentypen. Weitere Informationen über diese und andere Typen finden Sie im MySQL-Referenzhandbuch. Datentyp Beschreibung BLOB Beliebige binäre Daten, die maximal 65.535 Bytes lang sind CHAR(m) Eine Zeichenkette fester Länge, die maximal m Zeichen lang ist, wobei m kleiner als 256 ist. Um die angegebene Länge zu erreichen, wird die Zeichenkette gegebenenfalls mit Leerzeichen aufgefüllt. DATE Ein Datum im Format Jahr-Monat-Tag, beispielsweise 2005–12–31 DECIMAL DECIMAL(m,d) Eine Dezimalzahl, die als String von m Ziffern repräsentiert wird, von denen d rechts vom Dezimalpunkt stehen. Wenn m und d weggelassen werden, werden die Werte 10 und 0 angenommen. DOUBLE DOUBLE(m,d) Eine Fließkommazahl mit doppelter Genauigkeit, die insgesamt m Zeichen groß ist und über d Dezimalstellen verfügt FLOAT(m,d) Eine Fließkommazahl mit einfacher Genauigkeit, die insgesamt m Zeichen groß ist und über d Dezimalstellen verfügt INTEGER INTEGER UNSIGNED Eine 32-Bit-Ganzzahl. Wenn UNSIGNED angegeben wird, beträgt der Wertebereich 0 bis 4294967295; andernfalls beträgt der Bereich 2147483648 bis 2147483647. NUMERIC NUMERIC(m,d) Dasselbe wie DECIMAL REAL REAL(m,d) Dasselbe wie DOUBLE SMALLINT Eine 16-Bit-Ganzzahl. Wenn UNSIGNED angegeben wird, beträgt der SMALLINT UNSIGNED Wertebereich 0 bis 65535; andernfalls beträgt der Bereich –32768 bis 32767. Tabelle 13.1 Hauptdatentypen von MySQL 13 332 PHP 4 IT-Tutorial Datentyp Beschreibung TIME Ein Zeitwert in der Form Stunde-Minute-Sekunde, beispielsweise 08– 30–00 TIMESTAMP TIMESTAMP(m) Ein Datums- und Zeitwert in der Form Jahr-Monat-Tag StundeMinute-Sekunde, beispielsweise 1970–01–01 00:00:00. Diese Repräsentation entspricht dem Format, das von UNIX-Funktionen zurückgegeben wird. Es kann keine Daten darstellen, die nach einem bestimmten Tag im Jahre 2037 liegen. VARCHAR(m) Eine Zeichenkette variabler Länge mit maximal m Zeichen, wobei m kleiner als 256 ist. Leerzeichen am Ende werden entfernt. Tabelle 13.1 Hauptdatentypen von MySQL Die folgenden Faustregeln sollen Ihnen helfen, den passenden Datentyp zu wählen: ● Wählen Sie BLOB als Datentyp für Daten, auf die Sie nicht mit SQL zugreifen müssen oder die Sie nicht mit SQL manipulieren müssen. ● Wählen Sie den passenden Datums- oder Zeitdatentyp für Spalten, die Datums- oder Zeitwerte enthalten. ● Wählen Sie einen numerischen Typ für Spalten, die in Berechnungen verwendet werden. ● ● Wenn die Werte sehr groß oder sehr klein sind, wählen Sie DOUBLE als Datentyp. ● Wenn die Spalten ganze Zahlen enthalten, wählen Sie je nach Wertebereich SMALLINT oder INTEGER als Datentyp. ● Wählen Sie für andere Spalten, die numerische Daten enthalten, DECIMAL als Datentyp. Wählen Sie für andere Spalten CHAR oder VARCHAR als Datentyp, selbst wenn die Spalten hauptsächlich Ziffern, wie beispielsweise eine Postleitzahl, enthalten. Tipp Wenn Sie einen Datentyp wählen, sollten Sie Raum für ein künftiges Wachstum lassen. Beispielsweise sollten Sie nur dann eine zweistellige Kundennummer wählen, wenn Sie sicher sind, dass Sie nie mehr als hundert Kunden haben werden. Kapitel 13: Leitfaden für relationale Datenbanken und SQL 333 Eine MySQL-Datenbank erstellen Der Systemadministrator erstellt MySQL-Datenbanken. Wenn eine Datenbank erstellt wird, enthält sie zunächst keine Tabellen. Um eine Datenbanktabelle zu erstellen, wird eine spezielle SQL-Untersprache, die so genannte Data Definition Language (DDL), verwendet. In diesem Unterabschnitt wird die Form der DDLBefehle beschrieben. Sie können DDL- und andere SQL-Befehle mit Hilfe eines SQL-Interpreters oder mit Hilfe von PHP eingeben. Die Projekte in diesem Kapitel zeigen Ihnen, wie Sie SQL-Befehle mit einem SQL-Interpreter eingeben können. Im nächsten Kapitel erfahren Sie, wie Sie SQL-Befehle mit PHP absetzen können. Eine Tabelle erstellen Mit dem CREATE TABLE-Befehl können Sie eine Datenbanktabelle erstellen. Der Befehl hat die Form CREATE TABLE tabelle (col typ, col typ, ...); wobei tabelle den Namen der Tabelle, col den Namen einer Spalte und typ den Datentyp der Spalte angibt. Die Punkte (...) zeigen an, dass Sie eine unbegrenzte Anzahl von Spalten und Typen angeben können. Beispielsweise erstellt der folgende Befehl eine Tabelle namens buch, die die Spalten ISBN (einen eindeutigen Bezeichner für einen Buchtitel), titel und preis enthält: CREATE TABLE buch (isbn CHAR(10), titel VARCHAR(255), preis DECIMAL(5,2)); Bei SQL spielt die Groß- oder Kleinschreibung im Allgemeinen keine Rolle. Deshalb können Sie, wenn Sie wollen, auch den folgenden Befehl geben, der genau dieselbe Funktion ausführt wie der vorangegangene Befehl: create table buch (isbn char(10), titel varchar(255), preis decimal(5,2)); Tipp SQL-Code ist leichter lesbar, wenn Sie beim Schreiben von Befehlen einen konsistenten Stil verwenden. Beispielsweise könnten Sie alle SQL-Schlüsselwörter in Großbuchstaben und Wörter, die Sie selbst definieren, in Kleinbuchstaben schreiben. 13 334 PHP 4 IT-Tutorial Zusätzlich zu einem Datentyp kann eine Spalte mehrere optionale Attribute enthalten: Attribut Beschreibung NOT NULL Jede Zeile muss in der betreffenden Spalte einen Wert enthalten; Null-Werte sind nicht erlaubt. DEFAULT wert Wenn für die Spalte kein Wert angegeben wird, nimmt die Spalte automatisch den angegebenen wert an. AUTO-INCREMENT MySQL weist der betreffenden Spalte automatisch einen fortlaufenden Wert zu. PRIMARY KEY Die betreffende Spalte ist der Primärschlüssel der Tabelle, in der die Spalte enthalten ist. Das folgende Beispiel zeigt einen etwas komplexeren CREATE TABLE-Befehl, der einige optionale Attribute enthält: CREATE TABLE buch ( buchid CHAR(10) PRIMARY KEY, titel VARCHAR(255) NOT NULL, preis DECIMAL(5,2) DEFAULT 50.00 ); Eine Tabelle löschen Mit dem folgende Befehl können Sie eine Tabelle wieder löschen. Dabei werden alle Zeilen der Tabelle sowie die Tabelle selbst gelöscht: DROP TABLE tabelle; Dabei steht tabelle für den Namen der Tabelle, die gelöscht werden soll. Achtung Das Löschen einer Tabelle ist unwiderruflich. Überlegen Sie, ob Sie die Tabelle wirklich löschen wollen, bevor Sie einen DROP TABLE-Befehl geben, und vergewissern Sie sich, dass Sie den Befehl korrekt eingegeben haben, bevor Sie auf (¢) drücken. Eine Tabelle ändern Mit dem ALTER TABLE-Befehl können Sie eine existierende Tabelle ändern. Eine Form des Befehle dient dazu, eine Spalte der Tabelle zu löschen: ALTER TABLE tabelle DROP col; Kapitel 13: Leitfaden für relationale Datenbanken und SQL 335 Dabei steht tabelle für den Namen der Tabelle, die geändert werden soll, und col gibt den Namen der Spalte an, die gelöscht werden soll. Um beispielsweise die Spalte preis aus der Tabelle buch zu löschen, geben Sie den folgenden Befehl ein: ALTER TABLE buch DROP preis; Achtung Das Löschen einer Spalte ist unwiderruflich. Überlegen Sie, ob Sie die Spalte wirklich löschen wollen, bevor Sie einen ALTER TABLE-Befehl eingeben, und vergewissern Sie sich, dass Sie den Befehl korrekt eingegeben haben, bevor Sie auf (¢) drücken. Mit einer anderen Form des Befehls können Sie eine neue Spalte in eine Tabelle einfügen: ALTER TABLE tabelle ADD col typ [optionen]; Dabei steht tabelle für den Namen der Tabelle, die geändert werden soll, col ist der Name der Spalte, die hinzugefügt werden soll, typ ist der Typ der neuen Spalte und [optionen] sind gewünschte zusätzliche Optionen, wie beispielsweise PRIMARY KEY. Um beispielsweise die Spalte preis wieder in die Tabelle buch einzufügen, geben Sie den folgenden Befehl: ALTER TABLE buch ADD preis DECIMAL(5,2) DEFAULT 50.00; Zugriffsrechte gewähren und widerrufen Wenn ein Benutzer versucht, auf eine relationale Datenbank zuzugreifen, prüft das DBMS, ob der Benutzer berechtigt ist, die Operation auszuführen. Mit dem MySQL-Befehl GRANT kann der Systemadministrator einem Benutzer das Recht gewähren, auf eine Datenbanktabelle zuzugreifen. Der Befehl hat die folgende Form: GRANT ALL ON tabelle TO benutzer IDENTIFIED BY 'passwort'; Dabei steht tabelle für den Namen der Tabelle, benutzer für den Namen des Benutzerskontos und passwort für das Passwort, mit dem der Benutzer seine Identität authentifiziert. Alternativ kann der Systemadministrator mit der 13 336 PHP 4 IT-Tutorial folgenden Form des GRANT-Befehls einem Benutzer das Recht einräumen, auf alle Tabellen in einer Datenbank zuzugreifen: GRANT ALL ON datenbank.* TO benutzer IDENTIFIED BY 'passwort'; Beispielsweise weist der folgende Befehl dem Benutzer php das Recht zu, auf alle Tabellen der Datenbank testdb zuzugreifen, wenn der Benutzer das angegebene Passwort eingibt: GRANT ALL ON testdb.* TO php IDENTIFIED BY 'ichbins'; Mit dem REVOKE-Befehl können zuvor eingeräumte Berechtigungen widerrufen werden. Er hat die folgenden Formen: REVOKE ALL ON tabelle FROM benutzer; REVOKE ALL ON datenbank.* FROM benutzer; Beispielsweise können Sie mit dem folgenden Befehl alle Berechtigungen des Benutzers schurke widerrufen: REVOKE ALL ON *.* FROM schurke; Frage an den Experten Frage: Wie bereits erklärt wurde, scheint der Zugriff auf eine relationale Tabelle eine Alles-oder-nichts-Frage zu sein. Gibt es keine Methode, um nur den Zugriff auf bestimmte Spalten zu erlauben? Antwort: Ja, mit einer ausführlicheren Form des GRANT-Befehls kann der Systemadministrator den Zugriff auf die angegebenen Spalten beschränken. Der Befehl hat dann die folgende Form: GRANT priv (cols) ON tabelle TO benutzer IDENTIFIED BY 'passwort'; Oder: GRANT priv (cols) ON datenbank.* TO benutzer IDENTIFIED BY 'passwort'; Kapitel 13: Leitfaden für relationale Datenbanken und SQL 337 Dabei steht priv für die Berechtigung, die gewährt werden soll, und cols gibt die Spalten an, für die die Berechtigung gelten soll. Die Argumente tabelle, datenbank, benutzer und passwort haben ihre üblichen Bedeutungen. Der REVOKE-Befehl verfügt über ähnliche Formen: REVOKE priv (cols) ON tabelle FROM benutzer; Oder: REVOKE priv (cols) ON datenbank.* FROM benutzer; Die möglichen Berechtigungen umfassen: ● INSERT – Zeilen dürfen mit der angegebenen Spalte eingefügt werden ● SELECT – Zeilen dürfen mit der angegebenen Spalte abgefragt werden ● UPDATE – Zeilen dürfen mit der angegebenen Spalte aktualisiert werden Um einem Benutzer zu erlauben, auf eine Spalte zuzugreifen, ohne dass er diese ändern darf, können Sie beispielsweise die folgenden Befehle verwenden: REVOKE ALL ON buch FROM php; GRANT SELECT(buchid, titel, preis), INSERT(buchid, titel, preis), UPDATE(buchid, titel, preis) ON buch TO php IDENTIFIED BY 'itsme'; REVOKE INSERT(preis) ON buch FROM php; REVOKE UPDATE(preis) ON buch FROM php; Beachten Sie, dass der erste Befehl alle Berechtigungen auf Tabellenebene widerruft; andernfalls haben diese Berechtigungen Vorrang vor den Berechtigungen auf Spaltenebene. MySQL verfügt über ziemlich umfangreiche Berechtigungsfunktionen, die noch viele weitere Optionen zur Verfügung stellen. Weitere Informationen finden Sie in dem MySQL-Online-Handbuch unter www.mysql.com. 13 338 PHP 4 IT-Tutorial 1-Minuten-Test ● Wie heißt das Modellierungsverfahren, das häufig für das Entwerfen von Datenbanken verwendet wird? ● Welche Kardinalität haben die Beziehungen, die beim Entwurf einer Datenbank ersetzt werden müssen? ● Wie heißt der Prozess, bei dem eine Datenbank so umgewandelt wird, dass sie eine Reihe von Regeln erfüllt, die dazu dienen, bestimmte häufige Fehler zu vermeiden? ● Wie heißt die SQL-Untersprache, die zum Erstellen von Datenbanken verwendet wird? Auf Datenbankdaten zugreifen: SQL-Abfragen Zusätzlich zu der Data Definition Language enthält SQL die Data Manipulation Language (DML). Mit der DML können Sie Abfragen formulieren, die auf Daten in einer relationalen Datenbank zugreifen und Berichte erstellen. Außerdem können Sie mit der DML Tabellenzeilen einfügen, aktualisieren oder löschen. In den restlichen Abschnitten dieses Kapitels wird die DML beschrieben. In diesem Abschnitt wird zunächst die grundlegendste Form einer Abfrage behandelt: der einfache SELECT-Befehl. Die einfachste mögliche Abfrage zeigt alle Spalten aller Zeilen einer Tabelle an. Die Abfrage hat die folgende Form: SELECT * FROM tabelle; Dabei steht tabelle für den Namen der Tabelle, auf die zugegriffen werden soll. Das Output-Format fügt jede Tabellenzeile in eine neue Zeile ein und zeigt die Spalten in einer beliebigen Reihenfolge an. Der Output enthält die Spaltennamen und simuliert mit Hilfe normaler ASCII-Zeichen ein Tabellengitter zur ● ● ● ● E-R-Modellierung N:N Datenbanknormalisierung Data Definition Language Kapitel 13: Leitfaden für relationale Datenbanken und SQL 339 Trennung der Spalten. Eine Abfrage der employee-Tabelle könnte beispielsweise den folgenden Output erzeugen: +------------+-------------------+ | employeeno | name | +------------+-------------------+ | 1 | George Washington | | 3 | T. Jefferson | +------------+-------------------+ 2 rows in set (0.00 sec) Wenn Sie nur bestimmte Spalten auswählen oder die Spalten in einer bestimmten Reihenfolge anzeigen lassen wollen, können Sie die folgende alternative Form des SELECT-Befehls verwenden: SELECT col1, col2 FROM tabelle; Dabei steht tabelle für den Namen der Tabelle, und col1 und col2 geben die Spalten an, die abgefragt und angezeigt werden sollen. Sie können eine, zwei oder mehr Spalten angeben. Benachbarte Spaltennamen werden einfach durch ein Komma getrennt. Beispielsweise kehrt die folgende Abfrage die Reihenfolge der Spalten im Vergleich zu der früheren Abfrage um: SELECT name, employeeno FROM employee; Eine Abfrage der employee-Tabelle mit diesem Befehl könnte beispielsweise den folgenden Output erzeugen: +-------------------+------------+ | name | employeeno | +-------------------+------------+ | George Washington | 1 | | T. Jefferson | 3 | +-------------------+------------+ 2 rows in set (0.00 sec) Häufig sollen nur Zeilen ausgewählt werden, die bestimmte Kriterien erfüllen. Zu diesem Zweck können Sie mit der WHERE-Klausel eine Bedingung festlegen. Zeilen, die diese Bedingung nicht erfüllen, werden nicht ausgewählt. Das folgende Beispiel zeigt eine Abfrage, die nur eine einzelne Zeile ausgibt: SELECT employeeno, name FROM employee WHERE employeeno=1; 13 340 PHP 4 IT-Tutorial Die Form der Bedingungen in der DML von SQL ähnelt der Form von PHPBedingungen. Sie können die folgenden relationalen Operatoren verwenden: = gleich <> nicht gleich != nicht gleich < kleiner als > größer als <= kleiner als oder gleich >= größer als oder gleich Sie können den Wert einer Spalte mit dem Wert einer anderen Spalte oder mit einem Literal vergleichen. SQL-Stringliterale müssen in einfache Anführungszeichen ('), nicht in doppelte Anführungszeichen, die in PHP zulässig sind, eingeschlossen werden. Tipp Wenn einer Spalte kein Wert zugewiesen wurde, weist SQL ihr den speziellen Wert NULL zu. Sie können einer Spalte auch ausdrücklich den Wert NULL zuweisen. Normale Vergleichsoperationen, die auf Gleichheit testen, geben bei einem Vergleich mit NULL-Werten das Ergebnis false zurück. Sie können jedoch den speziellen <=>-Operator verwenden, der Werte auf „NULL-sichere“ Weise vergleicht. Mit diesem Operator ergibt der Vergleich zweier NULL-Werte das Ergebnis true. Darüber hinaus verfügt SQL über mehrere nichtalgebraische Vergleichsoperatoren: x BETWEEN y AND z True, wenn der Wert von x zwischen y und z ist. x LIKE y True, wenn der Wert von x dem Muster y entspricht. x NOT LIKE y True, wenn der Wert von x nicht mit dem Muster y übereinstimmt. x IN (y1,y2) True, wenn der Wert von x in der Liste y1, y2 enthalten ist; die Liste kann ein, zwei oder mehr Elemente enthalten. x NOT IN (y1,y2) True, wenn der Wert von x nicht in der Liste y1, y2 enthalten ist; die Liste kann eins, zwei oder mehr Elemente enthalten. x IS NULL True, wenn x den Wert NULL hat. x IS NOT NULL True, wenn x nicht den Wert NULL hat. Kapitel 13: Leitfaden für relationale Datenbanken und SQL 341 Die Untersprache, mit der Muster für den LIKE-Operator spezifiziert werden, verwendet andere Metazeichen als PHP oder die UNIX-Shell. Das Metazeichen % entspricht null oder mehr Zeichen, und das Metazeichen _ entspricht genau einem Zeichen. Muster wie beispielsweise Strings werden in einfache Anführungszeichen eingeschlossen. Beispielsweise entspricht das Muster '%hund%' jedem String, der den Substring 'hund' enthält, also: 'hund', 'hunde' und 'ein hund'. Tipp Wenn die Zeichen % oder _ selbst Bestandteil des Teststrings sein sollen, müssen Sie \% bzw. \_ verwenden. Wie in PHP dient ein Backslash als Escape-Zeichen und hat zur Folge, dass % oder _ als tatsächliche Zeichen und nicht als Metazeichen interpretiert werden. Wie in PHP können Sie in der DML von SQL logische Ausdrücke bilden, die relationale Ausdrücke verknüpfen. Dabei können Sie die folgenden logischen Operatoren verwenden: AND Und – true, wenn beide Operanden true sind OR Einschließendes Oder – true, wenn mindestens einer der Operanden true ist NOT Nicht – true, wenn der Operand false ist Beispielsweise gibt die folgende Abfrage die Zeilen zurück, deren Personalnummer (employeeno) größer als eins ist oder die einen Namen (name) enthalten, in dem der Substring 'George' vorkommt: SELECT employeeno, name FROM employee WHERE employeeno>1 OR name LIKE '%George%'; Frage an den Experten Frage: Der SQL-Operator zur Mustererkennung verwendet nicht die übliche Syntax für reguläre Ausdrücke. Gibt es eine Möglichkeit, reguläre Ausdrücke in SQL zu verwenden? Antwort: Obwohl SQL eine standardisierte Sprache ist, weichen DBMS-Anbieter immer wieder etwas von der SQL-Sprache ab oder erweitern sie. Deshalb arbeitet jedes DBMS mit einem etwas anderen Dialekt von SQL. Der Dialekt von MySQL verfügt über einen relationalen Operator, der Vergleiche mit regulären Ausdrücken ermöglicht; aber nicht alle Datenbanksysteme enthalten einen solchen Operator. 13 342 PHP 4 IT-Tutorial In MySQL können Sie mit dem folgenden Befehl einen Wert mit einem regulären Ausdruck vergleichen: x REGEXP y Dabei steht x für den Wert, der getestet werden soll, und y gibt einen regulären Ausdruck an, der in einfache Anführungszeichen eingeschlossen ist. MySQL verfügt über viele andere Erweiterungen der SQL-Sprache. Beispielsweise sind in MySQL die folgenden Operatoren gleichwertig: Operator Äquivalent AND && OR || NOT ! Weitere Informationen über die Abweichungen vom SQL-Standard und den Erweiterungen dieses Standards in MySQL finden Sie in dem MySQL-Online-Handbuch unter www.mysql.com. 1-Minuten-Test ● Mit welchem SQL-Befehl werden Daten einer Datenbank abgefragt? ● Mit welcher Klausel können Sie festlegen, welche Zeilen für eine Abfrage ausgewählt werden sollen? ● Mit welchem Operator können Sie einen Stringwert mit einem Muster vergleichen? Datenbankdaten ändern Die Data Manipulation Language von SQL enthält Befehle, mit denen Sie neue Tabellenzeilen einfügen, eine oder mehrere Spalten vorhandener Tabellenzeilen ändern oder Tabellenzeilen löschen können. Um eine neue Tabellenzeile einzufügen, verwenden Sie den INSERT-Befehl, der die folgende Form hat: INSERT INTO tabelle VALUES (wert1, wert2); ● SELECT ● WHERE ● LIKE Kapitel 13: Leitfaden für relationale Datenbanken und SQL 343 Dabei steht tabelle für den Namen der Tabelle, in die die Zeile eingefügt werden soll, und wert1 und wert2 geben den Wert der ersten bzw. der zweiten Tabellenspalte an. Sie können auch mehr oder weniger als zwei Werte angeben; die Anzahl der angegebenen Werte sollte gleich der Anzahl der Tabellenspalten sein. Einer Spalte kann der Wert NULL zugewiesen werden. Das gilt aber nicht für Spalten, deren Definition Gegenteiliges festlegt. Eine gebräuchlichere Form des INSERT-Befehls legt die Namen der Spalten fest, denen Werte zugewiesen werden: INSERT INTO tabelle (spalte1, spalte2) VALUES (wert1, wert2); Bei dieser Form wird der Spalte spalte1 der Wert wert1 und der Spalte spalte2 der Wert wert2 zugewiesen. Wie bei der ersten Form des INSERTBefehls können mehr oder weniger als zwei Spalten und Werte angegeben werden. Die Anzahl der angegebenen Spalten sollte der Anzahl der angegebenen Werte entsprechen. Spalten, die nicht in dem INSERT-Befehl genannt werden und die über keinen DEFAULT-Wert verfügen, wird der Wert NULL zugewiesen, falls dieser Wert nicht verboten ist; in diesem Fall scheitert der INSERT-Befehl. Beispielsweise könnten Sie mit einem Befehl wie dem folgenden eine neue Zeile in die employee-Tabelle einfügen: INSERT INTO employee (employeeno, name) VALUES (4, 'James Monroe'); Anderen Spalten außer employeeno und name wird der Wert NULL zugewiesen. Tipp Sie sollten die erste Form des INSERT-Befehls möglichst nicht verwenden. Wenn auf diese Weise Tabellenspalten hinzugefügt oder gelöscht werden, kann es zu einer Fehlfunktion kommen, da die korrekte Ausführung davon abhängt, dass die Werte in der richtigen Reihenfolge angegeben werden und den Datentypen der Tabellenspalten entsprechen. Mit dem UPDATE-Befehl können Sie eine oder mehrere vorhandene Tabellenzeilen ändern. Der Befehl hat die folgende Form: UPDATE tabelle SET spalte1=wert1, spalte2=wert2 WHERE bedingung; 13 344 PHP 4 IT-Tutorial Dabei steht tabelle für den Namen der Tabelle, deren Zeilen geändert werden sollen. Das Argument spalte1 gibt den Namen der ersten Spalte an, die geändert werden soll, wert1 ist der Wert, der spalte1 zugewiesen werden soll. Das Argument spalte2 gibt den Namen der zweiten Spalte an, die geändert werden soll, wert2 ist der Wert, der spalte2 zugewiesen werden soll. Das Argument bedingung identifiziert die Zeile oder die Zeilen, die geändert werden soll. Sie können auch mehr oder weniger als zwei Spalten aktualisieren. Wenn alle Zeilen aktualisiert werden sollen, können Sie die WHERE-Klausel weglassen. Beispielsweise ändert der folgende Befehl den Namen des Angestellten (employee) mit der Personalnummer (employeeno) 4 in James Monroe: UPDATE employee SET name='James Monroe' WHERE employeeno=4; Der folgende Befehl erhöht das Gehalt (salary) jedes Angestellten um zehn Prozent: UPDATE employee SET salary=1.1*salary; Mit dem DELETE-Befehl können Sie eine Tabellenzeile löschen. Der Befehl hat die folgende Form: DELETE FROM tabelle WHERE bedingung; Wenn Sie alle Tabellenzeilen löschen wollen, können Sie die WHERE-Klausel weglassen. Beispielsweise löscht der folgende Befehl die Tabellenzeile, die den Angestellten (employee) mit der Personalnummer 4 enthält: DELETE FROM employee WHERE employeeno=4; Der folgende Befehl löscht alle Zeilen der employee-Tabelle: DELETE FROM employee; Tipp Die Befehle INSERT, UPDATE und DELETE ändern die Werte von Tabellenzeilen. Im Allgemeinen ist es nicht möglich, die ursprünglichen Werte der Tabellenzeilen wiederzugewinnen, nachdem einer dieser Befehle ausgeführt worden ist. Deshalb ist es wichtig, Sicherungskopien von Datenbanken zu erstellen und Befehle dieser Art vorsichtig auszuführen. Kapitel 13: Leitfaden für relationale Datenbanken und SQL v 345 Frage an den Experten Frage: Gibt es eine einfache Methode, um mehrere Tabellenzeilen in eine Datenbank einzufügen? Antwort: Ja, Sie können die folgende geänderte Form des INSERTBefehls verwenden, mit dem Sie mehrere Tabellenzeilen angeben können: INSERT INTO tabelle (spalte1, spalte2) VALUES (wert1, wert2), (wert3, wert4), (wert5, wert6); Mit dieser Form des Befehls können Sie Gruppen von Werten angeben. Jede Gruppe ist in Klammern eingeschlossen und wird von benachbarten Gruppen durch ein Komma getrennt. Wie bei der gewöhnlichen Form des INSERT-Befehls muss in jeder Gruppe die Anzahl der angegebenen Spalten mit der Anzahl der angegebenen Werte übereinstimmen. Sie können jedoch so viele Gruppen angeben, wie Sie wollen. 1-Minuten-Test ● Schreiben Sie einen SQL-Befehl, um eine neue Zeile in die employeeTabelle einzufügen. Die neue Zeile sollte der Spalte employeeno den Wert 5 und der Spalte name den Wert „James Monroe“ zuweisen. ● Schreiben Sie einen SQL-Befehl, der das Gehalt (salary) jedes Angestellten um 20 Prozent erhöht. ● Schreiben Sie einen SQL-Befehl, der die Tabellenzeilen löscht, in denen die Spalte employeeno den Wert 2 hat. ● INSERT VALUES ● UPDATE ● DELETE INTO employee (employeeno, name) (5, 'James Monroe'); employee SET salary=1.2*salary; FROM employee WHERE employeeno=2; 13 346 PHP 4 IT-Tutorial Sortieren, aggregieren und gruppieren Häufig ist es wichtig, dass Daten in einer bestimmten Reihenfolge ausgegeben werden. Mit der ORDER BY-Klausel können Sie die Reihenfolge festlegen, in der Abfrageergebnisse zurückgegeben werden sollen. Die Klausel hat die folgende Form: ORDER BY wert Wenn Sie mehr als ein Feld sortieren wollen, können Sie mehrere Felder angeben und benachbarte Felder jeweils durch ein Komma trennen. Wenn Sie wollen, können Sie auch festlegen, dass die Sortierung absteigend statt aufsteigend erfolgen soll, indem Sie nach dem Wert das Schlüsselwort DESC angeben. Um beispielsweise alle Angestellten in der Reihenfolge ihrer Gehälter, vom größten zum kleinsten, und innerhalb gleicher Gehaltswerte nach Namen zu sortieren, könnten Sie die folgende Abfrage verwenden: SELECT salary, name FROM employee ORDER BY salary DESC, name; Um nur Mitarbeiter zu erfassen, die mehr als 80.000 DM verdienen, können Sie eine WHERE-Klausel zu dem SELECT-Befehl hinzufügen: SELECT salary, name FROM employee WHERE salary>80000 ORDER BY salary DESC, name; SQL enthält Funktionen, mit denen Sie Berichte erstellen können, die Werte zusammenfassen, indem sie beispielsweise die Anzahl der Tabellenzeilen ermitteln. Die folgende Tabelle fasst die gebräuchlichsten Aggregatfunktionen zusammen: Funktion Rückgabewert count(*) Die Anzahl der Tabellenzeilen count(spalte) Die Anzahl der Tabellenzeilen, die in der angegebenen Spalte Nicht-NULL-Werte enthalten count(distinct spalte) Die Anzahl unterschiedlicher Nicht-NULL-Werte, die in der angegebenen Spalte enthalten sind avg(spalte) Der Durchschnittswert der angegebenen numerischen Spalte min(spalte) Der minimale Wert in der angegebenen Spalte Kapitel 13: Leitfaden für relationale Datenbanken und SQL Funktion Rückgabewert max(spalte) Der maximale Wert in der angegebenen Spalte sum(spalte) Die Summe der Werte in der angegebenen Spalte 347 Beispielsweise gibt die folgende Abfrage die Anzahl der Mitarbeiter und ihr Durchschnittsgehalt zurück: SELECT count(*), avg(salary) FROM employee; Dieser Befehl gibt nur eine Output-Zeile aus, weil die Daten aggregiert werden. Mit der AS-Klausel von SQL können Sie einer Spalte oder einem Ausdruck einen anderen Namen zuweisen. Der angegebene Name wird in den Kopfzeilen von SQL-Berichten verwendet. Die AS-Klausel kann auch beim Arbeiten mit Aggregaten hilfreich sein. Beispielsweise könnte die vorangegangene Abfrage mit einer AS-Klausel folgendermaßen formuliert werden: SELECT count(*) AS Mitarbeiterzahl, avg(salary) AS Durchschnittsgehalt FROM employee; Die Abfrage könnte den folgenden Output erzeugen: +-----------------+---------------------+ | Mitarbeiterzahl | Durchschnittsgehalt | +-----------------+---------------------+ | 2 | 63250.000000 | +-----------------+---------------------+ 1 row in set (0.00 sec) Nehmen wir an, dass Sie die Anzahl der Mitarbeiter in jeder Abteilung ausgeben wollen. Der Output einer solchen Anfrage würde eine Zeile pro Abteilung und nicht pro Mitarbeiter enthalten. Eine solche Anfrage wird mit der GROUP BYKlausel formuliert. Die Klausel hat die folgende Form: GROUP BY sortier-spalte Dabei ist sortier-spalte ein Spaltename oder ein Wert, der in einer ORDER BY-Klausel angegeben wird und der auf eine GROUP BY-Klausel folgen muss. Beispielsweise gibt die folgende Abfrage die Anzahl der Mitarbeiter und das Durchschnittsgehalt pro Abteilung (snummer; deptno) zurück: SELECT count(*), avg(salary) FROM employee 13 348 PHP 4 IT-Tutorial GROUP BY deptno ORDER BY deptno; Wenn Sie nur ausgewählte Gruppen in den Output aufnehmen wollen, geben Sie unmittelbar nach der GROUP BY-Klausel eine HAVING-Klausel an. Diese Klausel hat die folgende Form: HAVING bedingung Um beispielsweise nur Abteilungen zu berücksichtigen, deren Abteilungsnummer größer als zwei ist, formulieren Sie die folgende Abfrage: SELECT count(*), avg(salary) FROM employee GROUP BY deptno HAVING deptno>2 ORDER BY deptno; 1-Minuten-Test ● Schreiben Sie eine Abfrage, die alle Mitarbeiter, nach Namen sortiert, zurückgibt. ● Schreiben Sie eine Abfrage, die das größte Gehalt aller Mitarbeiter zurückgibt. ● Schreiben Sie eine Abfrage, die die Anzahl der Mitarbeiter in allen Abteilungen zurückgibt, die zehn oder mehr Mitarbeiter verfügen. Frage an den Experten Frage: Was ist, wenn ich einen berechneten Wert anstatt eines Spaltenwerts sortieren will? Ist dies möglich? Antwort: Ja, die Werte in den ORDER BY- und GROUP-Klauseln sowie die Bedingungen in den WHERE- und HAVING-Klauseln können Ausdrücke anstelle von einfachen Spaltennamen enthalten. Der nächste Abschnitt beschreibt, wie Sie SQL-Ausdrücke bilden können, die Sie in diesen Kontexten verwenden können. ● SELECT name FROM employee ORDER BY name; ● SELECT max(salary) FROM employee; ● SELECT count(*) FROM employee GROUP BY deptno HAVING count(*)>=10 ORDER BY deptno; Kapitel 13: Leitfaden für relationale Datenbanken und SQL 349 Ausdrücke und Funktionen In SQL können Sie Ausdrücke aus Spaltenwerten, Literalen und Funktionen bilden. Wie in PHP können Sie die Reihenfolge der Auswertung von SQL-Ausdrücken mit Klammern ändern, die Unterausdrücke einschließen, die zuerst ausgewertet werden sollen. Die Tabellen 13.2 bis 13.6 fassen die MySQL-Operatoren und die gebräuchlichen MySQL-Funktionen zusammen. MySQL stellt viele zusätzliche Funktionen zur Verfügung. Die angezeigten Funktionen wurden auf der Basis ihrer Wichtigkeit und ihrer Verfügbarkeit in anderen relationalen Datenbanksystemen ausgewählt. Weitere Informationen über diese und andere MySQL-Funktionen finden Sie in dem MySQL-Online-Handbuch unter http://www.mysql.com. Wenn Sie ein anderes DBMS als MySQL verwenden, sollten Sie dessen Dokumentation konsultieren, um Informationen über die Funktionen zu erhalten, die es unterstützt. Operator Beschreibung + Addition - Subtraktion * Multiplikation / Division | Bitweises OR & Bitweises AND >> Rechts-Shift << Links-Shift ~ Bitweises Komplement Tabelle 13.2 Mathematische Operatoren 13 Operator Beschreibung NOT Logische Negation (NOT) ! Logische Negation (NOT) OR Logisches Oder (OR) || Logisches Oder (OR) AND Logisches Und (AND) && Logisches Und (AND) Tabelle 13.3 Logische Operatoren 350 PHP 4 IT-Tutorial Funktion Rückgabewert abs(x) Absoluter Wert von x atan(x) Arcustangens von x, wobei x als Radians angegeben wird atan2(y,x) Arcustangens von y/x, wobei die Vorzeichen der beiden Argumente den kartesianischen Quadranten festlegen ceiling(x) Kleinste Ganzzahl, die nicht kleiner als x ist cos(x) Cosinus von x, wobei x als Radians angegeben wird exp(x) Basis des natürlichen Logarithms (e) zur Potenz x erhoben floor(x) Größte Ganzzahl, die nicht größer als x ist log(x) Natürlicher Logarithmus von x mod(x,y) Rest von x/y power(x,y) xy rand(x) Zufälliger Fließkommawert, der größer als oder gleich null und kleiner als eins ist sign(x) Der Wert -1, 0 oder 1, je nachdem, ob der Wert von x negativ, null oder positiv ist sin(x) Sinus von x, wobei x als Radians angegeben wird sqrt(x) Quadratwurzel von x tan(x) Tangens von x, wobei x als Radians angegeben wird Tabelle 13.4 Gebräuchliche mathematische Funktionen von MySQL Funktion Rückgabewert ascii(s) ASCII-Code des linken Bytes von s char(n) Zeichen, dessen ASCII-Code n ist concat(s1,s2) Verkettung von s1 und s2, wobei s2 an s1 angehängt wird lcase(s) String s, wobei alle Großbuchstaben in Kleinbuchstaben umgewandelt wurden left(s,n) Die n linken Bytes von s length(s) Anzahl der Bytes in s locate(s1,s2) Position des ersten Vorkommens von s1 in s2 oder null, wenn s1 nicht in s2 gefunden wird ltrim(s) String s, wobei die führenden Leerzeichen entfernt wurden right(s,n) Die n rechten Bytes von s rpad(s1,n,s2) String s1, der rechts mit String s2 aufgefüllt wird, bis das Ergebnis die Länge n hat rtrim(s) String s, wobei Leerzeichen am Ende entfernt wurden space(n) String, der aus n Leerzeichen besteht Tabelle 13.5 Gebräuchliche Stringfunktionen von MySQL Kapitel 13: Leitfaden für relationale Datenbanken und SQL Funktion Rückgabewert substring(s,m,n) Substring von s, der an Position m beginnt und n Bytes lang ist trim(s) String s, wobei Leerzeichen am Anfang und am Ende entfernt wurden ucase(s) String s, wobei alle Kleinbuchstaben in Großbuchstaben umgewandelt wurden 351 Tabelle 13.5 Gebräuchliche Stringfunktionen von MySQL Funktion Rückgabewert dayofmonth(d) Tag des Monats (1–31) eines gegebenen Datums dayofweek(d) Wochentag (1=Sonntag, 2=Montag, ..., 7=Samstag) eines gegebenen Datums dayofyear(d) Tag des Jahres (1–366) eines gegebenen Datums hour(t) Stunde (0–23) einer gegebenen Zeit minute(t) Minute (0–59) einer gegebenen Zeit month(d) Monat (1–12) einer gegebenen Zeit now() Das aktuelle Datum und die aktulle Zeit second(t) Sekunde (0–59) einer gegebenen Zeit week(d) Woche des Jahres (0–53) eines gegebenen Datums year(d) Jahr (1000–9999) eines gegebenen Datums Tabelle 13.6 Gebräuchliche Datums- und Zeitfunktionen von MySQL Frage an den Experten Frage: Welche Funktionen werden beispielsweise von MySQL, aber nicht von anderen Datenbanksystemen unterstützt? Antwort: Wie andere Datenbanksysteme stellt auch MySQL eine Reihe von Funktionen zur Verfügung, die Operationen ausführen, die von dem SQL-Standard nicht abgedeckt werden. Diese Funktionen sind von DBMS zu DBMS recht verschieden. Die folgende Tabelle zeigt einige grundlegende Funktionen, die MySQL zur Verfügung stellt, die aber nicht zum SQL-Standard gehören: Funktion Beschreibung database() Gibt den Namen der geöffneten Datenbank zurück get_lock(s,n) Sperrt eine Datenbank md5(s) Gibt eine MD5-Prüfsumme des Strings s zurück 13 352 PHP 4 IT-Tutorial Funktion Beschreibung password(s) Gibt den String s verschlüsselt zurück, wobei der Verschlüsselungsalgorithmus verwendet wird, den MySQL auf Passwörter anwendet release_lock(s) Gibt eine Datenbanksperre frei user() Gibt den Namen des aktuellen Benutzers zurück version() Gibt die Versionsnummer von MySQL zurück Mit den Funktionen get_lock() und release_lock() können Sie den Zugriff auf Datenbanktabellen kontrollieren. Sie sind wichtig, weil der Schutz der Integrität von Transaktionen in MySQL nicht implementiert ist, was zu Datenverlusten oder zur Zerstörung von Daten führen kann, wenn mehrere Benutzer gleichzeitig auf Daten zugreifen. Jedoch ist die Verwendung dieser Funktionen ein fortgeschrittenes Thema, das über den Rahmen dieses einführenden Buches hinausgeht. Weitere Informationen finden Sie in einem grundlegenden Lehrbuch der Datenbanktheorie oder im MySQL-Online-Handbuch unter www.mysql.com. 1-Minuten-Test ● Welche MySQL-Funktion gibt eine Kleinbuchstabenversion eines Strings zurück? ● Welche MySQL-Funktion entfernt die Leerzeichen am Anfang und am Ende eines Strings? ● Welche MySQL-Funktion gibt das aktuelle Datum und die Zeit zurück? Joins Mit SQL können Sie in einer einzelnen Abfrage auf mehrere Tabellen zugreifen. Die Daten in den verknüpften Tabellen werden normalerweise über die Beziehungen zur Verfügung gestellt, die durch Fremdschlüssel definiert worden sind. Als Beispiel wollen wir annehmen, dass die Datenbank der Datenbank ähnelt, die weiter oben in Abbildung 13.2 gezeigt wurde. Diese Datenkank enthält eine ● lcase() ● trim() ● now() Kapitel 13: Leitfaden für relationale Datenbanken und SQL 353 Fremdschlüssel- Primärschlüssel-Beziehung, die die Tabellen employee und skills verbindet. Betrachten Sie jetzt die folgende Abfrage: SELECT name, skill FROM employee, skills WHERE employee.employeeno = skills.employeeno; Die Ausdrücke employee.employeeno und skills.employeeno werden als qualifizierte Namen bezeichnet. Der erste Ausdruck bezieht sich auf die employeeno-Spalte der employee-Tabelle, und der zweite bezieht sich auf die employeeno-Spalte der skills-Tabelle. Die WHERE-Klausel stellt sicher, dass der Wert des Fremdschlüssels in der skills-Tabelle mit dem entsprechenden Wert des Primärschlüssels in der employee-Tabelle verbunden wird. Ohne die WHEREKlausel würde jede Zeile der skills-Tabelle mit jeder Zeile der employeeTabelle verbunden werden. Ein solches Ergebnis, das so genannte kartesische Produkt, enthält im Allgemeinen viele Zeilen. Die meisten Zeilen sind unerwünscht und sollten deshalb ausgeschlossen werden. Das Ergebnis der Beispielabfrage ist ein Bericht, der die Namen jedes Angestellten in der employee-Tabelle und die zugehörige Fähigkeit in der skillsTabelle anzeigt: +-------------------+-------------+ | name | skill | +-------------------+-------------+ | George Washington | General | | John Adams | Philosopher | | T. Jefferson | Architect | +-------------------+-------------+ 3 rows in set (0.00 sec) Eine Abfrage wie diese, die Daten aus mehreren Tabellen kombiniert, wird als Join bezeichnet. Es sind auch komplexere Joins möglich, die drei oder mehr Tabellen verknüpfen. Bei einem Zwei-Tabellen-Join wird die Tabelle mit dem Primärschlüssel manchmal als Master-Tabelle und die Tabelle mit den Fremdschlüsseln als DetailTabelle bezeichnet. Die Beziehung zwischen den Tabellen wird dann auch als Master-Detail-Beziehung bezeichnet. In einer solchen Beziehung kann eine einzelne Zeile in der Master-Tabelle mit mehreren Zeilen in der Detail-Tabelle verbunden sein. 13 354 PHP 4 IT-Tutorial Frage an den Experten Frage: Was macht man, wenn eine Fremd-PrimärschlüsselBeziehung optional ist, d.h. wenn sie die Kardinalität 0:1 hat? Wenn es zu einer Zeile in der Master-Tabelle keine Zeile in der Detail-Tabelle gibt, erscheint die Zeile in der Master-Tabelle nicht im Output eines Joins. Gibt es eine Möglichkeit, dies zu vermeiden und dafür zu sorgen, dass die Zeile aus der Master-Tabelle in den Output aufgenommen wird? Antwort: Ja, Sie können eine spezielle Art Join, einen so genannten Left-Join oder Left-Outer-Join, verwenden. Ein Beispiel: SELECT name,skill FROM employee LEFT JOIN skills ON employee.employeeno=skills.employeeno; Diese Abfrage gibt alle Einträge der employee-Tabelle unabhängig davon zurück, ob ein Eintrag mit einem Eintrag in der skills-Tabelle verbunden ist oder nicht. Mitarbeiter ohne eine Fähigkeit erhalten in der skill-Spalte einen NULL-Wert: +-------------------+-----------+ | name | skill | +-------------------+-----------+ | George Washington | General | | John Adams | NULL | | T. Jefferson | Architect | +-------------------+-----------+ 3 rows in set (0.00 sec) Viele – vielleicht die meisten – Menschen finden Left-Joins zunächst verwirrend, sodass Sie nicht überrascht sein sollten, wenn Ihnen dieser Join rätselhaft erscheint. Weitere Informationen über Left-Joins finden Sie in einem ausführlichen Lehrbuch der Datenbanktheorie. Kapitel 13: Leitfaden für relationale Datenbanken und SQL 355 1-Minuten-Test ● Nehmen wir an, dass eine Datenbank eine Tabelle namens buch mit dem Primärschlüssel ISBN und eine Tabelle namens verkauf mit dem Primärschlüssel transaktionsid und dem Fremdschlüssel ISBN enthält. Schreiben Sie eine Abfrage, die die beiden Tabellen verknüpft. Projekt 13–1: Mit SQL arbeiten p13–1a.sh p13–1b.sh In diesem Projekt lernen Sie, wie eine MySQL-Datenbank erstellt und manipuliert wird. Sie werden eine Beispieldatenbank konstruieren, um das Formulieren von SQL-Abfragen zu üben. Projektziele ● Erklären, wie eine MySQL-Datenbank erstellt wird ● Demonstrieren, wie mit MySQL interaktive SQL-Abfragen ausgeführt werden ● Eine Beispieldatenbank erstellen, an der das Formulieren von SQLAbfragen geübt werden kann Schritt für Schritt 1. Wenn Sie mit einem Internet Service Provider zusammenarbeiten, der bereits eine MySQL-Datenbank für Sie eingerichtet hat, gehen Sie zu Schritt 4. Andernfalls loggen Sie sich als Systemadministrator ein oder bitten den Systemadministrator, die folgenden Schritte für Sie auszuführen. 2. Erstellen Sie das folgende Shell-Skript, und speichern Sie es unter dem Namen p13–1a.sh: mysql -p -u root<<EOF CREATE DATABASE testdb; USE testdb; GRANT ALL ON testdb.* TO php IDENTIFIED BY 'hiya'; EOF mysqladmin reload ● SELECT * von buch, verkauf WHERE buch.ISBN=verkauf.ISBN 13 356 PHP 4 IT-Tutorial Dieses Skript erstellt eine Datenbank und richtet einen Benutzer (php) ein, der über die volle Berechtigung verfügt, auf die Datenbank zuzugreifen und sie zu manipulieren. Wenn Sie wollen, können Sie den Datenbanknamen (testdb), den Benutzernamen (php) und das Passwort (hiya) durch Werte Ihrer Wahl ersetzen. Wenn Sie Ihren eigenen Login-Benutzernamen und Ihr Passwort angeben, können Sie sich die Arbeit vereinfachen. 3. Führen Sie das Skript aus, indem Sie den folgenden Befehl eingeben: sh p13–1a.sh Der mysql-Befehl fordert Sie auf, das Passwort des Systemadministrators einzugeben. Geben Sie den entsprechenden Wert ein, und drücken Sie auf (¢). Wenn das Skript beendet ist, wird ein Shell-Prompt (eine Eingabeaufforderung der MySQL-Shell) angezeigt. 4. Erstellen Sie das folgende Shell-Skript, und speichern Sie es unter dem Namen p13–1b.sh: mysql -p -u php <<EOF USE testdb CREATE TABLE employee ( employeeno SMALLINT PRIMARY KEY, name VARCHAR(50), hours SMALLINT, dept CHAR(16), salary DECIMAL(8,2), datehired DATE ); INSERT INTO employee ( employeeno, name, hours, dept, salary, datehired ) VALUES ( 1, 'George Washington', 40, Kapitel 13: Leitfaden für relationale Datenbanken und SQL 357 'Accounting', 80000.00, '2005–10–01' ), ( 2, 'John Adams', 35, 'Marketing', 120000.00, '2005–10–15' ), ( 3, 'Thomas Jefferson', 20, 'Sales', 35000.00, '2005–09–01' ); CREATE TABLE skills ( skill char(16) PRIMARY KEY, employeeno SMALLINT ); INSERT INTO skills ( skill, employeeno ) VALUES ( 'General', 1 ), ( 'Philosopher', 2 ), ( 'Architect', 3 ); EOF 13 358 PHP 4 IT-Tutorial Dieses Skript erstellt zwei Datenbanktabellen und fügt mehrere Zeilen in die Tabellen ein. Achten Sie darauf, dass Sie das Skript korrekt eintippen. Alternativ können Sie das Skript von der Website dieses Buches herunterladen, um mögliche Probleme zu vermeiden. Wenn Sie in Schritt 2 den Namen der Datenbank und/oder den Benutzernamen geändert haben, müssen Sie hier die entsprechenden Änderungen einfügen. 5. Führen Sie das Skript aus, indem Sie den folgenden Befehl eingeben: sh p13–1b.sh Das mysql-Programm fordert Sie auf, das Passwort einzugeben, das Sie in dem Skript in Schritt 2 definiert haben (hiya). Geben Sie das Passwort ein, und drücken Sie auf (¢). Wenn das Skript fertig ist, wird ein Shell-Prompt angezeigt. 6. Jetzt können Sie die Datenbank interaktiv abfragen. Geben Sie zu diesem Zweck den folgenden Befehl ein: mysql -p -u php testdb Geben Sie, wenn Sie dazu aufgefordert werden, das Passwort ein, das Sie in Schritt 2 definiert haben (hiya). 7. Geben Sie einige Abfragen der Datenbank ein – beispielsweise: SELECT * FROM employee; SELECT * FROM skills; 8. Jetzt sollten Sie einige anspruchvollere Abfragen Ihrer Wahl ausführen. Die Benutzerschnittstelle funktioniert wie die Linux-Befehlszeile. Mit den Pfeiltasten können Sie vorangegangene Befehle editieren oder wiederholen. 9. Die folgende Liste zeigt einige potenziell nützliche Nicht-SQL-Abfragen, die Sie ausprobieren können: SHOW SHOW SHOW SHOW SHOW SHOW SHOW STATUS; DATABASES; TABLES; COLUMNS FROM employee; INDEX FROM employee; CREATE FROM employee; GRANTS FOR php; Kapitel 13: Leitfaden für relationale Datenbanken und SQL 359 Diese MySQL-spezifischen Abfragen zeigen den Status und die Struktur von Datenbanken und Tabellen an. Mehrere dieser Abfragen erzeugen einen ziemlich umfangreichen Output. Informationen, wie der Output zu interpretieren ist, finden Sie in dem MySQL-Online-Handbuch unter www.mysql.com. 10.Wenn Sie keine weiteren Abfragen mehr ausführen wollen, sollten Sie das mysql-Programm mit dem folgenden Befehl verlassen: quit 9Übungsaufgaben 1. Wie lautet der Fachbegriff für die Komponente einer relationalen Datenbank, die Daten über eine Instanz eines Entitys enthält? 2. Wie lautet der Fachbegriff für die Art von Schlüsseln, die im Allgemeinen nicht für jede Zeile einer Datenbanktabelle eindeutig sind? 3. Welche Kardinalität hat die Art von Beziehung, die bei der E-R-Modellierung entfernt werden muss? 4. Schreiben Sie einen SQL-Befehl, der eine Tabelle namens test erstellt, die zwei 16-Zeichen-Felder namens a und b enthält. 5. Schreiben Sie einen SQL-Befehl, der in die Datenbank, die Sie in Aufgabe 4 erstellt haben, eine Zeile einfügt, die nur Leerzeichen als Wert enthält. 6. Schreiben Sie einen SQL-Befehl, der alle Zeilen zurückgibt, die in der Datenbank enthalten sind, die Sie in Aufgabe 4 erstellt haben. 13 Teil V Anhänge Anhang A Übungsaufgaben: Lösungen 464 PHP 4 IT-Tutorial Kapitel 1: PHP-Programme erstellen 1. Welches Windows-Programm wird häufig verwendet, um PHP-Skripts zu erstellen? Notepad 2. Wie sollte die erste Zeile eines PHP-Skripts lauten? <?php 3. Welche Zeichen sollten verwendet werden, um eine Datei zu benennen, die ein PHP-Skript enthält? Kleinbuchstaben, Ziffern und Bindestriche 4. Wie sollte die Dateierweiterung einer Datei lauten, die ein PHP-Skript enthält? .php 5. Welcher PHP-Befehl wird verwendet, um Text-Output zu einem Webbrowser zu senden? echo 6. Welches Programm wird häufig benutzt, um ein PHP-Skript auf einen Server heraufzuladen? FTP Kapitel 2: PHP-Bausteine 1. Schreiben Sie ein PHP-Literal, das den Wert 12,000 hat. 12000 2. Schreiben Sie ein PHP-Literal, das den Wert 10.39 hat. 10.39 3. Schreiben Sie ein PHP-Literal, das den Namen Ihres Lieblingsautos enthält. "Porsche" oder ähnlich 4. Schreiben Sie den Namen einer PHP-Variablen, mit der Sie den aktuellen Mehrwersteuersatz speichern können. mehrwertsteuer_satz oder ähnlich Anhang A: Übungsaufgaben: Lösungen 5. Schreiben Sie PHP-Befehle, die ein Array erstellen, das den Vornamen jedes Mitglieds Ihrer Familie mit dessen Geburtsjahr verbindet. $year["bill"] = 1953; $year["patrick"] = 1980; (usw. oder ähnlich) 6. Schreiben Sie mit Hilfe der Formel U = 2 x π x R einen PHP-Befehl, der aus dem Radius eines Kreises dessen Umfang berechnet. Benutzen Sie für π den Näherungswert 3.14159. $umfang = 3.14159 * 2 * $radius; (oder ähnlich) 7. Schreiben Sie einen PHP-Befehl, der den absoluten Wert von $entfernung berechnet und das Ergebnis in $netto_entfernung speichert. $netto_entfernung = abs(entfernung); (oder ähnlich) Kapitel 3: HTML-Formulare erstellen 1. Schreiben Sie ein HTML-form-Tag, das seine Daten an ein Skript sendet, das sich unter http://www.mitp.de/cgi-bin/test befindet. <form method="POST" action="http://www.mitp.com/cgi-bin/ test"> 2. Schreiben Sie HTML-Code, der ein mehrzeiliges Control namens adresse zur Texteingabe erstellt. Das Control sollte fünf Zeilen à 80 Zeichen aufnehmen können. <textarea name="adresse" rows="5" cols="80" wrap="xxx"> 3. Schreiben Sie HTML-Code, der ein Pulldown-Menü namens farbe erstellt, das die subtraktiven Primärfaben rot, gelb und blau enthält. Lassen Sie nur die Wahl einer Option zu, und legen Sie rot als Standardwahl fest. <select name="farbe" size="1"> <option selected>rot <option>gelb <option>blau </select> 4. Schreiben Sie HTML-Code, der einen Satz von Optionsfeldern namens size erstellt, mit dem der Benutzer einen der Werte klein, mittel oder groß wählen kann. 465 A 466 PHP 4 IT-Tutorial <input type="RADIO" name="size" value="klein"> <input type="RADIO" name="size" value="mittel"> <input type="RADIO" name="size" value="groß" checked> 5. Schreiben Sie HTML-Code, der ein Formular erstellt, das seine Daten an www.dev.null sendet. Das Formular sollte ein verborgenes Feld namens skript enthalten, das den Wert menu hat. <form method="POST" action="www.dev.null"> <input type="HIDDEN" name="skript" value="menu"> <input type="SUBMIT"> </form> Kapitel 4: Auf Daten zugreifen 1. Welche PHP-Variable sollte verwendet werden, um auf die Daten eines Controls zuzugreifen, das durch das HTML-Tag <input type="TEXT" name="farbe"> definiert wird? $farbe 2. Schreiben Sie einen PHP-Befehl, der den Wert der Variablen $x an den Browser sendet. echo "$x"; 3. Schreiben Sie einen PHP-Befehl, der den Namen der Variablen $y an den Browser sendet. echo "\$y"; 4. Schreiben Sie einen PHP-Befehl, der den URL der referenzierenden Seite an den Browser sendet. echo "$HTTP_REFERER"; Kapitel 5: Mit skalaren Werten arbeiten 1. Schreiben Sie einen Befehl, der eine Konstante namens speed definiert, die den Wert 186.282 hat. define("speed", 186282); 2. Schreiben Sie einen Befehl, der einen Wert ausgibt, der anzeigt, ob eine Konstane namens LAENGE definiert ist. echo defined("LAENGE"); Anhang A: Übungsaufgaben: Lösungen 3. Wenn $cat den Wert "Spot" und $pet den Wert "cat" hat, wie lautet dann der Name einer dynamischen Variablen, die den Wert "Spot" hat? $$pet 4. Welchen Typ hat das Ergebnis, wenn zwei Integer-Werte dividiert werden? Integer 5. Welchen Typ hat das Ergebnis, wenn ein Integer-Wert mit einem DoubleWert multipliziert wird? Double 6. Schreiben Sie einen Befehl, der den Typ der Variablen $cost in integer ändert. settype($cost, "integer"); oder $cost = (integer) $cost; Kapitel 6: Kontrollbefehle schreiben 1. Schreiben Sie einen if-Befehl, der den Wert von $y auf 1 setzt, wenn $x den Wert 1 hat, und der andernfalls den Wert von $y auf 2 setzt. if ($x == 1) $y = 1; else $y = 2; 2. Schreiben Sie einen switch-Befehl, der $y den Wert 5 zuweist, wenn $x den Wert 1 hat, der $y den Wert 15 zuweist, wenn $x den Wert 2 hat, der $y den Wert 20 zuweist, wenn $x den Wert 3 hat, und der andernfalls $y den Wert -1 zuweist. switch ($x) { case 1: $y = 5; break; case 2: $y = 15; break; case 3: $y = 20; break; default: $y = -1; } 467 A 468 PHP 4 IT-Tutorial 3. Schreiben Sie eine for-Schleife, die eine Reihe von Sternchen ausgibt; die Anzahl der Sternchen sollte durch den Wert von $stars festgelegt sein. for ($i = 1; $i <= $stars; $i++) echo "*"; 4. Schreiben Sie einen if-Befehl, der $y den Wert 1 zuweist, wenn $x den Wert 1 hat, der $y den Wert 3 zuweist, wenn $x den Wert 2 hat, der $y den Wert 5 zuweist, wenn $x den Wert 3 hat, und der andernfalls $y den Wert -1 zuweist. if ($x $y = elseif $y = elseif $y = else $y = == 1) 1; ($x == 2) 3; ($x == 3) 5; -1; Kapitel 7: Mit Funktionen arbeiten 1. Schreiben Sie einen Befehl, der die Funktion test() aufruft und die Werte 1 und 2 als Argumente übergibt. test(1, 2); 2. Schreiben Sie einen Befehl, der die Funktion live() aufruft und die Werte 1 und 2 als Argumente übergibt; stellen Sie sicher, dass während der Ausführung der Funktion keine Fehlermeldungen generiert werden. @live(1, 2); 3. Schreiben Sie einen Befehl, der den Inhalt der Datei header.php in das aktuelle Skript einbindet. require ("header.php"); 4. Schreiben Sie die Definition einer Funktion namens quadrat(), die die Fläche eines Quadrats berechnet, wenn die Länge einer Seite des Quadrats bekannt ist. function quadrat($seite) { return $seite * $seite; } Anhang A: Übungsaufgaben: Lösungen 5. Schreiben Sie die Definition einer Funktion namens zaehler(), die den Wert einer statischen lokalen Variablen erhöht und zurückgibt. funktion zaehler() { static zaehler; zaehler++; return zaehler; } Kapitel 8: Mit Arrays arbeiten 1. Schreiben Sie Befehle, die ein Array namens $pop erstellen, das die Namen mehrerer großer Weltstädte mit ihrer Bevölkerungszahl verbindet. $pop["Tokyo"] = 34500000; $pop["New York"] = 20200000; etc. 2. Schreiben Sie einen for-Befehl, der die Elemente eines Arrays namens $dwarfs sequenziell abarbeitet, dessen Schlüsselwert mindestens eins beträgt. Der Body (Körper) des for-Befehls sollte den Namen aller Elemente von $dwarfs ausgeben. Achten Sie darauf, dass der Testausdruck die Tatsache berücksichtigt, dass der niedrigste Schlüssel den Wert eins und nicht null hat. $n = count($dwarfs); for ($i = 1; $i <= $n; i++) { echo "<BR>$dwarfs[$i]"; } 3. Schreiben Sie einen foreach-Befehl, der das Array $states nach einem Element durchsucht, dessen Schlüssel denselben Wert wie die Variable $abbr hat. Geben Sie den Wert, nicht den Schlüssel des entsprechenden Elements aus. foreach($states as $key => $value) { if ($value == $abbr) { echo "<BR>$Wert"; break; } } 469 A 470 PHP 4 IT-Tutorial 4. Schreiben Sie einen Befehl, der das assoziative Array $pop in aufsteigender Reihenfolge nach Werten sortiert. asort($pop); Kapitel 9: Mit Strings arbeiten 1. Schreiben Sie einen Formatstring, der einen linksbündig ausgerichteten Stringwert festlegt, der 24 Stellen lang ist und auf den nach einem Leerzeichen ein linksbündig ausgerichteter double-Wert mit zwei Dezimalstellen folgt. "%-24s %-.2f" 2. Schreiben Sie eine Fluchtsequenz, die das Zeichen repräsentiert, dessen ASCII-Wert oktal 45 beträgt. \045 3. Schreiben Sie einen Funktionsaufruf und eine Zuweisung, der bzw. die die Whitespace-Zeichen am Anfang und Ende von $s entfernt und $r den Wert von $s zuweist. $r = trim($s); 4. Schreiben Sie einen Funktionsaufruf, der einen String zurückgibt, der dem String $s ähnelt, aber bei dem – beginnend mit Position i – n Zeichen durch den String $r ersetzt sind. substr_replace($s, $r, i, n) 5. Schreiben Sie einen regulären Ausdruck, der nur den Substrings "axb", "ayb" und "azb" am Ende eines Strings entspricht. a[xyz]b$ Kapitel 10: Mit Cookies arbeiten 1. Schreiben Sie einen PHP-Befehl, der ein Cookie namens correct erstellt, das den Wert "false" hat und das nach dreißig Minuten abläuft. setcookie("correct", "false", time() + 1800); 2. Schreiben Sie einen PHP-Befehl, der ein Cookie namens bygone löscht. setcookie("bygone", "", time() - 3600); Anhang A: Übungsaufgaben: Lösungen 3. Schreiben Sie einen PHP-Befehl, der den Wert eines Cookies namens age ausgibt. echo "$age"; 4. Schreiben Sie einen PHP-Befehl, der ein Array namens $inhalte in einen String namens $x packt. $x = serialize($inhalte); 5. Schreiben Sie einen PHP-Befehl, der ein Cookie namens woimmer erstellt, das den Wert "hier" hat. Das Cookie sollte nach dreißig Minuten ablaufen und in jedem Verzeichnis des Web-Verzeichnisbaums zugänglich sein. setcookie("woimmer", "hier", time() + 1800, "/"); Kapitel 11: Mit Dateien und Verzeichnissen arbeiten 1. Welcher Unix-Befehl würde das (leere) Verzeichnis test löschen? rmdir test 2. Welche numerischen Berechtigungen würden Sie einer Datei zuweisen, um ihrem Besitzer Read-only-Zugriff und anderen Benutzern überhaupt keine Zugriffsrechte zuzuweisen? 0400 (octal) 3. Welcher Funktionsaufruf öffnet die Datei test.txt und ermöglicht einen Append- und Read-Zugriff auf die Datei? fopen("test.txt", "a+") 4. Welcher Funktionsaufruf setzt den Dateizeiger der Datei, die mit dem Handle $f verbunden ist, auf das Ende der Datei? fseek($f, 0, SEEK_ENDE) oder fseek($f, filesize($f)) 5. Welcher Funktionsaufruf gibt die Berechtigungen zurück, die mit dem Verzeichnis /test verbunden sind? fileperms("/test"); 471 A 472 PHP 4 IT-Tutorial Kapitel 12: E-Mail senden und empfangen 1. Welches Protokoll wird benutzt, um Internet-Mail zu übertragen? SMTP 2. Wieso vereinfachen benutzerdefinierte Funktionen das Programmieren? Mit benutzerdefinierten Funktionen können Sie Operationen, die mehrfach ausgeführt werden, isolieren und sie nur einmal schreiben. Dadurch wird ein Programm kürzer. Außerdem können Sie damit eine Reihe von Operationen unter einem Namen zusammenfassen. 3. Schreiben Sie unter Verwendung der geeigneten benutzerdefinierten Funktion, die in diesem Kapitel beschrieben wurde, einen Befehl, der die IMAPNachricht Nummer 101 aus dem aktuellen Ordner in den Ordner "test" kopiert. Nehmen Sie an, dass der Wert der Variablen $mb das Handle einer offenen IMAP-Verbindung und die Variable $pfx das IMAP-Mailbox-Präfix enthält. copy_message($mb, $pfx, 101, "test"); 4. Schreiben Sie unter Verwendung der geeigneten benutzerdefinierten Funktion, die in diesem Kapitel beschrieben wurde, einen Befehl, der den Ordner "test1" in "test2" umbenennt. Nehmen Sie an, dass der Wert der Variablen $mb das Handle einer offenen IMAP-Verbindung enthält, dass die Variable $server den IMAP-Server-String (einschließlich der Klammern, das Server-Host-Namens, des Protokolls und der Portnummer) enthält, dass die Variable $pfx das IMAP-Mailbox-Präfix enthält und dass die Variablen $old und $new die Ordnernamen enthalten. rename_folder($mb, $server, $pfx, $old, $new); 5. Schreiben Sie unter Verwendung der geeigneten benutzerdefinierten Funktion, die in diesem Kapitel beschrieben wurde, einen Befehl, der die Header der IMAP-Nachricht ausgibt, deren Nummer durch den Wert von $n angegeben wird. Nehmen Sie an, dass der Wert der Variablen $mb das Handle einer offenen IMAP-Verbindung enthält. print_headers($mbx, $n); oder dump_headers($mbx, $n); Anhang A: Übungsaufgaben: Lösungen Kapitel 13: Einführung in relationale Datenbanken und SQL 1. Wie lautet der Fachbegriff für die Komponente einer relationalen Datenbank, die Daten über eine Instanz eines Entitys enthält? table 2. Wie lautet der Fachbegriff für die Art von Schlüsseln, die im Allgemeinen nicht für jede Zeile einer Datenbanktabelle eindeutig sind? foreign key 3. Welche Kardinalität hat die Art von Beziehung, die bei der E-R-Modellierung entfernt werden muss? N:N 4. Schreiben Sie einen SQL-Befehl, der eine Tabelle namens test erstellt, die zwei 16-Zeichen-Felder namens a und b enthält. CREATE TABLE test (a CHAR(15), b CHAR(15)); 5. Schreiben Sie einen SQL-Befehl, der in die Datenbank, die Sie in Aufgabe 4 erstellt haben, eine Zeile einfügt, die nur Leerzeichen als Wert enthält. INSERT INTO test (a, b) VALUES (' ', ' '); 6. Schreiben Sie einen SQL-Befehl, der alle Zeilen zurückgibt, die in der Datenbank enthalten sind, die Sie in Aufgabe 4 erstellt haben. SELECT * FROM test; Kapitel 14: Auf relationale Datenbanken zugreifen 1. Schreiben Sie PHP-Code, der eine Verbindung zu einem MySQL-Server auf dem Host namens db herstellt und dabei die Benutzer-ID admin und das Passwort secret benutzt. $db = mysql_connect("db", "admin", "secret"); 2. Schreiben Sie PHP-Code, der eine Datenbank namens lagerbestand für weitere Zugriffe öffnet. mysql_select_db("lagerbestand"); 473 A 474 PHP 4 IT-Tutorial 3. Schreiben Sie PHP-Code, der die Abfrage ausführt, die in der Stringvariablen $sql gespeichert ist und der das Ergebnis in der Variablen $rset speichert. $rset = mysql_query($sql); 4. Schreiben Sie PHP-Code, der die Fehlernummer anzeigt, die mit der letzten MySQL-Abfrage verbunden ist. echo mysql_errno(); 5. Schreiben Sie PHP-Code, der den Wert der ersten Spalte der nächsten Zeile der Ergebnismenge anzeigt, die in $row gespeichert ist. $row = mysql_fetch_row(); echo $row[0]; 6. Schreiben Sie eine PHP-Schleife, die alle Zeilen einer Ergebnismenge abarbeitet und dabei jede Zeile in der Variable $row speichert. Der Körper der Schleife soll leer sein. while ($row = mysql_fetch_row()) { } Kapitel 15: Klassen und Objekte verwenden 1. Mit welchem PHP-Operator wird ein Objekt instantiiert? new 2. Mit welchem PHP-Schlüsselwort wird eine Klasse definiert? class 3. Wie lautet die korrekte Bezeichnung für die Variablen, die in einer Klasse enthalten sind? Eigenschaften (Properties) 4. Wie lautet die korrekte Bezeichnung für die Funktionen, die in einer Klasse enthalten sind? Methoden 5. Wie lautet die korrekte Bezeichnung für die spezielle Funktion, mit der ein Objekt erstellt wird? Konstructor 6. Als was kann eine Elternklasse (übergeordnete Klasse) noch bezeichnet werden? Basisklasse Anhang A: Übungsaufgaben: Lösungen 7. Als was kann eine Kindklasse (untergeordnete Klasse) noch bezeichnet werden? Abgeleitete Klasse 8. Als was wird eine Methode bezeichnet, die in einer abgeleiteten Klasse redefiniert wird? Überschrieben 9. Als was wird eine Methode bezeichnet, die auf den Wert einer Eigenschaft zugreift, diesen aber nicht ändert? Accessor- oder Get-Methode 10. Als was wird eine Methode bezeichnet, die den Wert einer Eigenschaft ändert? Mutator- oder Set-Methode Kapitel 16: Anwendungs-Templates verwenden 1. Nennen Sie zwei Vorteile des Einsatzes von Templates, um eine große Website zu organisieren. Konsistenz des Designs und Spezialisierung der Mitarbeiter 2. Schreiben Sie einen HTML-Block, der eine Template-Variable namens link verwendet, um den URL zur Verfügung zu stellen, der mit einem Link verbunden ist. Der Text, der mit dem Link verbunden ist, sollte "Hierher gehen" lauten. <a href="{link}">Hierher gehen</a> 3. Schreiben Sie einen PHP-Befehl, der der FastTemplate-Template-Variablen pi den Wert 3,14159 zuweist. Nehmen Sie an, dass sich die PHP-Variable $t auf ein FastTemplate-Objekt bezieht. $t->assign('pi', '3.14159'); 4. Schreiben Sie einen PHP-Befehl, der den Wert der FastTemplate-TemplateVariablen html druckt. Nehmen Sie an, dass sich die PHP-Variable $t auf ein FastTemplate-Objekt bezieht. $t->FastPrint('html'); 475 A 476 PHP 4 IT-Tutorial 5. Schreiben Sie einen PHP-Befehl, der ein FastTemplate-Objekt instantiiert, das die Templates benutzt, die in dem Parent-Verzeichnis des Verzeichnisses gespeichert sind, das das PHP-Skript enthält. Speichern Sie die Referenz auf das Objekt in einer PHP-Variablen namens $ft. $ft = new FastTemplate('..'); Kapitel 17: PHP-Skripts debuggen 1. Wie wird die Debugging-Technik bezeichnet, bei der Abschnitte des Codes auskommentiert werden? Teile und herrsche 2. Verfügt PHP 4 über eine Debugging-Funktion? Nein 3. Welche PHP-Variable enthält den Text der jüngsten Fehlermeldung, selbst wenn die Meldung von Fehlern unterdrückt wird? $php_errormsg 4. Wie werden Fehler bezeichnet, die sich auf Verstöße gegen die Regeln der PHP-Grammatik beziehen? Syntaxfehler 5. Was passiert, wenn ein fataler Fehler auftritt und die Meldung von Fehlern unterdrückt wird? Das Programm wird beendet. Anhang B PHP installieren 478 PHP 4 IT-Tutorial Dieser Anhang beschreibt die Installation von PHP und zugehöriger Software – einschließlich des Apache-Webservers und des MySQL-Datenbanksystems – unter gebräuchlichen PC-Betriebssystemen. Weil Aktualisierungen von PHP und der zugehörigen Software Einfluss auf die Installation haben können, sollten Sie unter http://www.php.net und – sofern möglich – auf der Website des Anbieters Ihres Betriebssystems die neuesten Informationen prüfen. Die Verfahren, die hier beschrieben werden, gelten nur für Intel-kompatible PC-Systeme. Wenn Sie PHP auf einem SPARC-Computer oder einem anderen, nicht mit Intel kompatiblen System installieren wollen, müssen Sie den Installationsanweisungen folgen, die unter http://www.php.net und an anderen Stellen zu finden sind. Das Installieren und Konfigurieren von PHP und der zugehörigen Software kann leicht die Kenntnisse erfahrener Programmierer überfordern, von Programmieranfängern ganz zu schweigen. Eine einfache Alternative, um Zugang zu einem PHP-Server zu erlangen, besteht darin, ein Konto bei einem Internet Service Provider (ISP) zu eröffnen, der PHP unterstützt. Die PHP-Website enthält eine Liste derartiger ISPs (siehe http://www.php.net/links.php). Red Hat Linux 7.1 Red Hat Linux ist eine sehr gebräuchliche Plattform für die Ausführung von PHP. Die neueste Version von Red Hat Linux vereinfacht das Installieren von PHP und zugehöriger Software. Die folgenden Unterabschnitte beschreiben die Installation der PHP-spezifischen RPM-Pakete unter Red Hat Linux 7.1. Je nach Konfiguration Ihres Systems müssen Sie möglicherweise zusätzliche Pakete installieren, um den Abhängigkeiten der Pakete Rechnung zu tragen, die in den einzelnen Befehlen vorkommen. Apache installieren Disk 1 von Red Hat Linux 7.1 enthält das RPM-Paket für den Apache-Webserver. Sie können dieses Paket mit den folgenden Befehlen installieren: su mount -t iso9660 /dev/cdrom /mnt/cdrom cd /mnt/cdrom/RedHat/RPMS rpm --replacepkgs -Uvh apache-1*.rpm cd umount /mnt/cdrom exit Anhang B: PHP installieren 479 PHP installieren Disk 1 von Red Hat Linux 7.1 enthält das RPM-Paket für PHP. Sie können dieses Paket mit den folgenden Befehlen installieren: su mount -t iso9660 /dev/cdrom /mnt/cdrom cd /mnt/cdrom/RedHat/RPMS rpm --replacepkgs -Uvh php-4*.rpm cd umount /mnt/cdrom exit MySQL installieren Disk 2 von Red Hat Linux 7.1 enthält die RPM-Pakete für das MySQL-Datenbanksystem. Sie können diese Pakete mit den folgenden Befehlen installieren: su mount -t iso9660 /dev/cdrom /mnt/cdrom cd /mnt/cdrom/RedHat/RPMS rpm --replacepkgs -Uvh \ mysql-3*.rpm \ mysql-server-*.rpm \ mysqlclient9-*.rpm \ php-mysql-*.rpm cd umount /mnt/cdrom exit IMAP installieren Disk 2 von Red Hat Linux 7.1 enthält die RPM-Pakete für das IMAP-Mail-System. Sie können diese Pakete mit den folgenden Befehlen installieren: su mount -t iso9660 /dev/cdrom /mnt/cdrom cd /mnt/cdrom/RedHat/RPMS rpm --replacepkgs -Uvh \ imap-2000–9*.rpm \ php-imap-*.rpm cd umount /mnt/cdrom exit B 480 PHP 4 IT-Tutorial MySQL konfigurieren Leider ist es unter Red Hat Linux 7.1 etwas umständlich, MySQL zu konfigurieren. Wahrscheinlich wird dieses Problem jedoch von Red Hat in nächster Zeit gelöst werden. Als dieses Buch geschrieben wurde, war es möglich, MySQL mit den folgenden Befehlen zu konfigurieren: su service mysqld start su mysql mysql_install_db mysqladmin -u root password 'pass' mysqladmin -p -u root -h fqdn password 'pass' mysqladmin -p -u root -h host password 'pass' mysqladmin -p -u root -h localhost password 'pass' mysqladmin -p -u root -h localhost.localdomain \ password 'pass' exit exit Dabei haben die kursiven Wörter die folgenden Bedeutungen:: ● pass ist das Password des root-Benutzers ● fqdn ist der komplette Domänenname des lokalen Hosts ● host ist der Host-Name des lokalen Hosts Nach dem ersten mysqladmin-Befehl fragen die folgenden mysqladminBefehle nach dem Password, das durch den ersten Befehl gesetzt worden ist. Nachdem diese Befehle ausgeführt worden sind, kann der root-Benutzer die mysql- und mysqladmin-Programme benutzen. Insbesondere kann der rootBenutzer das mysqladmin-Programm verwenden, um zusätzliche Benutzer einzurichten. Den Apache-Dienst starten Nach der Installation von PHP und der zugehörigen Software müssen die damit verbundenen Dienste gestartet werden. Der MySQL-Dienst wurde durch das weiter oben genannte Konfigurationsskript gestartet. Der Apache-Webserver muss jedoch manuell gestartet werden. Geben Sie zu diesem Zweck die folgenden Befehle ein: su service httpd start exit Anhang B: PHP installieren 481 Dieser Server sollte immer neu gestartet werden, wenn die HTTP-Konfigurationsdatei, /etc/httpd.conf, geändert wird. Um den Server neu zu starten, geben Sie die folgenden Befehle ein: su service httpd stop service httpd start exit Alternativ können Sie Ihr System neu starten. Apache sollte automatisch starten, wenn das System den Run-Level 3 oder höher erreicht. Die Installation testen Um zu prüfen, ob Apache und PHP installiert sind und ausgeführt werden, wählen Sie mit einem Browser zunächst den Host an, auf dem sie installiert sind, und prüfen, ob der Browser die Apache-Testseite anzeigen kann. Zeigen Sie beispielsweise mit einem Browser, der selbst auf dem Host läuft, auf http://localhost/. Der Browser lynx ist für diesen Zweck gut geeignet, weil er keine funktionsfähige grafische Benutzerschnittstelle erfordert. Um mit lynx zu prüfen, ob Apache ausgeführt wird, geben Sie den folgenden Befehl ein: lynx http://localhost/ Um zu prüfen, ob PHP korrekt funktioniert, erstellen Sie das folgende Skript und speichern es in der Datei /var/www/html/phpinfo.php: <?php phpinfo(); ?> Zeigen Sie dann mit einem Browser auf den URL, der mit dem Skript verbunden ist (http://host/phpinfo.php), wobei host für den Namen des Hosts steht, auf dem Apache ausgeführt wird. Wenn der Browser auf demselben Host wie Apache ausgeführt wird, können Sie localhost als Wert von host angeben. Wenn PHP ausgeführt wird, sollten Sie die PHP-Informationen sehen, die von der phpinfo()-Funktion angezeigt werden. An diesem Punkt können Sie die Optionen der PHP-Konfiguration ändern. Editieren Sie zu diesem Zweck die Datei /etc/php.ini. Starten Sie dann Apache neu, indem Sie die folgenden Befehle eingeben: B 482 PHP 4 IT-Tutorial su service httpd stop service httpd start exit Andere Linux- und UnixVersionen Beim Installieren von PHP und der zugehörigen Software unter Red Hat Linux 6.2 und unter anderen Versionen von Linux und Unix ist es im Allgemeinen erforderlich, dass Sie PHP – und wahrscheinlich einige oder alle Programme der zugehörigen Software – mit Hilfe des Quellcodes erstellen. Dasselbe gilt wahrscheinlich auch, wenn Sie eine aktualisierte Version von PHP oder der zugehörigen Software installieren wollen, die noch nicht in die Red-Hat-Distribution aufgenommen worden sind. Anmerkungen und Hinweise zur Installation und Konfiguration von PHP finden Sie unter http://www.php.net/manual/en/installation.php im PHP-Online-Handbuch. Wenn Sie PHP mit Hilfe des Quellcodes erstellen wollen, müssen Sie die folgenden Schritte ausführen: ● die Quelldateien für PHP und Apache herunterladen ● die Quelldateien für die Software herunterladen, die Sie zusammen mit PHP verwenden wollen – wie beispielsweise MySQL oder IMAP ● die erforderlichen Softwareentwicklungswerkzeuge installieren – einschließlich C-Compiler, make-Utility, flex, bison und anderer Werkzeuge, die zum Kompilieren der Quelldateien benötigt werden ● die zugehörige Software als Libraries so konfigurieren und kompilieren, dass diese für Apache/PHP zugänglich sind ● PHP konfigurieren und kompilieren ● Apache konfigurieren, kompilieren und installieren Die Schritte, die Sie bei diesen Operationen ausführen müssen, ändern sich mit jeder neuen Version von PHP, Apache und der zugehörigen Software. Folglich müssen Sie – um einigermaßen Aussicht auf Erfolg zu haben – die einschlägigen Anweisungen der jeweiligen neuen Software-Versionen befolgen. Diese Aufgabe wird dadurch noch erschwert, dass die Versionen von PHP, Apache und der zugehörigen Software nicht synchronisiert sind. Deshalb können Aktualisierungen in einer Anwendung Änderungen der Installationsprozeduren von ande- Anhang B: PHP installieren ren Anwendungen erforderlich machen. Möglicherweise steht die geänderte Installationsprozedur jedoch erst zur Verfügung, wenn eine neue Version der betroffenen Anwendung freigegeben wird. Darüber hinaus setzen die Installationsanweisungen im Allgemeinen gründliche Kenntnisse der Unix/Linux-Befehle sowie der Systemverwaltung voraus. Deshalb sollten Sie, wenn Sie PHP installieren und konfigurieren wollen, die Ressourcen zu Rate ziehen, die in Anhang C genannt werden. Insbesondere werden Sie feststellen, dass die Newsgroups und Mailing-Listen eine wichtige Quelle sind, wenn Sie Hilfe zur Installation und Konfiguration von PHP suchen. Windows NT/2000 und 95/98/ME Um PHP unter einem Microsoft-Betriebssystem zu installieren, müssen Sie zunächst einen unterstützten Webserver installieren und konfigurieren. Unter Windows NT/2000 können Sie die folgenden Komponenten verwenden: ● Apache ● Microsoft Internet Information Server (IIS), Version 4.0 oder höher ● Netscape Enterprise Server oder iPlanet Server ● O'Reilly Website Pro ● Xitami Unter Windows 95/98/ME können Sie die folgenden Komponenten verwenden: ● Apache ● Microsoft Personal Webserver (PWS; nur für Windows 98/ME empfohlen) ● O'Reilly Website Pro ● Xitami Die folgenden Anweisungen erklären die Installation von Apache, IIS und PWS. Informationen über den Einsatz anderer Webserver, wie beispielsweise O'Reilly Website Pro, finden Sie in der Dokumentation des betreffenden Webservers. 483 B 484 PHP 4 IT-Tutorial Apache Um Apache zu installieren, laden Sie die Windows-Binärdistribution von http:/ /www.apache.org herunter und befolgen die Installations- und Konfigurationsanweisungen unter http://httpd.apache.org/docs/windows.html. IIS Um IIS unter Windows NT zu installieren, laden Sie das Option-Pack von Windows NT 4.0 von der NT-Server-Webseite (http://www.microsoft.com/ ntserver/) herunter. Microsoft baut seine Website regelmäßig um, sodass Sie möglicherweise die Suchfunktion der Site verwenden müssen, um die Datei zu finden. Als dieses Buch geschrieben wurde, befand sich die Datei unter http:// www.microsoft.com/ntserver/nts/downloads/recommended/NT4OptPk/ default.asp. Microsoft IIS ist in der Windows-2000-Distribution enthalten. Um IIS unter Windows 2000 zu installieren, wählen Sie START|EINSTELLUNGEN|SYSTEMSTEUERUNG|SOFTWARE|WINDOWS SETUP. Wenn das IIS-Kontrollkästchen aktiviert ist, ist der IIS bereits installiert. Andernfalls aktivieren Sie das Kontrollkästchen, klicken auf OK und folgen Anweisungen auf dem Bildschirm. PWS Um PWS unter Windows 98/ME zu installieren, legen Sie die Distributions-CD von Windows 98/ME in das CD-ROM-Laufwerk Ihres Systems ein. Gehen Sie mit dem Windows Explorer in das add-ons-Verzeichnis und dann in das pwsUnterverzeichnis. Doppelklicken Sie in diesem Verzeichnis auf die Datei setup.exe, und folgen Sie den Anweisungen auf dem Bildschirm, um PWS zu installieren. Notieren Sie sich das Verzeichnis, das Sie als Standard-Home-Verzeichnis für Ihre Webveröffentlichungen gewählt haben. Üblicherweise wird das Verzeichnis C:\Inetpub\wwwroot für diesen Zweck angelegt bzw. verwendet. Sie können jedoch ein anderes Verzeichnis Ihrer Wahl für diesen Zweck verwenden. PHP Um PHP zu installieren, laden Sie die Win32-CGI-Binärversion von PHP von http://www.php.net herunter. Entpacken Sie dann die Distributionsdatei, und folgen Sie den Anweisungen, die in der Datei install.txt enthalten sind. Beispiel Eine Anleitung für eine Beispielinstallation finden Sie im Stammverzeichnis der beiliegenden CD. Anhang C PHP-Ressourcen 486 PHP 4 IT-Tutorial Dieser Anhang nennt einige Ressourcen, die Ihnen helfen können, PHP und die zugehörige Software zu installieren, zu konfigurieren und zu verwenden. Websites ● Die PHP Conference Material-Site, conf.php.net, bietet Präsentationen an, die auf PHP-spezifischen Konferenzen vorgestellt wurden. ● Der PHP Web Ring, nav.webring.yahoo.com/hub?ring=php&list, ist ein Webring, der über 75 PHP-spezifische Sites enthält. ● Der PHP Resource Index, php.resourceindex.com, listet PHP-Code, -Dokumentation und -Interessengemeinschaften auf. ● Das PHP Classes Repository, phpclasses.upperdesign.com, bietet frei verfügbare PHP-Klassen an. ● PX, der PHP Code Exchange, px.sklar.com, bietet PHP-Code an. ● Das Webentwicklungsportal von HotScripts.com, www.hotSkripts.com/ PHP, enthält Übersichten über PHP-spezifische Bücher, Artikel, Interessengemeinschaften, Programme, Werkzeuge, Tipps, Tutorien und Websites. ● PHP Editors, www.itworks.demon.co.uk/phpeditors.htm, enthält eine Liste der PHP-fähigen Editoren. ● Linux Guruz, www.linuxguruz.org, ist eine Site mit vielen Links zu PHPund Linux-spezifischen Ressourcen. ● Die Website von MySQL, www.mysql.com ● Die Website von PHP, www.php.net ● PHPBuilder, www.phpbuilder.com, enthält PHP-spezifische Artikel, Tutorien, Webforen sowie PHP-Code. ● phpWizard.net, www.phpwizard.net, enthält Artikel, Tutorien und Projekte für PHP-Entwickler. ● WeberDev.com, www.weberdev.com, enthält Code-Beispiele, Artikel und Tutorien für Webentwickler. ● Zend.com, www.zend.com, ist die Website eines Entwicklers der PHP-Technik. Anhang C: PHP-Ressourcen 487 Mailing-Listen PHP-Benutzer sponsern mehrere Mailing-Listen. Diese Listen werden von www.php.net und www.phpbuilder.com archiviert, die ebenfalls Webseiten zum Abonnieren der folgenden Mailing-Listen anbieten: ● php-db, eine Mailing-Liste für Entwickler, die Datenbanken mit PHP benutzen ● php-developer-list, eine Mailing-Liste für PHP-Entwickler ● php-general, eine allgemeine PHP-spezifische Mailing-Liste ● php-i18n, eine Mailing-Liste für das PHP Internationalization Project ● php-install, eine Mailing-Liste zur Unterstützung der Installation von PHP ● phplib-dev-list, eine Mailing-Liste für PHPLib-Entwickler ● phplib-list, eine Mailing-Liste für PHPLib-Benutzer ● php-migration, eine Mailing-Liste für Entwickler, die Systeme nach (oder von) PHP migrieren ● php-windows, eine Mailing-Liste für PHP-Benutzer unter Microsoft Windows Newsgroups Mehrere USENET-Newsgroups behandeln PHP-spezifische Themen. Wenn Ihr Internet Service Provider keinen Zugang zu Newsgroups bietet, können Sie Newsgroup-Beiträge unter http://groups.google.com lesen und suchen. Die für Sie relevanten Newsgroups sind: ● php.dev, eine Newsgroup für PHP-Entwickler ● php.general, eine Newsgroup für PHP-Benutzer ● php.windows, eine Newsgroup für PHP-Benutzer unter Microsoft Windows C Anhang D UNIX-Grundlagen 490 PHP 4 IT-Tutorial Dieser Anhang erklärt grundlegende UNIX-Befehle, die von den meisten UNIX-ähnlichen Betriebssystemen einschließlich Linux unterstützt werden. Der Anhang beschränkt sich auf einfache Befehle, die üblicherweise verwendet werden, wenn man auf einem UNIX-basierten Host mit einem Benutzerkonto der Art arbeitet, wie es beispielsweise von vielen Internet Service Providern zur Verfügung gestellt wird. Um ein UNIX-System zu verwalten, anstatt es nur zu benutzen, müssen Sie eine etwas komplizierte Reihe anderer Befehle beherrschen. Wenn Sie mehr über die UNIX-Systemverwaltung wissen wollen, sollten Sie UNIX: The Complete Reference von Kenneth Rosen und Doug Host (Osborne McGraw-Hill, 1999) lesen. Im ersten Abschnitt dieses Anhangs werden die grundlegenden Termini und Begriffe beschrieben, die Sie kennen müssen, um UNIX und UNIX-Befehle zu verstehen. Im zweiten Abschnitt dieses Anhangs werden gebräuchliche UNIXOperationen erklärt. Grundlegende UNIX-Begriffe UNIX basiert wie andere bekannte Betriebssysteme auf einer Handvoll grundlegender Begriffe. Die wichtigsten dieser Begriffe sind: ● Dateien, die Daten speichern ● Verzeichnisse, die Dateien und andere Verzeichnisse (so genannte Unterverzeichnisse) enthalten ● Pfade, die die Speicherorte von Dateien und Verzeichnissen angeben Weil UNIX ein Multiuser-Betriebssystem ist, müssen Sie mehrere zusätzliche grundlegende Begriffe kennen. Die wichtigsten dieser Begriffe sind: ● Benutzerkonten, die autorisierten Systembenutzern zugeordnet sind ● Benutzergruppen, die einen oder mehrere Benutzer zu einer Gruppe zusammenfassen, die dann als eine Einheit behandelt werden kann ● Berechtigungen, die festlegen, welche Operation Benutzer und Gruppen an oder mit Verzeichnissen und/oder Dateien ausführen dürfen Anhang D: UNIX-Grundlagen 491 Dateien Wie andere bekannte Betriebssysteme auch speichert UNIX Daten in Objekten, die als Dateien bezeichnet werden. UNIX-Dateien können Text oder ASCIIDaten sowie binäre Daten, wie beispielsweise ausführbaren Code, enthalten. Der Name, den Sie einer UNIX-Datei zuweisen, muss bestimmte Formvorschriften erfüllen, die bei den einzelnen UNIX-Versionen verschieden sind. Um sicherzugehen, können Sie die folgenden übermäßig konservativen Regeln beachten: ● Der Name sollte nicht länger als 32 Zeichen sein. ● Der Name sollte mit einem Kleinbuchstaben beginnen. ● Der Name sollte nur Kleinbuchstaben, Ziffern und Unterstreichungszeichen enthalten; optional kann der Dateiname ein einzigen Punkt enthalten, auf den nicht mehr als drei Zeichen folgen. Die tatsächlichen UNIX-Vorschriften für Dateinamen sind wesentlicher weniger restriktiv als diese Regeln. Doch wenn Sie diese Regeln beachten, werden Sie Probleme vermeiden, die andernfalls auftreten könnten, wenn Sie Dateien von einem UNIX-System auf ein Nicht-UNIX-System oder umgekehrt übertragen. Beispielsweise werden im Gegensatz zu UNIX-Dateinamen bei Dateinamen unter Microsoft Windows Groß- und Kleinbuchstaben nicht unterschieden. Das bedeutet, dass unter Microsoft Windows die Namen abc und ABC dieselbe Datei bezeichnen, während diese Namen unter UNIX zwei verschiedene Dateien bezeichnen. Indem Sie nur Kleinbuchstaben für UNIX-Dateinamen verwenden, vermeiden Sie mögliche Irrtümer und Verwechslungen, wenn Sie Dateien von einem Betriebssystem auf ein anderes übertragen. Verzeichnisse Verzeichnisse, manchmal auch Ordner genannt, enthalten Dateien und andere Verzeichnisse. Ein Verzeichnis, das in einem Verzeichnis enthalten ist, wird als ein Unterverzeichnis bezeichnet. Das Verzeichnis, das ein gegebenes Verzeichnis enthält, wird als Oberverzeichnis, übergeordnetes Verzeichnis oder Elternverzeichnis des gegebenen Verzeichnisses bezeichnet. Jedes System verfügt über ein spezielles Verzeichnis, das als Root-, Stammoder Wurzelverzeichnis bezeichnet und (unter UNIX) durch einen einzelnen Schrägstrich (Slash = /) repräsentiert wird. Das Root-Verzeichnis verfügt über Unterverzeichnisse, die ihrerseits weitere Unterverzeichnisse haben. Diese Unterverzeichnisse bilden eine Hierarchie, an deren Spitze das Root-Verzeichnis steht. Das Ergebnis ähnelt der Struktur, die in Abbildung D.1 gezeigt wird. D 492 PHP 4 IT-Tutorial Abbildung D.1 Eine vereinfachte Verzeichnishierarchie Pfade Verzeichnisnamen müssen in einem System nicht eindeutig sein. Andernfalls könnten zwei Benutzer – beispielsweise Adam und Betty – nicht gleichzeitig Verzeichnisse mit dem Namen personal anlegen. Der komplette Name eines Verzeichnisses wird durch seinen Pfad festgelegt. Der Pfad enthält die Folge der Verzeichnisse vom Root-Verzeichnis bis zu dem aktuellen Verzeichnis. Die einzelnen Komponenten eines Pfads werden durch einen Schrägstrich (/) getrennt, also durch dasselbe Symbol, das auch das Root-Verzeichnis kennzeichnet. Sie können diesen trennenden Schrägstrich als eine Operation „gehe zu Verzeichnis“ auffassen, wobei Verzeichnis für den Verzeichnisnamen bedeutet, der unmittelbar auf den Schrägstrich folgt. Um einem Pfad zu folgen, beginnen Sie beim Root-Verzeichnis und folgen der Verzweigung zu jedem angegebenen Verzeichnis, bis Sie das Ende des Pfads erreichen. Beispielsweise zeigt Abbildung D.1, dass den Benutzern Adam und Betty jeweils ein Verzeichnis zugewiesen wurde. Das persönliche Verzeichnis von Adam hat den Pfad /home/adam/personal. Falls Betty ebenfalls über ein persönliches Verzeichnis verfügen würde, würde dessen Pfad /home/betty/personal lauten. Manchmal steht am Ende eines Pfads ein Schrägstrich (/), was aber die Bedeutung der Pfadangabe nicht ändert. Die Pfade /home/adam/personal und / home/adam/personal/ werden als gleichbedeutend angesehen. Anhang D: UNIX-Grundlagen Manchmal ist es praktisch, einen Pfad dadurch abzukürzen, dass seine Position relativ zu einem anderen Verzeichnis als dem Root-Verzeichnis angegeben wird. Solche Pfade werden als relative Pfade bezeichnet, und das Verzeichnis, auf das bezogen ein relativer Pfad angegeben wird, wird als Basisverzeichnis des Pfads bezeichnet; ein Pfad, der in Relation zum Root-Verzeichnis angegeben wird, wird absoluter Pfad genannt. Absolute Pfade beginnen immer mit einem Schrägstrich, um ihre Verbindung mit dem Root-Verzeichnis auszudrücken. Relative Pfade beginnen immer mit dem Namen eines Verzeichnisses, nämlich mit dem Namen des ersten Verzeichnisses, das nach dem Basisverzeichnis aufgesucht werden soll. Relativ zu dem Verzeichnis /home hat Adams persönliches Verzeichnis den Pfad adam/personal. Relativ zu dem Verzeichnis /home/adam hat Adams persönliches Verzeichnis den Pfad personal. Manchmal werden zwei spezielle Symbole verwendet, um relative Pfade anzugeben. Das Symbol .. (zwei Punkte) steht für das übergeordnete Verzeichnis, und das Symbol . (ein Punkt) steht für das aktuelle Verzeichnis. Relativ zu dem Verzeichnis /home/betty hat Adams persönliches Verzeichnis den Pfad ../ adam/personal. Relativ zu dem Verzeichnis /bin hat Adams persönliches Verzeichnis den Pfad ../home/adam/personal. Auch Dateien verfügen über Pfade. Der Pfad einer Datei ist ein absoluter oder relativer Pfad, der das Verzeichnis angibt, das die Datei enthält, gefolgt von ein Schrägstrich /, gefolgt vom Namen der Datei. Beispielsweise hann die Datei index.html im Verzeichnis /var/www/html durch den Pfad /var/www/html/ index.html identifiziert werden. Der Name einer Datei selbst ist eine spezielle Art eines relativen Pfads, der relativ zu dem Verzeichnis ist, das die Datei enthält. Benutzerkonten Um den Zugang zu einem UNIX-System zu kontrollieren, werden für autorisierte Benutzer so genannte Benutzerkonten oder kurz Konten eingerichtet. Ein Benutzerkonto verfügt üblicherweise über mehrere Eigenschaften, wie beispielsweise: ● den Namen des Benutzers ● einen speziellen Benutzernamen, mit dem der Benutzer dem System gegenüber identifiziert wird ● eine numerische Benutzer-ID ● ein Passwort, mit dem der Benutzer authentifiziert wird Im Allgemeinen wird einem Benutzer ein spezielles Verzeichnis für den persönlichen Gebrauch zugewiesen. Dieses Verzeichnis wird als das Home-Ver- 493 D 494 PHP 4 IT-Tutorial zeichnis des Benutzers bezeichnet. Der Systemadministrator eines UNIXSystems verfügt über ein spezielles Benutzerkonto mit dem Benutzernamen root. Dieser Systemadministrator kann Operationen ausführen, die normalen Benutzern verboten sind. Benutzergruppen Manchmal ist es nützlich, eine Reihe von Benutzerkonten auf einmal anzusprechen. Unter UNIX kann ein Systemadministrator für diesen Zweck Benutzergruppen definieren. Jedes UNIX-Konto gehört zu einer oder zu mehreren Benutzergruppen. Eigentümerschaft und Berechtigungen Jede UNIX-Datei verfügt über eine Reihe von so genannten Berechtigungen, die festlegen, welche Operationen Benutzer ausführen dürfen. Wenn ein Benutzer eine Datei oder ein Verzeichnis erstellt, kann er der Datei oder dem Verzeichnis Berechtigungen zuweisen. Dasselbe kann auch der Systemadministrator tun. Die möglichen Berechtigungen lauten: ● Read: (lesen) Diese Berechtigung erlaubt einem Benutzer, den Inhalt einer Datei anzuschauen. ● Write: (schreiben) Diese Berechtigung erlaubt einem Benutzer, den Inhalt einer Datei zu löschen, zu ändern oder neue Daten in die Datei einzufügen. ● Execute: (ausführen) Diese Berechtigung erlaubt einem Benutzer, ein Skript oder ein binäres Programm auszuführen. Auf ähnliche Weise sind auch UNIX-Verzeichnisse mit einem Satz von Berechtigungen verbunden. Diese Berechtigungen haben dieselben Namen wie die Berechtigungen für Dateien, aber besitzen etwas andere Bedeutungen: ● Read: (lesen) Diese Berechtigung erlaubt einem Benutzer festzustellen, welche Dateien und Unterverzeichnisse in dem Verzeichnis enthalten sind. ● Write: (schreiben) Diese Berechtigung erlaubt einem Benutzer, neue Dateien und Unterverzeichnisse in dem Verzeichnis zu erstellen und Dateien und Verzeichnisse aus dem Verzeichnis zu löschen. ● Execute: (ausführen) Diese Berechtigung erlaubt einem Benutzer, auf Dateien und Unterverzeichnisse in dem Verzeichnis zuzugreifen. Anhang D: UNIX-Grundlagen 495 Hinweis Um eine Datei zu löschen, benötigt ein Benutzer nur eine Write-Berechtigung für das Verzeichnis, das die Datei enthält. Der Benutzer benötigt keine WriteBerechtigung für die Datei selbst. Jede Datei und jedes Verzeichnis ist mit einem Benutzerkonto verbunden, das als ihr bzw. sein Besitzer bezeichnet wird. Außerdem ist die Datei bzw. das Verzeichnis mit einer Benutzergruppe verbunden, die als ihr bzw. sein Gruppenbesitzer bezeichnet wird. Einige UNIX-Systeme erlauben es dem Besitzer einer Datei oder eines Verzeichnisses, die Eigentümerschaft (den Besitz) auf ein anderes Benutzerkonto zu übertragen. Alle UNIX-Systeme erlauben es dem Besitzer einer Datei oder eines Verzeichnisses die Gruppeneigentümerschaft der Datei oder des Verzeichnisses auf jede Gruppe zu übertragen, deren Mitglied der Besitzer ist. Dem Besitzer einer Datei oder eines Verzeichnisses können eine oder mehrere der möglichen Berechtigungen (read, write und execute, dt. lesen, schreiben und ausführen) zugewiesen werden, um damit die Operationen festzulegen, die der Besitzer ausführen darf. Auf ähnliche Weise können dem Gruppenbesitzer einer Datei eine oder mehrere der möglichen Berechtigungen zugewiesen werden. Schließlich sind eine oder mehrere Berechtigungen mit einer speziellen Gruppe namens others verbunden. Dabei handelt es sich um Benutzer, die weder Besitzer der Datei noch des Verzeichnisses noch Mitglieder des Gruppeneigentümers sind. Beispielsweise könnte eine Datei mit den folgenden Berechtigungen verbunden werden: ● Besitzer: read, write (lesen, schreiben) ● Gruppenbesitzer: read (lesen) ● Other: none (keine) Diese Berechtigungen erlauben es dem Besitzer, die Datei zu lesen und zu bearbeiten, nicht aber auszuführen. Sie erlauben den Mitgliedern der Gruppe, die Eigentümerin der Datei ist, diese zu lesen, nicht aber, sie zu bearbeiten oder auszuführen. Andere Benutzer – die weder Besitzer der Datei noch Mitglieder der Gruppe sind, die Eigentümerin der Datei ist – können überhaupt nicht auf die Datei zugreifen. D 496 PHP 4 IT-Tutorial Grundlegende UNIX-Techniken Dieser Abschnitt erklärt, wie Sie mit UNIX-Befehlen gebräuchliche Operationen ausführen können. UNIX ist ein umfangreiches und ausgefeiltes System, sodass diese Informationen nicht alle Themen abdecken. Greifen Sie auf das am Anfang genannte Buch zurück, wenn Sie nähere Informationen über die UNIX-Befehle, die in diesem Abschnitt erwähnt werden, sowie über andere UNIX-Befehle suchen, die Sie für nützlich halten. UNIX kann über eine textbasierte Befehlszeilenschnittstelle oder über eine grafische Benutzerschnittstelle bedient werden. Die meisten Benutzer, die über das Internet auf ein UNIX-System zugreifen, verwenden die Befehlszeilenschnittstelle. Aus diesem Grund und weil UNIX mehrere grafische Benutzerschnittstellen mit geringfügig inkonsistenten Bedienungseigenschaften unterstützt, wird in diesem Abschnitt nur die UNIX-Befehlszeile behandelt. UNIX-Systeme unterstützen auch eine Reihe von Befehlszeilenschnittstellen, die als Shells bezeichnet werden. Die gebräuchlichsten Shells sind die BourneShell und davon abgeleitete Shells, wie beispielsweise die Bourne-again-Shell (BASH), die standardmäßig auf Linux-Systemen eingerichtet wird. Wenn Ihr UNIX-System nicht für eine Bourne-ähnliche, sondern für eine andere Shell konfiguriert ist, könnten die Befehle, die in diesem Abschnitt erklärt werden, unter Umständen nicht genau so funktionieren, wie es hier beschrieben wird. In diesem Fall sollten Sie Ihren Systemadministrator bitten, Ihr Konto so zu konfigurieren, dass es eine Bourne-ähnliche Shell, wie beispielsweise die BASHShell, verwendet. Im Allgemeinen kann ein Systemadministrator diese einfache Bitte in wenigen Sekunden erfüllen. Ein- und ausloggen Im Allgemeinen kann man sich in ein UNIX-System von der Systemkonsole aus oder mit einem Fernbedienungsprogramm wie beispielsweise Telnet oder SSH einloggen (d.h. sich bei ihm anmelden). Abgesehen von persönlichen Workstations greifen die meisten Benutzer per Fernbedienung auf UNIX-Systeme zu. Das SSH-Protokoll ist sicherer als das Telnet-Protokoll, das den Benutzernamen und die Passwörter ohne Verschlüsselung überträgt. Deshalb sollten Sie, wenn das System, auf das Sie zugreifen wollen, SSH unterstützt, SSH statt Telnet verwenden, um das Risiko zu vermindern, dass Ihr Konto kompromittiert wird. Microsoft Windows und UNIX-Systeme stellen im Allgemeinen Telnet-Clients als ihrer Standardkonfiguration zur Verfügung. Um per Telnet auf einen Remote-Host zuzugreifen, geben Sie den folgenden Befehl: telnet host Anhang D: UNIX-Grundlagen wobei host der Name oder die IP-Adresse des Hosts ist, auf den Sie zugreifen wollen. Als Antwort auf den Befehl sollte der Remote-Host Sie auffordern, Ihren Benutzernamen und Ihr Passwort einzugeben. Das Passwort wird nicht auf dem Bildschirm angezeigt, wenn Sie es eintippen, um zu verhindern, dass mögliche Zuschauer mitlesen können. UNIX-Systeme stellen im Allgemeinen einen SSHClient als Bestandteil ihrer Standardkonfiguration zur Verfügung. Je nach SSHKonfiguration des Servers müssen Sie Ihr Benutzerkonto möglicherweise für den Zugriff per SSH vorkonfigurieren. Im Allgemeinen ist jedoch ein Zugriff per SSH erlaubt. Falls dies der Fall ist, können Sie per SSH auf einen Remote-Host zugreifen, indem Sie den folgenden Befehl geben: ssh -l username host wobei username für Ihren normalen Benutzernamen und host für den Namen oder die IP-Adresse des Hosts steht, auf die Sie zugreifen wollen. Möglicherweise fordert das System Sie auf, Ihr Passwort einzugeben, das jedoch beim Eintippen nicht angezeigt wird. Microsoft-Windows-Systeme stellen in der Standardkonfiguration keinen SSH-Client zur Verfügung. Es gibt mehrere SSH-Clients für Windows, darunter das kostenlos erhältliche putty (http://www.chiark.greenend.org.uk/~sgtatham/putty/). Wenn Sie sich bei einem UNIX-System – ob per Konsole, Telnet oder SSH – anmelden, zeigt Ihnen das UNIX-System ein Login-Banner und schließlich einen Befehlsprompt (Eingabeaufforderung). Üblicherweise besteht dieser aus einer Zeichenkette, die mit einem Dollarzeichen ($) endet. Beispiel: [mccartyb@athlon mccartyb]$ Der Befehlsprompt sagt Ihnen, dass das System bereit ist, Ihre Befehle entgegenzunehmen. Das Ausloggen (Abmelden) aus einem UNIX-System ist etwas einfacher als das Einloggen. Geben Sie einfach den Befehl exit ein, und drücken Sie auf (¢). Ein Nachricht sollte bestätigen, dass Sie sich erfolgreich abgemeldet haben. Einen UNIX-Befehl eingeben Um einen UNIX-Befehl einzugeben, tippen Sie den Befehl nach dem Befehlsprompt ein und drücken dann auf (¢). Viele UNIX-Systeme verfügen über spezielle Tastenkombinationen, mit denen Sie den aktuellen Befehl editieren und ältere Befehle wiederholen können. Probieren Sie beispielsweise die Pfeiltasten aus, um deren Möglichkeiten zu erforschen. Wenn ein UNIX-Befehl nicht in eine einzelne Zeile passt, können Sie die Zeile fortsetzen, indem Sie als letztes Zeichen der Zeile einen Backslash (\) eingeben und dann auf (¢) drü- 497 D 498 PHP 4 IT-Tutorial cken. UNIX-Befehle bestehen im Allgemeinen aus drei Teilen, von den die beiden letzten optional sind: ● aus dem Befehlsnamen ● aus Befehlsoptionen, die aus Buchstaben oder Wörtern bestehen, vor denen ein Bindestrich steht (-) ● aus Argumenten, die aus Dateinamen, Verzeichnisnamen oder beliebigem Text bestehen können Das folgende Beispiel zeigt einen typischen UNIX-Befehl: chown -R mccartyb /home/mccartyb Ihr Passwort ändern Mit dem passwd-Befehl können Sie Ihr UNIX-Passwort ändern. Der Befehl benötigt keine Optionen oder Argumente. Der Befehl fragt Sie zunächst nach Ihrem aktuellen Passwort und fordert Sie dann auf, das neue Passwort zweimal einzugeben: [mccartyb@athlon mccartyb]$ passwd Changing Passwort for mccartyb (current) UNIX password: New UNIX password: Retype new UNIX password: passwd: all authentification tokens updated successfully [mccartyb@athlon mccartyb]$ Beachten Sie, dass Passwort-Informationen nicht angezeigt werden. Angemeldete Benutzer anzeigen Mit dem w-Befehl können Sie anzeigen, wer sich bei einem UNIX-Host eingeloggt hat. Der Befehl zeigt eine Reihe von Informationen über den Systemstatus und die gegenwärtig angemeldeten Benutzer an: [mccartyb@athlon mccartyb]$ w 11:46am up 21 days, 22:05, 2 users, load average: 0.00, 0.00, 0.00 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root tty1 - 17May01 7days 0.23s 0.23s -bash root pts/0 192.168.0.3 11:44am 0.00s 0.08s 0.02s w [mccartyb@athlon mccartyb]$ Anhang D: UNIX-Grundlagen 499 Beispielsweise zeigt der obige Output, dass der Systemadministrator zweimal angemeldet ist. Eine Sitzung begann am 17. Mai und die andere heute um 11:44 A.M. Prüfen, ob ein Host aktiv ist Um zu prüfen, ob ein Host aktiv ist, geben Sie den folgenden Befehl ein: ping -c 3 host wobei host für den Namen oder die IP-Adresse des Hosts steht. Wenn die Netzwerkfunktionen des Hosts aktiv sind, gibt der Befehl die Zeit zurück, die ein einzelnes Paket benötigt, um den Host zu erreichen. Er misst diese Zeitspanne dreimal und zeigt Ihnen dann eine Zusammenfassung an. Ein Beispiel: [mccartyb@athlon mccartyb]$ ping -c 3 www.osborne.com PING www.osborne.com (198.45.24.130) from 192.168.0.12 : 56(84) bytes of data. 64 bytes from 198.45.24.130: icmp_seq=0 ttl=241 time=106.986 msec 64 bytes from 198.45.24.130: icmp_seq=1 ttl=241 time=79.953 msec 64 bytes from 198.45.24.130: icmp_seq=2 ttl=241 time=79.962 msec --- www.osborne.com ping statistics --3 packets transmitted, 3 packets received, 0 % Paket loss round-trip min/avg/max/mdev = 79.953/88.967/106.986/12.741 ms [mccartyb@athlon mccartyb]$ E-Mail lesen und senden UNIX unterstützt eine Reihe von Clients für das Senden und Empfangen von EMail. Viele UNIX-Systemadministratoren installieren den beliebten E-Mail-Client pine. Um pine zu starten, geben Sie den Befehl pine ein. Der E-Mail-Client pine verfügt über eine eingebaute Dokumentation, die Ihnen helfen soll zu lernen, wie das Programm verwendet wird. Das Programm ist menügesteuert; Sie können Cursor-Navigationstasten verwenden, um einen Menüeintrag zu markieren, und dann den Eintrag auswählen, indem Sie auf (¢) drücken. Zusätzlich zum Senden und Empfangen von E-Mail-Nachrichten kann pine Newsgroup-Nachrichten lesen und veröffentlichen. Die meisten UNIX-Systeme unterstützen den weniger ausgefeilten mailBefehl, der für grundlegende E-Mail-Bedürfnisse ausreicht. Die Bedienung von mail wird auf einer so genannten Man-Page (man = manual, dt. Handbuch, also Handbuchseite) beschrieben (siehe den Abschnitt Die UNIX-Online-Dokumentation lesen). D 500 PHP 4 IT-Tutorial Das aktuelle Arbeitsverzeichnis ändern Wenn sich ein Benutzer bei einem UNIX-System einloggt, wird das HomeVerzeichnis des Benutzers zum so genannten aktuellen Arbeitsverzeichnis oder einfach zum aktuellen Verzeichnis. Das aktuelle Verzeichnis dient als Basisverzeichnis jedes relativen Pfads, der in einem UNIX-Befehl angegeben wird. Mit dem folgenden Befehl können Sie das aktuelle Arbeitsverzeichnis ändern: cd dir wobei dir für das neue aktuelle Verzeichnis steht und als absoluter oder relativer Pfad angegeben werden kann. Beispielsweise könnten Sie das aktuelle Verzeichnis in /bin ändern, indem Sie den folgenden Befehl eingeben: cd /bin Die meisten UNIX-Systeme sind so konfiguriert, dass der Name des aktuellen Verzeichnisses als Teil des Befehlsprompts angezeigt wird. Beispielsweise zeigt der Befehlsprompt [mccartyb@athlon bin]$ an, dass der Benutzer als mccartyb bei einem Host namens athlon eingeloggt ist und dass der Name des aktuellen Verzeichnisses bin lautet. Mit dem Befehl pwd können Sie das aktuelle Verzeichnis ermitteln. Der Befehl zeigt den absoluten Pfad des aktuellen Verzeichnisses an. Verzeichnisinhalte anzeigen Mit dem Befehl ls können Sie eine Liste der Dateien und Unterverzeichnisse anzeigen, die in dem aktuellen Verzeichnis enthalten sind. Der Befehl zeigt auf jeder Zeile mehrere Dateien oder Verzeichnisse an, beispielsweise so: index.html php php.tgz Anhang D: UNIX-Grundlagen 501 Bei einigen UNIX-Systemen werden die Namen von Dateien und Verzeichnissen in verschiedenen Farben angezeigt. Wenn Sie nicht den Inhalt des aktuellen, sondern eines anderen Verzeichnisses sehen wollen, geben Sie den Befehl ls path ein, wobei path den relativen oder absoluten Pfad des Verzeichnisses angibt. Der ls-Befehl unterstützt eine Reihe von Optionen, mit denen Sie zusätzliche Informationen anzeigen können. Das gebräuchlichste Flag ist -l (minus eins), das dazu führt, dass ls pro Zeile nur eine Datei oder ein Verzeichnis anzeigt: [mccartyb@athlon mccartyb]# ls -l /home/mccartyb/ public_html/ total 21 -rw-r--r-- 1 mccartyb mccartyb 80 May 24 16:01 index.html drwxrwxr-x 18 mccartyb mccartyb 1024 Jun 2 09:54 php -rwxr-xr-x 1 mccartyb mccartyb 17915 May 24 15:55 php.tgz Die erste Zeile zeigt die Anzahl der Verzeichnisblöcke (I-Nodes) an, die mit dem Verzeichnis verbunden sind; diese Information ist im Allgemeinen nicht wichtig. Die folgenden Zeilen beschreiben jeweils eine Datei oder ein Verzeichnis. Wenn das erste Zeichen einer Zeile ein Bindestrich (-) ist, beschreibt die Zeile eine Datei; wenn das erste Zeichen der Buchstabe d ist, beschreibt die Zeile ein Verzeichnis. Die folgenden neun Zeichen geben die Berechtigungen an, die mit der Datei bzw. dem Verzeichnis verbunden sind. Die ersten drei Zeichen dieser Gruppe geben die Berechtigungen des Eigentümers an, die nächsten drei Zeichen geben die Berechtigungen der Gruppenmitglieder an, und die letzten drei Zeichen geben die Berechtigungen der anderen Benutzer an. Die Berechtigungen werden durch die folgenden Codes angezeigt: Code Berechtigung r read (lesen) w write (schreiben) x execute (ausführen) Danach werden die folgenden Eigenschaften in der hier gezeigten Reihenfolge angegeben: ● die Anzahl der Dateisystem-Links, die mit der Datei oder dem Verzeichnis verbunden sind, was im Allgemeinen uninteressant ist ● der Name des Eigentümers der Datei oder des Verzeichnisses D 502 PHP 4 IT-Tutorial ● der Name des Gruppeneigentümers der Datei oder des Verzeichnisses ● die Größe der Datei oder des Verzeichnisses (in Bytes) ● der Zeitpunkt (Datum und Zeit), zu dem die Datei oder das Verzeichnis zuletzt geändert wurde ● der Name der Datei oder des Verzeichnisses Dateiinhalte und Befehlsausgaben Um die Inhalte einer Textdatei anzuzeigen, geben Sie den Befehl more path ein, wobei path der Pfad ist, der mit der Datei verbunden ist. Mit dem moreBefehl können Sie die Datei seitenweise anzeigen. Mit der (____) können Sie jeweils um eine Seite vorwärts blättern. Mit (Q) können Sie das Programm beenden. Wenn Sie versuchen, den Inhalt einer binären Datei mit dem more-Befehl anzuzeigen, wird das Ergebnis unverständlich sein. Im schlimmsten Fall kann der Inhalt der Datei die Einstellungen Ihres Terminals zerstören und Sie zwingen, sich auszuloggen und dann wieder einzuloggen, damit Sie Ihre Arbeit fortsetzen können. Mit dem more-Befehl können Sie auch den Output eines Befehls anzeigen. Dies ist hilfreich, wenn ein Befehl einen umfangreichen Output erzeugt. Geben Sie zu diesem Zweck den Befehl command | more ein, wobei command der Befehl (einschließlich seiner zugehörigen Optionen und Argumente) ist, der den Output erzeugt. Eine Datei editieren UNIX unterstützt eine Reihe von Texteditoren, wie beispielsweise vi und emacs. Anfänger sind jedoch mit dem Editor pico gut bedient, einem Verwandten des EMail-Clients pine, der von UNIX-Systemadministratoren häufig installiert wird. Wie pine ist pico menügesteuert und einfach zu bedienen. Um pico zu starten, geben Sie den folgenden Befehl ein: pico Anhang D: UNIX-Grundlagen 503 Um eine vorhandene Datei zu bearbeiten, starten Sie pico, indem Sie zugleich den Namen der Datei angeben: pico file wobei file der Pfad der Datei ist, die Sie bearbeiten wollen. Der pico-Editor verfügt über eine eingebaute Dokumentation, die Ihnen helfen soll zu lernen, wie das Programm verwendet wird. Mit den Pfeiltasten können Sie einen Menüeintrag markieren und dann den Eintrag auswählen, indem Sie auf (¢) drücken. Ein Verzeichnis erstellen Um ein Verzeichnis zu erstellen, geben Sie den Befehl mkdir dir ein, wobei dir der Pfad ist, der mit dem Verzeichnis verbunden ist. Eine Datei löschen Um eine Datei zu löschen, geben Sie den Befehl rm file ein, wobei file der Pfad ist, der mit der Datei verbunden ist. Achtung Weil UNIX im Gegensatz zu Microsoft Windows nicht über einen Papierkorb verfügt, sind die Inhalte der gelöschten Dateien im Allgemeinen nicht wiederherstellbar. Achten Sie darauf, dass Sie nur Dateien löschen, die nicht mehr benötigt werden. Ein Verzeichnis löschen Wenn ein Verzeichnis leer ist, d.h. wenn es keine Dateien oder Unterverzeichnisse enthält, können Sie es mit dem Befehl rmdir dir D 504 PHP 4 IT-Tutorial löschen, wobei dir der Pfad ist, der mit dem Verzeichnis verbunden ist. Falls das Verzeichnis nicht leer ist, können Sie das Verzeichnis und seine Inhalte mit dem Befehl rm -rf dir löschen, wobei dir der Pfad ist, der mit dem Verzeichnis verbunden ist. Eine Datei oder ein Verzeichnis kopieren Um eine Datei zu kopieren, geben Sie den Befehl cp file copy ein, wobei file der Pfad ist, der mit der Datei verbunden ist, und copy der Pfad ist, der mit der Kopie verbunden ist. Um ein Verzeichnis und seine Inhalte zu kopieren, geben Sie den Befehl ein cp -av dir copy ein, wobei dir der Pfad ist, der mit dem Verzeichnis verbunden ist, und copy der Pfad ist, der mit der Kopie verbunden ist. Eine Datei oder ein Verzeichnis umbenennen Um eine Datei oder ein Verzeichnis umzubenennen, geben Sie den Befehl mv old new ein, wobei old der ursprüngliche Pfad der Datei oder des Verzeichnisses und new der neue Pfad ist. Shell-Metazeichen und Name-Globbing Indem Sie in Befehle spezielle Zeichen – so genannte Metazeichen – einfügen, können Sie Befehle auf mehrere Dateien auf einmal anwenden. Diese UNIXFunktion, die als Name-Globbing bezeichnet wird, ähnelt den Platzhalterzeichen (Wildcards), die in MS-DOS verwendet werden, ist aber beträchtlich leistungsfähiger. Das Metazeichen ? steht für genau ein Zeichen, und das Metazeichen * steht für eine beliebige Anzahl von Zeichen (null oder mehr). In UNIX gibt es noch weitere Metazeichen, die jedoch für die Anforderungen eines Anfängers unwichtig sind. Anhang D: UNIX-Grundlagen 505 Der Befehl rm a?c löscht Dateien in dem aktuellen Verzeichnis, deren Dateiname aus drei Buchstaben besteht, wobei dieser mit einem a beginnt und mit einem c endet. Wenn es beispielsweise in dem aktuellen Verzeichnis die Dateien aac, abc, acc oder adc gibt, werden sie durch diesen Befehl gelöscht. Der Befehl rm /home/mess/a* löscht alle Dateien im Verzeichnis /home/mess, deren Namen mit einem a beginnen. Der Befehl rm -rf * löscht alle Dateien und Verzeichnisse in dem aktuellen Verzeichnis; verwenden Sie ihn und ähnliche Befehle sehr vorsichtig. Sie können das Name-Globbing vermeiden, indem Sie ein Argument in ein Paar gleichartiger Anführungszeichen – entweder einfach oder doppelt – einschließen. Beispielsweise löscht der Befehl rm "a?c" die Datei, deren Name drei Buchstaben lang ist und aus den Zeichen a, ? und c besteht. Natürlich ist es nicht ratsam, derartige Dateinamen zu verwenden, insbesondere wenn Sie unter mehreren Betriebssystemen arbeiten. Die UNIX-Online-Dokumentation lesen UNIX verfügt über eine einfache Online-Hilfsfunktion, die die Operationen, Optionen und Argumente der UNIX-Befehle beschreibt. Wenn Sie beispielsweise mehr über den rm-Befehl erfahren wollen, geben Sie den folgenden Befehl ein: man rm Die Informationen, die von dem man-Befehl zur Verfügung gestellt werden, werden als Man-Page bezeichnet (Kurzform für Manual-Page, dt. Handbuchseite). Wenn Sie mehr über den man-Befehl erfahren wollen, geben Sie den folgenden Befehl ein: man man D 506 PHP 4 IT-Tutorial Man-Pages sind nach nummerierten Abschnitten geordnet. Abschnitt 1 enthält die Befehle, die üblicherweise von normalen Benutzern verwendet werden. Mehrere Abschnitte können Informationen zu einem bestimmten Thema enthalten. Um die Man-Page aus einem bestimmten Abschnitt anzuzeigen, geben Sie den Befehl man n topic ein, wobei n die Nummer des Abschnitts und topic der Name des Befehls oder des Themas ist, an dem Sie interessiert sind. Die Verwendung des Festplattenplatzes anzeigen Um die Verwendung des Festplattenplatzes auf den Laufwerken des Systems anzuzeigen, geben Sie den Befehl df -m ein. Der Output des Befehls ähnelt dem folgenden Beispiel und zeigt den benutzten und den verfügbaren Speicherplatz in MB, nach Dateisystemen geordnet: Filesystem 1M-blocks Used Available /dev/hda9 972 497 424 /dev/hda1 996 529 467 /dev/hda5 38 5 31 /dev/hda6 1935 1456 399 /dev/hda7 3874 3537 176 /dev/hda8 486 58 403 /dev/hda11 10066 7558 1985 Use% Mounted on 54 % / 54 % /dos 14 % /boot 79 % /usr 96 % /home 13 % /var 80 % /space Um den Speicherplatz anzuzeigen, der von bestimmten Verzeichnissen und Dateien belegt wird, geben Sie den Befehl du -m path ein, wobei path der Name der Datei oder des Verzeichnisses ist, an der bzw. dem Sie interessiert sind. Wenn Sie ein Verzeichnis angeben, zeigt der Befehl den Speicherplatz an, der von jedem Unterverzeichnis des Verzeichnisses belegt wird. Anhang D: UNIX-Grundlagen 507 Den Besitzer einer Datei festlegen Auf einigen UNIX-Systemen kann der Besitzer einer Datei oder eines Verzeichnisses die Besitzerschaft an der Datei oder an dem Verzeichnis auf einen anderen Benutzer übertragen. Geben Sie zu diesem Zweck den Befehl chown owner path ein, wobei path für den Pfad steht, der mit der Datei oder dem Verzeichnis verbunden ist, und owner für den Benutzernamen oder die ID des neuen Eigentümers steht. Um den Gruppenbesitzer einer Datei oder eines Verzeichnisses festzulegen, deren bzw. dessen Besitzer Sie sind, geben Sie den folgenden Befehl chgrp group path ein, wobei path den Pfad angibt, der mit der Datei oder dem Verzeichnis verbunden ist, und group den Benutzergruppennamen oder die ID des neuen Gruppenbesitzers symbolisiert. Dateiberechtigungen setzen Um die Berechtigungen zu ändern, die mit einer Datei oder einem Verzeichnis verbunden sind, deren bzw. dessen Besitzer Sie sind, geben Sie den Befehl chmod xxx path ein, wobei path den Pfad angibt, der mit der Datei oder dem Verzeichnis verbunden ist, und xxx aus drei Oktalziffern besteht, die die gewünschten Berechtigungen festlegen. Die erste Ziffer legt die Berechtigungen des Eigentümers, die zweite die Berechtigungen des Gruppeneigentümers und die dritte die Berechtigungen der anderen Benutzer fest. Jede Ziffer hat einen der folgenden Werte, die den zugeordneten Berechtigungen entsprechen: Ziffer Berechtigungen 0 --- 1 --x 2 -w- 3 -wx 4 r-- 5 r-x D 508 PHP 4 IT-Tutorial Ziffer Berechtigungen 6 rw- 7 rwx Beispielsweise gibt der Befehl chmod 640 myfile dem Besitzer Read- und Write-Zugriff, Gruppenmitgliedern Read-Zugriff und anderen Benutzern keinen Zugriff auf die Datei namens myfile. Eine zweite Form des chmod-Befehls erleichtert das Gewähren und Widerrufen von Berechtigungen, die mit einer Datei verbunden sind. Näheres erfahren Sie auf der einschlägigen Man-Page. Eine Datei suchen Um den Speicherort einer Datei zu ermitteln, deren Namen Sie kennen, geben Sie den Befehl find / -name findme ein, wobei findme der Name der Datei ist. Die Suche beginnt im Root-Verzeichnis. Wenn die Suche in einem anderen Verzeichnis beginnen soll, geben Sie anstelle des Schrägstrichs / den gewünschten Pfad ein. Wenn Sie nur einen Teil des Dateinamens kennen, können Sie Metazeichen verwenden, um die unbekannten Teile anzugeben; jedoch müssen Sie das resultierende Muster in Anführungszeichen setzen, sodass kein Datei-Globbing erfolgt und das Muster unverändert an den find-Befehl übergeben wird. Beispielsweise sucht der folgende Befehl eine Datei, die sich irgendwo unter dem /home-Verzeichnis befindet und die das Wort red im Namen hat: find /home -name "*red*" Einige UNIX-Systeme unterstützen den locate-Befehl, der mit einer Datenbank arbeitet, um die Ergebnisse schneller als der find-Befehl zur Verfügung zu stellen; jedoch sind die berichteten Ergebnisse nur so aktuell wie die Datenbank, die mit dem locate-Befehl verbunden ist und die üblicherweise täglich aktualisiert wird. Um eine Datei mit locate zu suchen, geben Sie den Befehl locate findme ein, wobei findme der Name der Datei ist. Anhang D: UNIX-Grundlagen 509 Eine Datei suchen, die einen bestimmten Text enthält Um eine Datei zu suchen, die einen bestimmten Text enthält, geben Sie den Befehl grep -i text fileset ein, wobei text den gesuchten Text angibt und fileset aus einem oder mehreren Pfaden besteht, die die zu durchsuchenden Dateien angeben. Beispielsweise durchsucht der Befehl grep -i red file1 file2 die Dateien file1 und file2 nach dem Text red, der in Großbuchstaben, Kleinbuchstaben oder in gemischter Schreibweise auftreten kann. Eine gebräuchliche Form des Befehls lautet: grep -i text * Mit diesem Befehl werden die Dateien in dem aktuellen Verzeichnis nach dem Text text durchsucht. Wenn text Metazeichen enthält oder aus mehreren Wörtern besteht, muss er in Anführungszeichen eingeschlossen werden. Der grep-Befehl verfügt über viele nützliche Optionen; Einzelheiten erfahren Sie auf der zugehörigen ManPage. Den Typ einer Datei ermitteln Um den Typ einer Datei zu ermitteln, geben Sie den Befehl file path ein, wobei path für den der Pfad der Datei steht. Die file-Befehl untersucht nicht nur die Erweiterung des Dateinamens, falls vorhanden; stattdessen arbeitet er mit einer ausgefeilten Heuristik, um den Dateityp zu bestimmen. Textdateien vergleichen Um zwei Textdateien zu vergleichen, geben Sie den Befehl diff -ignore-all-space path1 path2 D 510 PHP 4 IT-Tutorial ein, wobei path1 und path2 die Pfade der Textdateien sind, die Sie vergleichen wollen. Der Befehl zeigt die Änderungen an, die erforderlich sind, um die eine Datei in die andere zu überführen. Dieser Befehl ist insbesondere nützlich, um Versionen von HTML-Dateien und PHP-Skripts zu vergleichen. Mit komprimierten Dateien arbeiten UNIX-Dateien werden üblicherweise mit einer von zwei Methoden komprimiert: mit der zip-Methode (die UNIX mit der Microsoft-Windows-Welt gemeinsam hat) oder mit der GNU-zip-Methode. Zip-Dateien können Dateien und Verzeichnisse enthalten, während eine GNU-zip-Datei nur eine einzige Datei enthalten kann. Um eine zip-Datei zu entkomprimieren, geben Sie den Befehl unzip path ein, wobei path der Pfad der komprimierten Datei ist. Um eine Datei oder ein Verzeichnis mit der zip-Methode zu komprimieren, geben Sie den Befehl zip zipfile pathset ein, wobei zipfile den Pfad der zip-Datei angibt, die erstellt werden soll, und pathset eine oder mehrere Dateien oder Verzeichnisse angibt, die in die zipDatei eingefügt werden sollen. Um beispielsweise eine zip-Datei zu erstellen, die die Datei test und den Inhalt des Verzeichnisses folder enthält, können Sie den folgenden Befehl eingeben: zip result.zip test folder Per Konvention haben die Namen von zip-Dateien die Namenserweiterung .zip. Um eine GNU-zip-Datei zu entkomprimieren, geben Sie den Befehl gunzip path ein, wobei path der Pfad der komprimierten Datei ist. Um eine Datei mit der GNU-zip-Methode zu komprimieren, geben Sie den Befehl gzip pathset ein, wobei pathset eine oder mehrere Dateien angibt, die komprimiert werden soll bzw. sollen. GNU-zip erstellt für jede angegebene Datei eine neue Datei, die denselben Namen wie die ursprüngliche Datei, aber die Namenserweiterung .gz Anhang D: UNIX-Grundlagen 511 hat. Die ursprüngliche Datei wird gelöscht. Um beispielsweise eine GNU-zipDatei mit der Datei test zu erstellen, können Sie den folgenden Befehl eingeben: gzip test Die resultierende Datei bekommt den Namen test.gz. Mit Tarballs arbeiten Um mehrere UNIX-Dateien und Verzeichnisse zu einer einzigen Datei zusammenzufassen, wird häufiger der tar-Befehl als der zip-Befehl verwendet. Die Datei, die das Ergebnis des tar-Befehls ist, wird als tar-Datei oder Tarball bezeichnet. Um eine tar-Datei zu erstellen, geben Sie den Befehl tar zcvf tarfile.tgz pathset ein, wobei tarfile.tgz den Namen der tar-Datei angibt, die erstellt werden soll, und pathset die Dateien oder Verzeichnisse enthält, die in die tar-Datei eingefügt werden sollen. Einige UNIX-Benutzer verwenden für eine tar-Datei lieber die Dateierweiterung .tar.gz. Die z-Option legt fest, dass automatisch das GNU-zip-Programm verwendet werden soll. Wenn das z in zcvf weggelassen wird, wird eine unkomprimierte tar-Datei mit der Erweiterung .tar erstellt. Wenn Sie die Daten beim Erstellen einer tar-Datei nicht komprimieren, können Sie die tar-Datei danach mit dem GNU-zip-Programm komprimieren. Um eine komprimierte tar-Datei zu entpacken, geben Sie den Befehl tar zxvf tarfile.tgz ein, wobei tarfile.tgz für den Namen der tar-Datei steht. Um eine unkomprimierte tar-Datei zu entpacken, lassen Sie das z weg: tar xvf tarfile.tar Der tar-Befehl verfügt über zahlreiche andere nützliche Optionen. Näheres erfahren Sie auf der zugehörigen Man-Page. D 512 PHP 4 IT-Tutorial Dateien von und auf Remote-Hosts übertragen Mit dem ftp-Befehl können Sie Dateien von und auf Remote-Hosts übertragen (siehe Kapitel 1). Dieses Verfahren hat jedoch einen Nachteil: FTP sendet Ihren Benutzernamen und Ihr Passwort in unverschlüsselter Form über das Netzwerk. Wenn sowohl der lokale Host als auch der Remote-Host SSH unterstützt, können Sie das scp-Programm verwenden, das die Informationen verschlüsselt, die über das Netzwerk übertragen werden. Um eine Datei per SSH auf ein RemoteSystem zu übertragen, geben Sie den Befehl scp file user@host:path ein. file ist der Pfad der Datei, die übertragen werden soll, user ist der Name des Benutzerkontos auf dem Remote-Host, host ist der Host-Name oder die IPAdresse des Remote-Hosts und path legt den Zielpfad für die übertragene Datei fest. Um eine Datei per SSH von einem Remote-System zu übertragen, geben Sie den Befehl scp user@host:file path ein. user ist der Name des Benutzerkontos auf dem Remote-Host, host ist der Host-Name oder die IP-Adresse des Remote-Hosts, file ist der Pfad der Datei, die übertragen werden soll, und path legt den Zielpfad für die übertragene Datei fest. Der scp-Befehl verfügt über zahlreiche andere nützliche Optionen. Näheres erfahren Sie auf der zugehörigen Man-Page. Anhang E Fluchtzeichen (Escapes) 514 PHP 4 IT-Tutorial Fluchtzeichen Wird ersetzt durch \n Zeilenvorschub (ASCII 0x0A) \r Wagenrücklauf (ASCII 0x0D) \t Horizontaler Tabulator (ASCII 0x09) \\ Backslash \$ Dollarzeichen \" Doppeltes Anführungszeichen \nnn Das Zeichen, dessen ASCII-Wert dem Oktalwert nnn entspricht \xnn Das Zeichen, dessen ASCII-Wert dem Hexadezimalwert nn entspricht Anhang F ASCII 516 PHP 4 IT-Tutorial Dezimal 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 Oktal 0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20 21 22 23 24 25 26 27 30 31 32 33 34 35 36 37 40 41 42 43 44 45 46 47 50 51 52 Hexadezimal 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a Bedeutung Null Start of Heading Start of text Ende of text Ende of transmit Enquiry Acknowledge Audible Bell Backspace Horizontal tab Line feed Vertical tab Form feed Carriage return Shift out Shift in Data link escape Device control 1 Device control 2 Device control 3 Device control 4 Negative acknowledge Synchronous idle Ende transmit block Cancel Ende of medium Substitution Escape File separator Group separator Record separator Unit separator Space ! „ # $ % & ‘ ( ) * Abkürzung NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US Anhang F: ASCII Dezimal 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 Oktal 53 54 55 56 57 60 61 62 63 64 65 66 67 70 71 72 73 74 75 76 77 100 101 102 103 104 105 106 107 110 111 112 113 114 115 116 117 120 121 122 123 124 125 Hexadezimal 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 Bedeutung + , . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U 517 Abkürzung F 518 PHP 4 IT-Tutorial Dezimal 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 Oktal 126 127 130 131 132 133 134 135 136 137 140 141 142 143 144 145 146 147 150 151 152 153 154 155 156 157 160 161 162 163 164 165 166 167 170 171 172 173 174 175 176 177 Hexadezimal 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f Bedeutung V W X Y Z [ \ ] ^ _ ‘ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ Delete Abkürzung Anhang G PHP-Operatoren 520 PHP 4 IT-Tutorial Vorrang Assoziativität Operatoren Bedeutung 20 keine new Objektkonstruktor 19 rechts [] Subskript 18 rechts ! Logisches NOT (Negation) ~ Bitweises NOT ++ Inkrement -- Dekrement (int) Cast nach Integer (double) Cast nach Double (string) Cast nach String 17 16 links links (array) Cast nach Array (object) Cast nach Objekt @ Fehlerkontrolle * Multiplikation / Division % Modulus + Addition - Subtraktion . Stringverkettung 15 links << bitweiser Left-Shift >> bitweiser Right-Shift 14 keine < kleiner als 13 keine <= kleiner als oder gleich > größer als >= größer als oder gleich == gleich != nicht gleich === identisch !== nicht identisch 12 links & bitweises AND (Und) 11 links ^ bitweises XOR (Xor) 10 links | bitweises OR (Oder) 9 links && logisches AND (Und) 8 links || logisches OR (Oder) 7 links ?: Conditional (Bedingte Zuweisung) Anhang G: PHP-Operatoren Vorrang Assoziativität Operatoren Bedeutung 6 links Zuweisung = += Additionszuweisung -= Subtraktionszuweisung *= Multiplikationszuweisung /= Divisionszuweisung .= Verkettungszuweisung %= Moduluszuweisung &= bitweise AND-Zuweisung |= bitweise OR-Zuweisung ^= bitweise XOR-Zuweisung ~= bitweise NOT-Zuweisung <<= bitweise Left-Shift-Zuweisung >>= bitweise Right-Shift-Zuweisung 5 rechts print Print (Druck) 4 links and logisches AND 3 links xor logisches XOR 2 links or logisches OR 1 links , Komma 521 G Anhang H Sicherheit 524 PHP 4 IT-Tutorial Sicherheit ist ein fortgeschrittenes Thema, das für einen angehenden Programmierer nicht geeignet ist. Jedoch wollen selbst angehende PHP-Programmierer Anwendungen erstellen und in der Praxis einsetzen. Leider ist es eine unglückliche Tatsache des Netzwerbetriebs, dass Anwendungen, die über ein Netzwerk zur Verfügung stehen, das Ziel von Angriffen sind, die sowohl von böswilligen als auch von bloß neugierigen Angreifern ausgeführt werden. Dieser Anhang soll Sie auf einige sicherheitsrelevante Themen und Ressourcen hinweisen, die sonst in diesem Buch nicht dargestellt werden. Wenn Sie die möglichen Sicherheitsschwachstellen kennen, wollen Sie möglicherweise mehr über diese Probleme lernen und erfahren, wie Sie sie vermeiden können. Wenn Sie sich dafür interessieren, Internet-Anwendungen einzusetzen, die wichtige Daten – wie beispielsweise geschäftliche Transaktionen – verarbeiten, sollten Sie Ihr Studium von PHP und der Sicherheit vertiefen oder einen Sicherheitsexperten zur Rate ziehen. Bedrohungen und Risiken Ein Grundprinzip der Softwaresicherheit lautet, dass kein System vollkommen sicher ist. Folglich ist die Sicherheit kein Alles-oder-nichts-Thema, sondern Sicherheitsvorschriften und -maßnahmen müssen aufgrund folgender Aspekte entwickelt werden: ● aufgrund der Häufigkeit und Art der Sicherheitsbedrohungen ● aufgrund der möglichen Folgen einer Sicherheitsverletzung Anders ausgedrückt: Sicherheitsmaßnahmen haben eher mit Abschreckung als mit Vorbeugung zu tun. Wenn ein zielstrebiger Hacker über genügend Zeit und Erfahrung verfügt, kann er mit ziemlicher Sicherheit jedes System kompromittieren. Das Ziel von Sicherheitsmaßnahmen besteht darin, die Latte für die Fähigkeiten, die erforderlich sind, um ein System zu kompromittieren, so hoch zu legen, dass ein Möchtegern-Hacker mehr Zeit aufwenden müsste, als es im Hinblick auf den zu erwartenden Gewinn aus einem erfolgreichen Einbruch vernünftig wäre. Hacker können ganz unterschiedliche Motive haben: die Erwartung eines finanziellen Gewinns, den Wunsch nach Rache, einfache Neugier oder eine Reihe anderer Gründe. Einige Hacker verfügen über beträchtliche Programmierfähigkeiten. Andere, die häufig als Skript-Kiddies bezeichnet werden, können nur die Werkzeuge und Prozeduren anwenden, die von anderen entwickelt wurden. Jedoch kann ein entschlossener Hacker, der über hinreichende Fähigkeiten verfügt, ein gefährlicher Gegner sein. Anhang H: Sicherheit 525 Eine andere Möglichkeit, um Sicherheitsbedrohungen zu charakterisieren, besteht darin, sie nach den Auswirkungen zu klassifizieren, die sie auf das Zielsystem haben. Man spricht dann von dem so genannten Bedrohungstyp. Netzwerkbasierte Software-Anwendungen sind unter anderem den folgenden Bedrohungstypen ausgesetzt: ● Offenlegung vertraulicher Daten ● Änderung oder Zerstörung von Daten ● Verweigerung von Diensten (Denial of service) ● Nichtanerkennung von Transaktionen Die Offenlegung vertraulicher Daten ist eine besonders häufige Bedrohung. Sehr häufig vorkommende Varianten dieses Bedrohungstyps sind die Veröffentlichung von privaten E-Mail-Nachrichten und von Kreditkarteninformationen. Der Schutz vor dieser Bedrohung umfasst eine gute Programmierung und entsprechende Maßnahmen der Systemverwaltung. Die Änderung oder Zerstörung von Daten ist eine weitere häufige Bedrohung. Sie erfolgt häufig in der Form, dass eine Website verunstaltet wird. Computerviren, die Daten ändern, bilden eine andere häufige Form des Angriffs. Auch hier besteht der Schutz in einer guten Programmierung und in sinnvollen Maßnahmen der Systemverwaltung. Die Verweigerung von Diensten (Denial of service = DOS) ist ein weiterer Bedrohungstyp, der sehr populär geworden ist. Während die Offenlegung vertraulicher Daten und die Änderung oder Zerstörung von Daten häufig die Folge einer Sicherheitsverletzung sind, die durch einen Fehler oder ein Versehen eines Programmierers oder eines Systemadministrators ermöglicht wurde, sind bei DOS-Angriffen keine Schwachstellen dieser Art erforderlich. Heutzutage sind die meisten Systeme durch DOS-Angriffe gefährdet. Dabei wird ein Host so mit unerlaubten Dienstanforderungen bombardiert oder überflutet, dass er nicht mehr auf ernst gemeinte Anforderungen reagieren kann. Gegenwärtig wird erforscht, wie derartige Angriffe vereitelt werden können. Die Nichtanerkennung von Transaktionen ist eine Sicherheitsbedrohung, die beim E-Commerce eine Rolle spielt. Dabei bestreitet eine der Parteien, die an einer Transaktion beteiligt waren, später, dass sie die Transaktion autorisiert hat. Zum Schutz vor dieser Bedrohung müssen Anwendungen entworfen werden, die unter anderem auch kryptographische Techniken verwenden, um die Identität der Parteien zu authentifizieren, die an einer Transaktion beteiligt sind. Sicherheitsverletzungen können sehr unterschiedliche Folgen haben. Beispielsweise können die Folgen, die eine Offenlegung vertraulicher Daten nach sich zieht, von einer leichten Verlegenheit (beispielsweise im Fall der Veröffentlichung einer privaten E-Mail-Nachricht mit einer nicht gesellschaftsfähigen Aus- H 526 PHP 4 IT-Tutorial drucksweise) bis zu einer katastrophalen Geschäfts- oder Rufschädigung reichen (beispielsweise im Fall der Veröffentlichung geheimer Geschäftspläne. Gegenmaßnahmen Dieser Abschnitt erklärt einige Gegenmaßnahmen, die üblicherweise eingesetzt werden, um das Risiko einer Sicherheitsverletzung zu verringern. Diese Beschreibung ist weder vollständig noch umfassend. Sie soll Sie auf die wichtigsten Möglichkeiten hinweisen, kann aber nicht garantieren, dass die empfohlenen Maßnahmen eine hundertprozentige Sicherheit gewährleisten. Der folgende Abschnitt weist Sie auf mehrere umfassendere Quellen hin. Authentifizierung und Autorisierung von Benutzern Wenn eine Anwendung Funktionen enthält, die nicht für den allgemeinen Gebrauch bestimmt sind, sollte die Anwendung Mechanismen bieten, um die Benutzer des Systems zu identifizieren, zu authentifizieren und zu autorisieren. Einige Anfänger schreiben Anwendungen, die sich darauf verlassen, dass die Benutzer sich selbst identifizieren. Da ein böswilliger Benutzer wahrscheinlich nicht seine richtige Identität angibt, ist eine bloße Identifikation unzuverlässig. Bei der Authentifizierung wird die Identität eines Benutzers überprüft. Das gebräuchlichste Mittel für diesen Zweck ist die Verwendung eines privaten Passworts. Es gibt jedoch noch andere Methoden – beispielsweise das Challengeund-Response-Verfahren, bei dem dem Benutzer eine Frage aus einer vorgegebenen Liste von Fragen gestellt wird. Bei der Autorisierung werden bestimmte Berechtigungen mit der Identität eines Benutzers verknüpft. Beispielsweise könnten einige Benutzer das Recht haben, die Gehaltsdaten in einer Personaldatenanwendung zu sehen, aber nur besonders berechtigte Benutzer könnten das Recht haben, die Gehaltsdaten zu ändern. Das Speichern der Authentifizierungs- und Autorisierungsdaten in einer Datenbank ermöglicht es bestimmten Benutzern, diese Informationen zu warten und damit dafür zu sorgen, die Daten auf dem neuesten Stand zu halten. Sicherheitsverletzungen können auftreten, wenn die Berechtigungen von solchen Benutzern nicht widerrufen werden, die nicht mehr mit einem Unternehmen oder Projekt verbunden sind. Passwortinformationen sollten in verschlüsselter Form gespeichert werden, sodass nicht einmal Systemadministratoren Identitäten fälschen können. Anhang H: Sicherheit 527 Benutzereingaben misstrauen In Kapitel 14 wurde erklärt, dass Sie den Daten, die vom Benutzer stammen, misstrauen sollten. Die Angabe von Daten, die Metazeichen enthalten, ist ein gebräuchliches Verfahren, um die Sicherheit von Anwendungen zu kompromittieren. Wenn Sie netzwerkbasierte PHP-Anwendungen schreiben, sollten Sie die addslashes()-Funktion und andere Mittel einsetzen, um sicherzustellen, dass Benutzereingaben keine ungeplante Verarbeitung auslösen. Kryptographische Maßnahmen einsetzen Dieses Buch beschreibt nicht, wie kryptographische Funktionen in PHP unterstützt werden. Dennoch ist die Anwendung solcher Funktionen wichtig, um die Sicherheit zu gewährleisten. Eine gebräuchliche Sicherheitsmaßnahme besteht darin, einen so genannten sicheren Webserver einzurichten, der Daten mit Client-Webbrowsern über HTTPS austauscht, eine verschlüsselte Variante des gebräuchlichen HTTP-Protokolls. E-Commerce-Transaktionen werden üblicherweise mit Hilfe des HTTPS-Protokolls abgewickelt. Andere verfügbare kryptographische Verfahren arbeiten mit privaten und öffentlichen Schlüsseln, mit denen Benutzer und Nachrichten authentifiziert und Informationen sicher ausgetauscht werden können. Zu den speziellen Verfahren, die sich als nützlich erweisen könnten, zählen: ● MD5-Digests ● RSA-Verschlüsselung ● PGP- und GNU-PG-Verschlüsselung Server korrekt konfigurieren Aufgrund der Art und Weise, wie PHP mit einem Webserver zusammenarbeitet, kann eine ungeeignete Konfiguration des Webservers die PHP-Sicherheit nachträglich beeinflussen. Wenn Sie Systemadministrator eines Hosts sind, der Webdienste zur Verfügung stellt, sollten Sie mit den Webserver-Optionen vertraut sein, die Einfluss auf die Sicherheit haben. Außerdem sollten Sie Korrekturen und/oder Ergänzungen des Betriebssystems, des Webservers und von PHP beschaffen und installieren, die die Sicherheit des Systems und des Netzwerks beeinflussen. Ein wichtiger Aspekt der Webserver-Sicherheit besteht darin, nicht autorisierte Zugriffe auf Quelldateien und Datendateien zu verhindern. Sie sollten den Webserver so konfigurieren, dass Webbrowser nur auf ausgewählte Verzeichnisse zugreifen können, und sicherstellen, dass Quell- und Datendateien nicht in diesen, sondern in anderen Verzeichnissen gespeichert sind. H 528 PHP 4 IT-Tutorial Datenbanken sichern Die Benutzernamen und Passwörter, die zur Herstellung von Datenbankverbindungen verwendet werden, werden üblicherweise direkt in PHP-Skripts eingefügt. Wenn ein Hacker einen Benutzernamen und das zugehörige Passwort herausfindet, kann er eine Verbindung zu der Datenbank herstellen und jede gewünschte autorisierte Operation ausführen. Beispielsweise könnte ein Hacker alle Datensätze aus einer oder mehreren Datenbanktabellen löschen. Eine Möglichkeit, um Benutzernamen und Passwörter zu schützen, besteht darin, sie in Dateien zu speichern, die über include- oder require-Befehle abgerufen werden. Solche Dateien müssen nicht – und sollten nicht – in Verzeichnissen gespeichert sein, die über den Webserver zugänglich sind. Indem Sie die Dateien in einem Verzeichnis speichern, das vom Web aus nicht zugänglich ist, machen Sie es einem Hacker schwerer, die Inhalte dieser Dateien zu entdecken. Ressourcen Wenn Sie eine Einführung in die Netzwerksicherheit suchen, die für Anfänger geeignet ist, sollten Sie IT-Crackdown von Othmar Kyas und Markus a Campo (MITP-Verlag) oder Network Security: A Beginner's Guide von Eric Maiwald (Osborne McGraw-Hill, 2001) lesen. Wenn Sie mehr darüber lernen wollen, wie Sie Unix-Systeme gegen lokale und Fernbedrohungen sichern können, sollten Sie UNIX System Security Tools von Seth Ross (Osborne McGraw-Hill, 1999) lesen. Nähere Informationen über die Konfiguration von Apache finden Sie in Apache Webserver von Lars Eilebrecht (MITP-Verlag). Anhang I PHP-Funktionen 530 PHP 4 IT-Tutorial Dieser Anhang beschreibt die hauptsächlichen PHP-Funktionen einschließlich der Funktionen, die in diesem Buch verwendet werden. PHP enthält viele andere Funktionen, die in diesem Anhang aus Platzgründen nicht beschrieben werden können. In diesem Anhang können Sie schnell eine nützliche Funktion finden oder die Reihenfolge und die Typen der Argumente einer Funktion nachschlagen. Weitere Informationen über die Funktionen, die in diesem Anhang beschrieben werden, sowie über Funktionen, die hier nicht beschrieben werden, finden Sie im PHP-Online-Handbuch auf der PHP-Website unter http:// www.php.net. Die Funktionen werden hier mit Hilfe von Funktionsprototypen beschrieben, die die gleiche Form wie die Prototypen haben, die in dem PHP-Online-Handbuch benutzt werden. Funktionsprototypen sind etwas komplexer als die Syntaxmuster, die an anderen Stellen in diesem Buch verwendet werden, aber Funktionsprototypen liefern mehr Informationen als einfache Syntaxmuster. Das Folgende ist ein Beispiel für einen Funktionsprototyp: int area (double length [, double width]) Dieser Prototyp beschreibt eine Funktion namens area, die einen Wert vom Typ int zurückgibt. Das erste Argument der Funktion heißt length und ist vom Typ double. Natürlich können Sie die Funktionen mit einem beliebig benannten Argument aufrufen. Der Name length ist ein Platzhalter – ein formaler Parameter –, der dazu dient, das Argument zu bezeichnen. Der Name des Arguments wird kursiv dargestellt, um anzuzeigen, dass er ersetzt werden kann. Die eckigen Klammern zeigen an, dass das zweite Argument – ein double namens width – optional ist. Wenn das Argument angegeben wird, muss das voranstehende Komma ebenfalls verwendet werden. Um anzuzeigen, dass ein Argument unbegrenzt oft verwendet werden darf, wird das Symbol ... verwendet. Beispielsweise hat der Prototyp der Funktion array() die folgende Form: array array ([mixed ...]) Der Prototyp zeigt an, dass array() einen Wert vom Typ array zurückgibt und dass die Funktion null oder mehr Argumente beliebigen Typs haben kann. Wenn ein Argument einen beliebigen Typ haben kann, wird der Typ des Arguments als mixed angegeben. Wenn ein Argument einen von mehreren bestimmten Typen haben kann, werden die Typen angegeben und jeweils durch einen senkrechten Balken getrennt. Beispielsweise kann ein Argument, das vom Typ int|double ist, den Typ int oder den Typ double haben. Es gibt einen speziellen Typ, resource, der Werten zugewiesen wird, die von Funktionen wie mysql_connect() zurückgegeben werden. Anhang I: PHP-Funktionen 531 Array-Funktionen Funktionsprototyp Beschreibung array array input) array array Gibt ein Array der Parameter zurück Gibt die Anzahl der Werte in einem Array zurück Berechnet die Differenz von zwei oder mehr Arrays array ([mixed ...]) array_count_values(array array_diff (array array1, array2 [, array ...]) array array_filter (array input [, mixed callback]) Filtert Elemente eines Arrays mit Hilfe einer Callback-Funktion array array_flip (array trans) Kehrt die Reihenfolge der Werte eines Arrays um array array_intersect (array array1, array array2 [, array ...]) array array_keys (array input [, mixed search_value]) array array_merge (array array1, array array2 [, array ...]) array array_merge_recursive (array array1, array array2 [, array ...]) bool array_multisort (array ar1 [, mixed arg [, mixed ... [, array ...]]]) array array_pad (array input, int pad_size, mixed pad_value) mixed array_pop (array array) Bestimmt die Elemente, die zwei oder mehr Arrays gemeinsam haben Gibt die Schlüssel eines Arrays zurück int array_push (array array, mixed var [, mixed ...]) Fügt ein oder mehrere Elemente an das Ende des Arrays an mixed array_rand (array input [, int num_req]) mixed array_reduce (array input, mixed callback [, int initial]) array array_reverse (array array [, bool preserve_keys]) Wählt einen Eintrag oder mehrere Einträge zufällig aus einem Array aus Wendet auf jedes Element eines Arrays eine Funktion an und gibt ein Ergebnis zurück Gibt ein Array mit den Elementen in umgekehrter Reihenfolge zurück mixed array_search (mixed needle, array haystack, bool strict) Durchsucht ein Array nach einem bestimmten Wert und gibt den zugehörigen Schlüssel zurück, wenn der Wert gefunden wird Entfernt ein Element vom Anfang eines Arrays mixed array_shift (array array) array array_slice (array array, int offset [, int length]) Führt zwei oder mehr Arrays zusammen Führt zwei oder mehr Arrays rekursiv zusammen Sortiert ein oder mehrere Arrays mit einer oder mehreren Dimensionen Füllt das Array bis zur angegebenen Länge auf Entfernt das Element am Ende des Arrays Gibt einen Teil eines Arrays zurück I 532 PHP 4 IT-Tutorial Funktionsprototyp Beschreibung array array_splice (array input, int offset [, int length [, array replacement]]) Entfernt und ersetzt einen Teil eines Arrays mixed array_sum (array arr) Berechnet die Summe der Werte in einem Array array array_unique (array array) int array_unshift (array array, mixed var [, mixed ...]) array array_values (array input) Entfernt doppelte Werte aus einem Array Fügt ein oder mehrere Elemente am Anfang eines Arrays ein Gibt alle Werte eines Arrays zurück int array_walk (array arr, string func, mixed userdata) void arsort (array array [, int sort_flags]) Wendet auf jedes Element eines Arrays eine Funktion an Sortiert ein Array in umgekehrter Reihenfolge, wobei die Indexzuordnung erhalten bleibt void asort (array array [, int sort_flags]) array compact (mixed varname [, mixed ...]) int count (mixed var) Sortiert ein Array, wobei die Indexzuordnung erhalten bleibt Erstellt ein Array, das die Werte der angegebenen Variablen enthält Gibt die Anzahl der Elemente zurück, die in einer Variablen enthalten sind Gibt das aktuelle Element eines Arrays zurück mixed current (array array) array each (array array) Gibt das nächste Schlüssel-Wert-Paar eines Arrays zurück mixed end (array array) Setzt den internen Zeiger eines Arrays auf dessen letztes Element int extract (array var_array [, int extract_type [, string prefix]]) bool in_array (mixed needle, array haystack [, bool strict]) mixed key (array array) Importiert Variablen, die durch ein Array angegeben werden, in die Symboltabelle Gibt TRUE zurück, wenn der angegebene Wert in einem Array existiert Gibt einen Schlüssel eines assoziativen Arrays zurück Sortiert ein Array in umgekehrter Reihenfolge nach den Schlüsseln int krsort (array array [, int sort_flags]) int ksort (array array [, int sort_flags]) Sortiert ein Array nach den Schlüsseln void list (...) void natcasesort (array array) Weist einer Reihe von Variablen Werte zu Sortiert ein Array unabhängig von der Groß/Kleinschriebung in natürlicher Reihenfolge void natsort (array array) mixed next (array array) Sortiert ein Array in natürlicher Reihenfolge Setzt den internen Zeiger eines Arrays um eine Position weiter Anhang I: PHP-Funktionen Funktionsprototyp Beschreibung mixed pos (array array) Gibt das aktuelle Element eines Arrays zurück mixed prev (array array) Setzt den internen Zeiger eines Arrays um eine Position zurück Erstellt ein Array, das einen Bereich von Ganzzahlen enthält Setzt den internen Zeiger eines Arrays auf das erste Element Sortiert ein Array in umgekehrter Reihenfolge array range (int low, int high) mixed reset (array array) void rsort (array array [, int sort_flags]) void shuffle (array array) Erzeugt eine zufällige Reihenfolge der Elemente eines Arrays int sizeof (array array) Gibt die Anzahl der Elemente eines Arrays zurück void sort (array array [, int sort_flags]) void uasort (array array, function cmp_function) void uksort (array array, function cmp_function) Sortiert ein Array void usort (array array, string cmp_function) Sortiert ein Array mit Hilfe einer benutzerdefinierten Vergleichsfunktion Sortiert ein Array mit Hilfe einer benutzerdefinierten Vergleichsfunktion nach den Schlüsseln Sortiert ein Array mit Hilfe einer benutzerdefinierten Vergleichsfunktion nach Werten Ausgabekontrollfunktionen Funktionsprototyp void ob_end_clean () void ob_end_flush () void flush () string ob_get_contents () string ob_get_length () string ob_gzhandler (string buffer) void ob_implicit_flush ([int flag]) void ob_start ([string output_callback]) Beschreibung Löscht den Inhalt des Output-Puffers und schaltet das Puffern des Outputs ab Leert den Output-Puffer und deaktiviert das Puffern des Outputs Leert den Output-Puffer Gibt den Inhalt des Output-Puffers zurück Gibt die Länge des Output-Puffers zurück Eine Callback-Funktion, um den Inhalt des Output-Puffers mit gzip zu bearbeiten (wird über eine Option in php.ini aktiviert) Schaltet das implizite Leeren an oder ab Ermöglicht das Puffern des Outputs 533 I 534 PHP 4 IT-Tutorial Dateisystemfunktionen Funktionsprototyp string basename (string path) int chgrp (string filename, mixed group) int chmod (string filename, int mode) int chown (string filename, mixed user) void clearstatcache () int copy (string source, string dest) string dirname (string path) float diskfreespace (string directory) bool fclose (int fp) int feof (int fp) int fflush (int fp) string fgetc (int fp) array fgetcsv (int fp, int length [, string delimiter]) string fgets (int fp, int length) string fgetss (int fp, int length [, string allowable_tags]) array file (string filename [, int use_include_path]) bool file_exists (string filename) int fileatime (string filename) int filectime (string filename) int filegroup (string filename) int fileinode (string filename) int filemtime (string filename) int fileowner (string filename) int fileperms (string filename) int filesize (string filename) string filetype (string filename) Beschreibung Gibt den Dateinamen innerhalb eines Pfads zurück Ändert die Gruppenzugehörigkeit einer Datei Ändert die Berechtigungen einer Datei Ändert den Eigentümer einer Datei Löscht den Dateistatus-Zwischenspeicher Kopiert eine Datei Gibt den Verzeichnisnamen eines Pfads zurück Gibt den verfügbaren Speicherplatz in einem Verzeichnis zurück Schließt einen geöffneten Dateizeiger Prüft, ob der Dateizeiger am Ende der Datei steht Schreibt ausstehenden Output in eine Datei Gibt ein Zeichen einer Datei zurück Gibt eine Zeile einer Datei zurück und parst die Zeile auf CSV-Felder Gibt eine Zeile einer Datei zurück Gibt eine Zeile einer Datei zurück und entfernt HTML-Tags Liest eine komplette Datei in ein Array Prüft, ob eine Datei existiert Gibt die Zeit des letzten Dateizugriffs zurück Gibt die Zeit zurück, zu der der I-Node einer Datei geändert wurde Gibt die Gruppenzugehörigkeit einer Datei zurück Gibt den I-Node einer Datei zurück Gibt die Zeit der letzten Änderung einer Datei zurück Gibt den Eigentümer einer Datei zurück Gibt die Berechtigungen zurück, die mit einer Datei verbunden sind Gibt die Größe einer Datei zurück Gibt den Typ einer Datei zurück Anhang I: PHP-Funktionen Funktionsprototyp bool flock (int fp, int operation [, int wouldblock]) int fopen (string filename, string mode [, int use_include_path]) int fpassthru (int fp) int fputs (int fp, string str [,int length]) string fread (int fp, int length) mixed fscanf (int handle, string format [, string var1...]) int fseek (int fp, int offset [, int base]) array fstat (int fp) int ftell (int fp) int ftruncate (int fp, int size) int fwrite (int fp, string string [, int length]) bool is_dir (string filename) bool is_executable (string filename) bool is_file (string filename) bool is_link (string filename) bool is_readable (string filename) bool is_uploaded_file (string filename) bool is_writable (string filename) int link (string target, string link) int linkinfo (string path) array lstat (string filename) int mkdir (string pathname, int mode) bool move_uploaded_file (string filename, string destination) array pathinfo (string path) int pclose (int fp) 535 Beschreibung Sperrt eine Datei Öffnet eine Datei oder einen URL Schreibt alle verbleibenden Daten in eine Datei Schreibt in eine Datei Liest die Binärdaten einer Datei auf sichere Weise Parst den Input einer Datei entsprechend einer Formatangabe Setzt den Dateizeiger an die angegebene Position innerhalb einer Datei Gibt mit Hilfe eines geöffneten Dateizeigers Informationen über eine Datei zurück Gibt die aktuelle Position innerhalb einer Datei zurück Verkleinert eine Datei auf die angegebene Länge Schreibt auf sichere Weise Daten in eine Binärdatei Prüft, ob ein Dateiname ein Verzeichnis bezeichnet Prüft, ob eine Datei ausführbar ist Prüft, ob die Datei eine normale Datei ist Prüft, ob ein Dateiname einen symbolischen Link (Verknüpfung) bezeichnet Prüft, ob eine Datei lesbar ist Prüft, ob eine Datei über HTTP-POST heraufgeladen wurde Prüft, ob eine Datei schreibbar ist; dasselbe wie is_writeable() Erstellt einen „harten“ Link Gibt Informationen über einen Link zurück Gibt Informationen über eine Datei oder einen symbolischen Link zurück Erstellt ein Verzeichnis Verschiebt eine heraufgeladene Datei an eine andere Stelle Gibt Informationen über einen Pfad zurück Schließt eine Pipe I 536 PHP 4 IT-Tutorial Funktionsprototyp int popen (string command, string mode) int readfile (string filename [, int use_include_path]) string readlink (string path) string realpath (string path) int rename (string oldname, string newname) int rewind (int fp) int rmdir (string dirname) int set_file_buffer (int fp, int buffer) array stat (string filename) int symlink (string target, string link) string tempnam (string dir, string prefix) int tmpfile () int touch (string filename [, int time]) int umask (int mask) int unlink (string filename) Beschreibung Öffnet eine Pipe Liest eine Datei Gibt das Ziel eines symbolischen Links zurück Gibt einen kanonischen, absoluten Pfadnamen zurück Benennt eine Datei um Setzt die Position eines Dateizeigers zurück Löscht ein Verzeichnis Verbindet einen Dateipuffer mit einer Datei Gibt Informationen über eine Datei zurück Erstellt einen symbolischen Link Erstellt einen eindeutigen Dateinamen Erstellt eine temporäre Datei Setzt den Änderungszeitpunkt einer Datei auf die aktuelle Zeit Ändert die aktuelle umask Löscht eine Datei Datums- und Zeitfunktionen Funktionsprototyp int checkdate (int month, int day, int year) string date (string format [, int timestamp]) array getdate ([int timestamp]) Beschreibung Prüft ein gregorianisches Datum Formatiert eine lokale Datums-/Zeitangabe Gibt Datums-/Zeit-Informationen zurück array gettimeofday () Gibt die aktuelle Zeit zurück string gmdate (string format [, int timestamp]) Formatiert eine GMT-Datums-/Zeitangabe int gmmktime (int hour, int minute, int second, int month, int day, int year [, int is_dst]) Gibt den UNIX-Zeitstempel eines GMTDatums zurück string gmstrftime (string format [, int timestamp]) Formatiert eine GMT-Datums-/Zeitangabe den aktuellen Ländereinstellungen entsprechend Anhang I: PHP-Funktionen Funktionsprototyp Beschreibung array localtime ([int timestamp [,bool is_associative]]) Gibt die lokale Zeit zurück string microtime () Gibt den aktuellen UNIX-Zeitstempel einschließlich der Mikrosekunden zurück Gibt den UNIX-Zeitstempel eines Datums zurück int mktime (int hour, int minute, int second, int month, int day, int year [, int is_dst]) string strftime (string format [,int timestamp]) Formatiert eine lokale Datums-/Zeitangabe den aktuellen Ländereinstellungen entsprechend int strtotime (string time [,int now]) Wandelt eine Datums-/Zeitangabe in Form eines englischen Textes in einen UNIX-Zeitstempel um int time () Gibt den aktuellen UNIX-Zeitstempel zurück Fehlerbehandlungs- und Protokollfunktionen Funktionsprototyp Beschreibung int error_log (string message, int message_type [, string destination [, string extra_headers]]) Schreibt eine Fehlermeldung in ein Protokoll int error_reporting ([int level]) Legt fest, welche PHP-Fehler gemeldet werden void restore_error_handler () Stellt eine frühere Fehlerbehandlungsfunktion wieder her Setzt eine benutzerdefinierte Fehlerbehandlungsfunktion Löst eine Fehlermeldung auf Benutzerebene aus Erzeugt eine Fehlermeldung auf Benutzerebene string set_error_handler (string error_handler) void trigger_error (string error_msg [, int error_type]) void user_error (string error_msg [, int error_type]) 537 I 538 PHP 4 IT-Tutorial FTP-Funktionen Funktionsprototyp int ftp_chdir (int ftp_stream, string directory) int ftp_cdup (int ftp_stream) int ftp_connect (string host [, int port]) int ftp_delete (int ftp_stream, string path) int ftp_fget (int ftp_stream, int fp, string remote_file, int mode) Beschreibung Wechselt zu dem angegebenen Verzeichnis auf einem FTP-Server Wechselt zum übergeordneten Verzeichnis Öffnet eine FTP-Verbindung Löscht eine Datei auf dem FTP-Server Lädt eine Datei von dem FTP-Server herunter und speichert die Daten in einer geöffneten Datei int ftp_fput (int ftp_stream, Lädt Daten von einer geöffneten Datei auf string remote_file, int fp, int mode) einen FTP-Server herauf int ftp_get (int ftp_stream, string Lädt eine Datei von dem FTP-Server herunter local_file, string remote_file, int mode) int ftp_login (int ftp_stream, Loggt sich bei einer geöffneten FTP-Verbinstring username, string password) dung ein int ftp_mdtm (int ftp_stream, Gibt den Zeitpunkt der letzten Änderung string remote_file) der angegebenen Datei zurück string ftp_mkdir (int ftp_stream, Erstellt ein Verzeichnis auf dem FTP-Server string directory) array ftp_nlist (int ftp_stream, Gibt eine Liste der Dateien in dem angegestring directory) benen Verzeichnis zurück int ftp_pasv (int ftp_stream, int Schaltet den Passivmodus an oder ab pasv) int ftp_put (int ftp_stream, string Lädt eine Datei auf den FTP-Server herauf remote_file, string local_file, int mode) string ftp_pwd (int ftp_stream) Gibt den aktuellen Verzeichnisnamen zurück int ftp_quit (int ftp_stream) Schließt eine FTP-Verbindung array ftp_rawlist (int ftp_stream, Gibt eine detaillierte Liste der Dateien in string directory) dem angegebenen Verzeichnis zurück int ftp_rename (int ftp_stream, Benennt eine Datei auf dem FTP-Server um string from, string to) int ftp_rmdir (int ftp_stream, Löscht ein Verzeichnis auf dem FTP-Server string directory) int ftp_site (int ftp_stream, Sendet einen SITE-Befehl an den FTP-Server string cmd) int ftp_size (int ftp_stream, Gibt die Größe der angegebenen Datei string remote_file) zurück string ftp_systype (int ftp_stream) Gibt den Systemtyp-Bezeichner des RemoteFTP-Servers zurück Anhang I: PHP-Funktionen 539 HTTP-Funktionen Funktionsprototyp int header (string string) bool headers_sent () int setcookie (string name [, string value [, int expire [, string path [, string domain [, int secure]]]]]) Beschreibung Sendet einen rohen HTTP-Header Gibt true zurück, wenn HTTP-Header gesendet wurden Sendet ein Cookie IMAP-, POP3- und NNTP-Funktionen Funktionsprototyp string imap_8bit (string string) array imap_alerts () int imap_append (int imap_stream, string imap_base64 (string text) string imap_binary (string string) string imap_body (int imap_stream, int msg_number [, int flags]) object imap_check (int imap_stream) string imap_clearflag_full (int stream, string sequence, string flag, string options) int imap_close (int imap_stream [,int flags]) int imap_createmailbox (int imap_stream, string mbox) int imap_delete (int imap_stream, int msg_number [, int flags]) int imap_deletemailbox (int imap_stream, string mbox) Beschreibung Wandelt einen 8-Bit-String in einen QuotedPrintable-String (druckbaren String in Anführungszeichen) um Gibt IMAP-Alert-Meldungen zurück, die während der aktuellen Seitenabfrage oder seit dem Rücksetzen des Alert-Stacks aufgetreten sind Fügt eine String-Meldung an die angegebene Mailbox an Entschlüsselt BASE64-codierten Text Wandelt einen 8-Bit-String in einen BASE64String um Liest einen Meldungskörper Prüft die aktuelle Mailbox Löscht die Flags von Meldungen Schließt einen IMAP-Stream Erstellt eine neue Mailbox Markiert eine Meldung in der aktuellen Mailbox zum Löschen Löscht eine Mailbox I 540 PHP 4 IT-Tutorial Funktionsprototyp array imap_errors () Beschreibung Gibt alle IMAP-Fehler zurück, die während der aktuellen Seitenabfrage oder seit dem Rücksetzen des Alert-Stacks aufgetreten sind int imap_expunge (int imap_stream) Löscht alle Meldungen, die zum Löschen markiert sind array imap_fetch_overview (int Gibt einen Überblick über die Informationen imap_stream, string sequence [, int in den Headern der angegebenen Meldung flags]) string imap_fetchbody (int Gibt den angegebenen Abschnitt des Bodys imap_stream, int msg_number,string einer Meldung zurück part_number [, flags flags]) string imap_fetchheader (int Gibt den Header einer Meldung zurück imap_stream, int msgno, int flags) object imap_fetchstructure (int Liest die Struktur einer bestimmten Meldung imap_stream, int msg_number [, int flags]) array imap_get_quota (int Gibt die Quoteneinstellungen einer Mailbox imap_stream, string quota_root) zurück array imap_getmailboxes (int Liest die Liste der Mailboxen imap_stream, string ref, string pattern) array imap_getsubscribed (int Listet alle abonnierten Mailboxen auf imap_stream, string ref, string pattern) object imap_header (int Liest den Header einer Meldung imap_stream, int msg_number [, int fromlength [, int subjectlength [, string defaulthost]]]) object imap_headerinfo (int Liest den Header einer Meldung imap_stream, int msg_number [, int fromlength [, int subjectlength [, string defaulthost]]]) array imap_headers (int Gibt die Header aller Meldungen in einer imap_stream) Mailbox zurück string imap_last_error () Gibt den letzten IMAP-Fehler zurück, der während der aktuellen Seitenabfrage aufgetreten ist array imap_listmailbox (int Gibt die Liste der Mailboxen zurück imap_stream, string ref, string pattern) array imap_listsubscribed (int Gibt alle abonnierten Mailboxen zurück imap_stream, string ref, string pattern) string imap_mail (string to, Sendet eine E-Mail-Nachricht string subject, string message [, string additional_headers [, string cc [, string bcc [, string rpath]]]]) Anhang I: PHP-Funktionen Funktionsprototyp string imap_mail_compose (array envelope, array body) int imap_mail_copy (int imap_stream, string msglist, string mbox [, int flags]) object imap_mailboxmsginfo (int imap_stream) array imap_mime_header_decode (string text) int imap_msgno (int imap_stream, int uid) int imap_num_msg (int imap_stream) int imap_num_recent (int imap_stream) int imap_open (string mailbox, string username, string password [, int flags]) int imap_ping (int imap_stream) string imap_qprint (string string) int imap_renamemailbox (int imap_stream, string old_mbox, string new_mbox) int imap_reopen (int imap_stream, string mailbox [, string flags]) array imap_rfc822_parse_adrlist (string address, string default_host) object imap_rfc822_parse_headers (string headers [, string defaulthost]) string imap_rfc822_write_address (string mailbox, string host, string personal) array imap_scanmailbox (int imap_stream, string ref, string pattern, string content) array imap_search (int imap_stream, string criteria, int flags) int imap_set_quota (int imap_stream, string quota_root, int quota_limit) string imap_setflag_full (int stream, string sequence, string flag, string options) 541 Beschreibung Erstellt eine MIME-Meldung anhand eines angegebenen Bodys und eines Envelopes Kopiert die angegebenen Meldungen in eine Mailbox Gibt Informationen über die aktuelle Mailbox zurück Entschlüsselt MIME-Header-Elemente Gibt die Meldungssequenznummer der angegebenen UID zurück Gibt die Anzahl der Meldungen in der aktuellen Mailbox zurück Gibt die Anzahl der neuen Meldungen in der aktuellen Mailbox zurück Öffnet einen IMAP-Stream zu einer Mailbox Prüft, ob ein IMAP-Stream aktiv ist Wandelt einen Quoted-Printable-String in einen 8-Bit-String um Benennt eine Mailbox um Öffnet einen IMAP-Stream erneut Parst eine RFC-822-Adresse Parst RFC-822-Mail-Header Gibt eine passend formatierte E-Mail-Adresse zurück Durchsucht Mailboxen nach Text Durchsucht Mailboxen nach Meldungen, die die angegebenen Kriterien erfüllen Setzt die Quote für eine Mailbox Setzt Meldungsflags I 542 PHP 4 IT-Tutorial Funktionsprototyp array imap_sort (int stream, int criteria, int reverse, int options) object imap_status (int imap_stream, string mailbox, int options) int imap_subscribe (int imap_stream, string mbox) int imap_uid (int imap_stream, int msgno) int imap_undelete (int imap_stream, int msg_number) int imap_unsubscribe (int imap_stream, string mbox) string imap_utf7_decode (string text) string imap_utf7_encode (string data) string imap_utf8 (string text) Beschreibung Sortiert ein Array mit Meldungs-Headern Gibt Statusinformationen über eine Mailbox zurück Abonniert eine Mailbox Gibt die UID der angegebenen Meldungssequenznummer zurück Setzt das Löschflag einer Meldung zurück Hebt das Abonnement einer Mailbox auf Entschlüsselt einen modifizierten UTF-7codierten String Wandelt 8-Bit-Daten in modifizierten UTF-7Text um Wandelt Text in UTF-8 um Kalenderfunktionen Funktionsprototyp int easter_date (int year) int easter_days (int year) int frenchtojd (int month, int day, int year) int gregoriantojd (int month, int day, int year) mixed jddayofweek (int julianday, int mode) string jdmonthname (int julianday, int mode) string jdtofrench (int juliandaycount) string jdtogregorian (int julianday) string jdtojewish (int julianday) Beschreibung Gibt einen UNIX-Zeitstempel für Mitternacht des Osterdatums des angegebenen Jahres zurück Gibt die Anzahl der Tage nach dem 21. März bis zum Osterdatum des angegebenen Jahres zurück Wandelt ein Datum des französischen republikanischen Kalenders in eine julianische Tageszahl um Wandelt ein gregorianisches Datum in eine julianische Tageszahl um Gibt den Tag der Woche zurück Gibt einen Monatsnamen zurück Wandelt eine julianische Tageszahl in ein Datum des französischen republikanischen Kalenders um Wandelt eine julianische Tageszahl in ein gregorianisches Datum um Wandelt eine julianische Tageszahl in ein Datum des jüdischen Kalenders um Anhang I: PHP-Funktionen Funktionsprototyp string jdtojulian (int julianday) int jdtounix (int julianday) int jewishtojd (int month, int day, int year) int juliantojd (int month, int day, int year) int unixtojd ([int timestamp]) 543 Beschreibung Wandelt eine julianische Tageszahl in ein Datum des julianischen Kalenders um Wandelt eine julianische Tageszahl in einen UNIX-Zeitstempel um Wandelt ein Datum des jüdischen Kalenders in eine julianische Tageszahl um Wandelt ein Datum des julianischen Kalenders in eine julianische Tageszahl um Wandelt einen UNIX-Zeitstempel in eine julianische Tageszahl um Klassen/Objekt-Funktionen Funktionsprototyp mixed call_user_method_array (string method, object obj [, array parm]) mixed call_user_method (string method, object obj [, mixed parm [, mixed ...]]) bool class_exists (string class_name) string get_class (object obj) array get_class_methods (string class_name) array get_class_vars (string class_name) array get_declared_classes () array get_object_vars (object obj) string get_parent_class (object obj) bool method_exists (object object, string method) Beschreibung Ruft eine Benutzermethode mit dem angegebenen Parameter-Array auf Ruft eine Benutzermethode für das angegebene Objekt auf Prüft, ob eine bestimmte Klasse definiert ist Gibt den Klassennamen eines Objekts zurück Gibt ein Array mit den Namen der Methoden einer Klasse zurück Gibt ein Array mit den Standardeigenschaften einer Klasse zurück Gibt ein Array mit den Namen der definierten Klassen zurück Gibt ein assoziatives Array mit Objekteigenschaften zurück Gibt den Namen der übergeordneten Klasse eines Objekts zurück Prüft, ob eine Klassenmethode existiert I 544 PHP 4 IT-Tutorial Mail-Funktionen Funktionsprototyp bool mail (string to, string subject, string message [, string additional_headers [, string additional_parameters]]) int ezmlm_hash (string addr) Beschreibung Sendet E-Mail Berechnet den Hash-Wert, der von EZMLM benötigt wird Mathematische Funktionen Funktionsprototyp mixed abs (mixed number) float acos (float arg) float asin (float arg) float atan (float arg) float atan2 (float y, float x) string base_convert (string number, int frombase, int tobase) int bindec (string binary_string) float ceil (float value) float cos (float arg) string decbin (int number) string dechex (int number) string decoct (int number) double deg2rad (double number) float exp (float arg) Beschreibung Gibt den absoluten Wert des angegebenen Arguments zurück Gibt den Arcuscosinus des angegebenen Arguments zurück Gibt den Arcussinus des angegebenen Arguments zurück Gibt den Arcustangens des angegebenen Arguments zurück Gibt den Arcustangens des angegebenen Punktes zurück Wandelt eine Zahl zwischen beliebigen Basen um Wandelt einen binären in einen dezimalen Wert um Rundet einen Wert auf die nächste Ganzzahl, die größer als dieser Wert oder gleich diesem ist Gibt den Cosinus des angegebenen Wertes zurück Wandelt einen dezimalen in einen binären Wert um Wandelt einen dezimalen in einen hexadezimalen Wert um Wandelt einen dezimalen in einen oktalen Wert um Wandelt einen Winkel in Grad in einen Winkel in Radians um Gibt die angegebene Potenz von e (die Basis des natürlichen Logarithmus) zurück Anhang I: PHP-Funktionen Funktionsprototyp float floor (float value) int getrandmax () int hexdec (string hex_string) double lcg_value () float log (float arg) float log10 (float arg) mixed max (mixed arg1, mixed arg2, mixed argn) mixed min (mixed arg1, mixed arg2, mixed argn) int mt_rand ([int min [, int max]]) void mt_srand (int seed) int mt_getrandmax () string number_format (float number, int decimals, string dec_point, string thousands_sep) int octdec (string octal_string) double pi () float pow (float base, float exp) double rad2deg (double number) int rand ([int min [, int max]]) double round (double val [, int precision]) float sin (float arg) float sqrt (float arg) void srand (int seed) Beschreibung Rundet einen Wert auf die nächste Ganzzahl, die kleiner als dieser Wert oder gleich diesem ist Gibt den größtmöglichen Wert zurück, der von rand() erzeugt werden kann Wandelt einen hexadezimalen in einen dezimalen Wert um Gibt einen zufälligen Wert zurück, der durch einen kombinierten Lineare-KongruenzGenerator erzeugt wurde Gibt den natürlichen Logarithmus des angegebenen Wertes zurück Gibt den Logarithmus zur Basis 10 des angegebenen Wertes zurück Gibt den größten Wert unter den angegebenen Werten zurück Gibt den kleinsten Wert unter den angegebenen Werten zurück Gibt einen zufälligen Wert aus dem angegebenen Bereich zurück Legt eine Seed-Zahl für den Zufallszahlengenerator fest, der von mt_rand() verwendet wird Gibt den größtmöglichen Wert zurück, der von mt_rand() erzeugt werden kann Formatiert eine Zahl mit Tausendergruppen Wandelt einen oktalen in einen dezimalen Wert um Gibt den Wert von Pi zurück Gibt den Potenzwert des angegebenen Wertes und des angegebenen Exponenten zurück Wandelt einen Winkel in Radians in einen Winkel in Grad um Gibt einen zufälligen Wert aus dem angegebenen Bereich zurück Rundet einen float-Wert Gibt den Sinus des angegebenen Wertes zurück Gibt die Quadratwurzel des angegebenen Wertes zurück Legt eine Seed-Zahl für den Zufallszahlengenerator fest, der von rand() verwendet wird 545 I 546 PHP 4 IT-Tutorial Funktionsprototyp float tan (float arg) Beschreibung Gibt den Tangens des angegebenen Wertes zurück MySQL-Funktionen Funktionsprototyp int mysql_affected_rows ([resource link_identifier]) int mysql_change_user (string user, string password [, string database [, resource link_identifier]]) bool mysql_close ([resource link_identifier]) resource mysql_connect ([string hostname [:port] [:/path/to/socket] [, string username [, string password]]]) int mysql_create_db (string database_name [, resource link_identifier]) bool mysql_data_seek (resource result_identifier, int row_number) string mysql_db_name (resourcev resource mysql_db_query (string database, string query [, resource link_identifier]) bool mysql_drop_db (string database_name [, resource link_identifier]) int mysql_errno ([resource link_identifier]) string mysql_error ([resource link_identifier]) string mysql_escape_string (string unescaped_string) array mysql_fetch_array (resource result [, int result_type]) array mysql_fetch_assoc (resource result) Beschreibung Gibt die Anzahl der Zeilen zurück, die von der vorausgegangenen MySQL-Operation betroffen waren Ändert die Benutzeridentität, die mit der aktiven Verbindung verbunden ist Schließt eine MySQL-Verbindung Öffnet eine Verbindung zu einem MySQLServer Erstellt eine MySQL-Datenbank Verschiebt den Zeiger der internen Ergebnismenge Gibt Daten der Ergebnismenge zurück Sendet eine MySQL-Abfrage zur Ausführung Löscht eine MySQL-Datenbank Gibt den numerischen Wert der Fehlermeldung der vorausgegangenen MySQL-Operation zurück Gibt den Text der Fehlermeldung der vorausgegangenen MySQL-Operation zurück Schützt einen String, der in einer Abfrage verwendet werden soll, durch Escape-Zeichen Gibt einen Datensatz als assoziatives Array, als numerisches Array oder in beiden Formen zurück Gibt einen Datensatz als assoziatives Array zurück Anhang I: PHP-Funktionen Funktionsprototyp object mysql_fetch_field (resource result [, int field_offset]) array mysql_fetch_lengths (resource result) object mysql_fetch_object (resource result [, int result_type]) array mysql_fetch_row (resource result) string mysql_field_flags (resource result, int field_offset) int mysql_field_len (resource result, int field_offset) string mysql_field_name (resource result, int field_index) int mysql_field_seek (resource result, int field_offset) string mysql_field_table (resource result, int field_offset) string mysql_field_type ( iresource result, int field_offset) int mysql_free_result (resource result) string mysql_get_client_info (void ) string mysql_get_host_info ([resource link_identifier]) int mysql_get_proto_info ([resource link_identifier]) int mysql_get_server_info ([resource link_identifier]) int mysql_insert_id ([resource link_identifier]) resource mysql_list_dbs ([resource link_identifier]) resource mysql_list_fields (string database_name, string table_name [, resource link_identifier]) resource mysql_list_tables (string database [, resource link_identifier]) int mysql_num_fields (resource result) 547 Beschreibung Gibt die Spalteninformationen einer Ergebnismenge als Objekt zurück Gibt die Länge jeder Spalte in einer Ergebnismenge zurück Gibt einen Datensatz als Objekt zurück Gibt einen Datensatz als indiziertes Array zurück Gibt die Flags zurück, die mit dem angegebenen Feld in einer Ergebnismenge verbunden sind Gibt die Länge des angegebenen Feldes in einer Ergebnismenge zurück Gibt den Namen des angegebenen Feldes in einer Ergebnismenge zurück Setzt den Ergebniszeiger auf das Feld mit dem angegebenen Offset Gibt den Namen der Tabelle zurück, aus der das Feld in der angegebenen Ergebnismenge stammt Gibt den Typ des Felds in der angegebenen Ergebnismenge zurück Gibt den Speicher der Ergebnismenge frei Gibt Informationen über den MySQL-Client zurück Gibt Informationen über den MySQL-Host zurück Gibt MySQL-Protokollinformationen zurück Gibt Informationen über den MySQL-Server zurück Gibt die ID zurück, die von der vorausgegangenen Insert-(Einfüge-)Operation einer Zeile generiert wurde, die über ein auto_increment-Feld verfügt Gibt eine Liste der Datenbanken zurück, die auf einem MySQL-Server zur Verfügung stehen Gibt eine Liste der Spalten einer MySQLTabelle zurück Gibt eine Liste der Tabellen in einer MySQLDatenbank zurück Gibt die Anzahl der Spalten in einer Ergebnismenge zurück I 548 PHP 4 IT-Tutorial Funktionsprototyp int mysql_num_rows (resource result) resource mysql_pconnect ([string hostname [:port] [:/path/to/socket] [, string username [, string password]]]) resource mysql_query (string query [, resource link_identifier]) mixed mysql_result (resource result, int row [, mixed field]) bool mysql_select_db (string database_name [, resource link_identifier]) string mysql_tablename (resource result, int i) Beschreibung Gibt die Anzahl der Zeilen in einer Ergebnismenge zurück Öffnet eine dauerhafte Verbindung zu einem MySQL-Server Sendet eine MySQL-Abfrage zur Ausführung Gibt Daten der Ergebnismenge zurück Wählt eine MySQL-Datenbank aus Gibt den Tabellennamen des Ergebnismenge-Feldes zurück PHP-Optionen und -Informationen Funktionsprototyp int assert (string|bool assertion) mixed assert_options (int what [,mixed value]) int dl (string library) bool extension_loaded (string name) string get_cfg_var (string varname) string get_current_user () array get_defined_constants () array get_extension_funcs (string module_name) array get_included_files () array get_loaded_extensions () long get_magic_quotes_gpc () Beschreibung Prüft, ob eine Zusicherung falsch ist Setzt verschiedene Assert-Flags oder gibt sie zurück Lädt eine PHP-Erweiterung Prüft, ob eine Erweiterung geladen ist Gibt den Wert einer Option der PHP-Konfiguration zurück Gibt den Namen des Eigentümers des aktuellen PHP-Skripts zurück Gibt ein assoziatives Array mit den Namen und Werten aller definierten Konstanten zurück Gibt ein Array mit den Namen der Funktionen innerhalb eines Moduls zurück Gibt ein Array mit den Namen der Dateien zurück, auf die mit einem Skript mittels include_once zugegriffen wurde Gibt ein Array mit den Namen aller geladenen Module zurück Gibt die aktuelle Einstellung von magic_quotes_gpc zurück Anhang I: PHP-Funktionen Funktionsprototyp long get_magic_quotes_runtime () array get_required_files () string getenv (string varname) int getlastmod () int getmyinode () int getmypid () int getmyuid () array getrusage ([int who]) string ini_alter (string varname, string newvalue) string ini_get (string varname) string name) string string string string ini_restore (string varini_set (string varname, newvalue) php_logo_guid () php_sapi_name () string php_uname () void phpcredits (int flag) int phpinfo ([int what]) string phpversion () void putenv (string setting) long set_magic_quotes_runtime (int new_setting) void set_time_limit (int seconds) string zend_logo_guid () string zend_version () 549 Beschreibung Gibt die aktuelle Einstellung von magic_quotes_runtime zurück Gibt ein Array mit den Namen der Dateien zurück, auf die mit einem Skript mittels require_once oder include_once zugegriffen wurde Gibt den Wert einer Umgebungsvariablen zurück Gibt den Zeitpunkt der letzten Änderung der aktuellen Seite zurück Gibt die I-Node-Nummer des aktuellen Skripts zurück Gibt die Prozess-ID des PHP-Skripts zurück Gibt die UID des Eigentümers des aktuellen Skripts zurück Gibt Informationen über die aktuelle Ressourcennutzung zurück Setzt den Wert einer Konfigurationsoption Gibt den Wert einer Konfigurationsoption zurück Stellt den Wert einer Konfigurationsoption wieder her Setzt den Wert einer Konfigurationsoption Gibt das PHP-Logo-Bild zurück Gibt den Typ der Schnittstelle zwischen dem Webserver und PHP zurück Gibt Informationen über das Betriebssystem zurück, unter dem PHP erstellt wurde Druckt die Credits (Angaben über die Urheber) von PHP Druckt Informationen über die PHP-Konfiguration und den PHP-Status Gibt die aktuelle PHP-Version zurück Setzt den Wert einer Umgebungsvariablen Setzt die aktuelle Einstellung von magic_quotes_runtime Setzt die Obergrenze für die Ausführungszeit Gibt das Zend-Logo-Bild zurück Gibt die Version der aktuellen Zend-Engine zurück I 550 PHP 4 IT-Tutorial Programmausführungsfunktionen Funktionsprototyp string escapeshellarg (string arg) string escapeshellcmd (string command) string exec (string command [, string array [, int return_var]]) void passthru (string command [, int return_var]) string system (string command [, int return_var]) Beschreibung Schützt einen String, der als Shell-Argument verwendet werden soll, durch Escape-Zeichen Schützt Shell-Metazeichen durch Escape-zeichen Führt ein externes Programm aus Führt ein externes Programm aus und zeigt den rohen Output an Führt ein externes Programm aus und zeigt den Output an POSIX-Funktionen Funktionsprototyp string posix_ctermid () string posix_getcwd () int posix_getegid () int posix_geteuid () int posix_getgid () array posix_getgrgid (int gid) array posix_getgrnam (string name) array posix_getgroups () int posix_getid (int pid) string posix_getlogin () int posix_getpgid (int pid) int posix_getpgrp () Beschreibung Gibt den Pfadnamen des Steuerterminals an, das mit dem aktuellen Prozess verbunden ist Gibt den Pfadnamen des aktuellen Verzeichnisses zurück Gibt die gegenwärtige Gruppen-ID des aktuellen Prozesses zurück Gibt die gegenwärtige Benutzer-ID des aktuellen Prozesses zurück Gibt die echte Gruppen-ID des aktuellen Prozesses zurück Gibt Informationen über die angegebene Prozessgruppe zurück Gibt Informationen über die angegebene Prozessgruppe zurück Gibt die Gruppe des aktuellen Prozesses zurück Gibt die SID des angegebenen Prozesses zurück Gibt den Login-Namen des Benutzers zurück, dem der aktuelle Prozess gehört Gibt die Prozessgruppen-ID des angegebenen Prozesses zurück Gibt den aktuellen Prozessgruppenbezeichner zurück Anhang I: PHP-Funktionen Funktionsprototyp int posix_getppid () array posix_getpwnam (string username) array posix_getpwuid (int uid) array posix_getrlimit () int posix_getuid () bool posix_isatty (int fd) bool posix_mkfifo (string pathname, int mode) bool posix_setgid (int gid) int posix_setpgid (int pid, int pgid) int posix_setsid () bool posix_setuid (int uid) array posix_times () string posix_ttyname (int fd) array posix_uname () Beschreibung Gibt die Prozess-ID des übergeordneten Prozesses zurück Gibt Informationen über den angegebenen Benutzer zurück Gibt Informationen über den angegebenen Benutzer zurück Gibt Informationen über Grenzen der Systemressourcen zurück Gibt die echte Benutzer-ID des aktuellen Prozesses zurück Gibt zurück, ob ein Dateideskriptor mit einem interaktiven Terminal verbunden ist Erstellt eine spezielle FIFO-Datei, d.h. eine benannte Pipe Setzt die gegenwärtige GID des aktuellen Prozesses Setzt die Prozessgruppen-ID des angegebenen Prozesses Macht aus dem aktuellen Prozess einen Sitzungsführer Setzt die gegenwärtige UID des aktuellen Prozesses Gibt Informationen über die CPU-Nutzung des aktuellen Prozesses zurück Gibt den Terminal-Gerätenamen zurück Gibt den Systemnamen zurück POSIX-Funktionen für erweiterte reguläre Ausdrücke Funktionsprototyp int ereg (string pattern, string string [, array regs]) string ereg_replace (string pattern, string replacement, string string) int eregi (string pattern, string string [, array regs]) string eregi_replace (string pattern, string replacement, string string) Beschreibung Prüft, ob ein String mit dem angegebenen regulären Ausdruck übereinstimmt Ersetzt einen Teilstring, der mit einem regulären Ausdruck übereinstimmt Prüft, ob ein String mit dem angegebenen regulären Ausdruck (Groß-/Kleinschreibung spielt keine Rolle) übereinstimmt Ersetzt einen Teilstring, der mit einem regulären Ausdruck übereinstimmt (Groß-/Kleinschreibung spielt keine Rolle) 551 I 552 PHP 4 IT-Tutorial Funktionsprototyp array split (string pattern, string string [, int limit]) array spliti (string pattern, string string [, int limit]) string sql_regcase (string string) Beschreibung Zerlegt einen String mittels eines regulären Ausdrucks in ein Array Zerlegt einen String mittels eines regulären Ausdrucks in ein Array (Groß-/Kleinschreibung spielt keine Rolle) Gibt ein Muster zurück, das auf dem angegebenen regulären Ausdruck basiert, wobei die Groß-/Kleinschriebung keine Rolle spielt Rechtschreibfunktionen Funktionsprototyp int aspell_new (string master, string personal) bool aspell_check (int dictionary_link, string word) bool aspell_check_raw (int dictionary_link, string word) array aspell_suggest (int dictionary_link, string word) Beschreibung Lädt ein Rechtschreibwörterbuch Prüft die Groß-/Kleinschriebung eines Wortes Prüft die Groß-/Kleinschriebung eines Wortes, ohne dessen Groß- oder Kleinschreibung zu ändern oder Leerzeichen am Anfang am oder Ende zu entfernen Schlägt mögliche Korrekturen der Groß-/ Kleinschreibung eines Wortes vor Sitzungsverwaltungsfunktionen Funktionsprototyp string session_cache_limiter ([string cache_limiter]) bool session_decode (string data) bool session_destroy () string session_encode () array session_get_cookie_params () string session_id ([string id]) bool session_is_registered (string name) string session_module_name ([string module]) Beschreibung Gibt die aktuelle Option zur Cache-Begrenzung zurück oder setzt diese Option Entschlüsselt Sitzungsdaten Löscht Daten, die zu einer Sitzung gespeichert wurden Verschlüsselt aktuelle Sitzungsdaten Gibt die Sitzungs-Cookie-Parameter zurück Gibt die aktuelle Sitzungs-ID zurück oder setzt sie Prüft, ob eine Variable in einer Sitzung registriert ist Gibt das aktuelle Sitzungsmodul zurück oder setzt dieses Anhang I: PHP-Funktionen Funktionsprototyp string session_name ([string name]) bool session_register (mixed name [, mixed ...]) string session_save_path ([string path]) void session_set_cookie_params (int lifetime [, string path [, string domain]]) void session_set_save_handler (string open, string close, string read, string write, string destroy, string gc) bool session_start () bool session_unregister (string name) void session_unset () Beschreibung Gibt den aktuellen Sitzungsnamen zurück oder setzt diesen Registriert eine oder mehrere Variablen in der aktuellen Sitzung Gibt den Speicherpfad der aktuellen Sitzung zurück oder setzt diesen Setzt die Sitzungs-Cookie-Parameter Setzt die Sitzungsspeicherfunktionen auf Benutzerebene Initialisiert die Sitzungsdaten Löscht die Registrierung einer Variablen in der aktuellen Sitzung Gibt alle Sitzungsvariablen frei String-Funktionen Funktionsprototyp string addcslashes (string str, string charlist) string addslashes (string str) string bin2hex (string str) string chop (string str) string chr (int ascii) string chunk_split (string str [, int chunklen [, string end]]) string convert_cyr_string (string str, string from, string to) mixed count_chars (string str [, int mode]) int crc32 (string str) string crypt (string str [, string salt]) echo (string arg1, string[argn]...) 553 I Beschreibung Fügt für die in charlist angegebenen Zeichen Slashes (genauer: Backslashes=\) in einen String ein Schließt einen String in Slashes ein Wandelt binäre in hexadezimale Daten um Entfernt Whitespace-Zeichen am Ende eines Strings Gibt das Zeichen zurück, das dem angegebenen ASCII-Wert zugeordnet ist Zerlegt einen String in Teilstrings Wandelt einen String aus einem kyrillischen Zeichensatz in einen anderen um Gibt Informationen über die Zeichen zurück, die in einem String verwendet werden Berechnet das crc32-Polynom eines Strings Verschlüsselt einen String mit DES Druckt einen oder mehrere Strings 554 PHP 4 IT-Tutorial Funktionsprototyp array explode (string separator, string str [, int limit]) string get_html_translation_table (int table [, int quote_style]) array get_meta_tags (string filename [, int use_include_path]) string [, int string [, int hebrev (string hebrew_text max_chars_per_line]) hebrevc (string hebrew_text max_chars_per_line]) string htmlentities (string str [, int quote_style]) string htmlspecialchars (string str [, int quote_style]) string implode (string glue, array pieces) string join (string glue, array pieces) int levenshtein (string str1, string str2) int levenshtein (string str1, string str2, int cost_ins, int cost_rep, int cost_del) int levenshtein (string str1, string str2, function cost) array localeconv () string ltrim (string str) string md5 (string str) string metaphone (string str) string nl2br (string str) int ord (string str) void parse_str (string str [,array arr]) print (string arg) int printf (string format [,mixed args...]) Beschreibung Zerlegt einen String in Teilstrings, wobei der angegebene Separatorstring (Trennstring) zugrunde gelegt wird Gibt die Übersetzungstabelle zurück, die von htmlspecialchars() und htmlentities() verwendet wird Extrahiert alle Meta-Tag-Inhaltsattribute aus einer Datei und gibt sie in einem Array zurück Wandelt logischen hebräischen Text in visuellen Text um Wandelt logischen hebräischen Text in visuellen Text um, wobei Zeilenumbrüche umgewandelt werden Wandelt alle anwendbaren Zeichen in HTML-Entities um Wandelt alle Sonderzeichen in HTML-Entities um Fasst Array-Elemente zu einem String zusammen und gibt diesen zurück Fasst Array-Elemente zu einem String zusammen und gibt diesen zurück Berechnet den Levenshtein-Abstand zwischen zwei Strings Berechnet den Levenshtein-Abstand zwischen zwei Strings Berechnet den Levenshtein-Abstand zwischen zwei Strings Gibt numerische Formatierungsinformationen für die aktuelle Ländereinstellung (Locale) zurück Entfernt Whitespace-Zeichen vom Anfang eines Strings Berechnet den MD5-Hash-Wert eines Strings Berechnet den metaphonen Wert eines Strings Fügt HTML-Zeilenumbrüche vor allen Zeilenumbruchzeichen in einen String ein Gibt den ASCII-Wert eines Zeichens zurück Parst einen String in Variablen Druckt einen String Druckt einen formatierten String Anhang I: PHP-Funktionen Funktionsprototyp string quoted_printable_decode (string str) string quotemeta (string str) string rtrim (string str) mixed sscanf (string str, string format [, string var1...]) string setlocale (mixed category, string locale) int similar_text (string first, string second [, double percent]) string soundex (string str) string sprintf (string format [,mixed args...]) int strncasecmp (string str1, string str2, int n) int strcasecmp (string str1, string str2) string strchr (string haystack, string needle) int strcmp (string str1, string str2) int strcoll (string str1, string str2) int strcspn (string str1, string str2) string strip_tags (string str [,string allowable_tags]) string stripcslashes (string str) string stripslashes (string str) string stristr (string haystack, string needle) int strlen (string str) int strnatcmp (string str1, string str2) 555 Beschreibung Wandelt einen Quoted-Printable-String in einen 8-Bit-String um Setzt in einem String Backslashes vor Metazeichen Entfernt Whitespace-Zeichen am Ende eines Strings Parst den Input aus einem String, dem angegebenen Format entsprechend Setzt Informationen der Ländereinstellung Berechnet die Ähnlichkeit zwischen zwei Strings Berechnet den Soundex-Wert eines Strings Gibt einen formatierten String zurück Vergleicht die ersten n Zeichen von zwei Strings (Groß-/Kleinschriebung spielt keine Rolle) Vergleicht zwei Strings (Groß-/Kleinschriebung spielt keine Rolle) Sucht das erste Vorkommen eines angegebenen Zeichens innerhalb eines Strings Vergleicht zwei Strings Vergleicht zwei Strings auf der Basis der aktuellen Ländereinstellung Bestimmt die Länge des linken Teilstrings, der dem angegebenen String nicht entspricht Entfernt die HTML- und PHP-Tags eines Strings Entfernt Slashes eines Strings, der das Format hat, das von addcslashes() zurückgegeben wurde Entfernt die Slashes eines Strings, der das Format hat, das durch addslashes() zurückgegeben wird Sucht das erste Vorkommen des angegebenen Teilstrings innerhalb eines Strings (Groß-/Kleinschriebung spielt keine Rolle) Gibt die Länge eines Strings zurück Vergleicht zwei Strings mit Hilfe eines Algorithmus, der auf der natürlichen Reihenfolge beruht I 556 PHP 4 IT-Tutorial Funktionsprototyp int strnatcasecmp (string str1, string str2) int strncmp (string str1, string str2, int n) string str_pad (string input, int pad_length [, string pad_string [, int pad_type]]) int strpos (string haystack, string needle [, int offset]) string strrchr (string haystack, string needle) string str_repeat (string input, int multiplier) string strrev (string str) int strrpos (string haystack, char needle) int strspn (string str1, string str2) string strstr (string haystack, string needle) string strtok (string arg1, string arg2) string strtolower (string str) string strtoupper (string str) mixed str_replace (mixed search, mixed replace, mixed subject) string strtr (string str, string from, string to) string substr (string str, int start [, int length]) int substr_count (string haystrack, string needle) string substr_replace (string str, string replacement, int start [, int length]) string trim (string str) string ucfirst (string str) Beschreibung Vergleicht zwei Strings mit Hilfe eines Algorithmus, der auf der natürlichen Reihenfolge beruht (Groß-/Kleinschreibung spielt keine Rolle) Vergleicht die ersten n Zeichen von zwei Strings Füllt einen String bis zu der angegebenen Länge auf Sucht das erste Vorkommen des angegebenen Teilstrings innerhalb eines Strings Sucht das erste Vorkommen eines Zeichens innerhalb eines Strings Gibt ein String zurück, der mehrere Wiederholungen des angegebenen Strings enthält Kehrt die Reihenfolge der Zeichen eines Strings um Sucht das letzte Vorkommen eines Zeichens innerhalb eines Strings Sucht die Länge des linken Teilstrings, der dem angegebenen String entspricht Sucht das erste Vorkommen eines Teilstrings Parst einen String in Tokens Wandelt einen String in Kleinbuchstaben um Wandelt einen String in Großbuchstaben um Ersetzt alle Vorkommen des angegebenen Suchstrings durch den angegebenen Ersetzungsstring Übersetzt die angegebenen Zeichen Gibt einen Teilstring zurück, der durch die angegebene Position festgelegt wird Zählt die Anzahl der Vorkommen eines Teilstrings Ersetzt einen Teilstring an der angegebenen Position Entfernt Whitespace-Zeichen vom Anfang und Ende eines Strings Wandelt das erste Zeichen eines Strings in Großbuchstaben um Anhang I: PHP-Funktionen 557 Funktionsprototyp string ucwords (string str) Beschreibung Wandelt das erste Zeichen jedes Wortes innerhalb eines Strings in Großbuchstaben um string wordwrap (string str [,int Umbricht einen String auf die angegebene width [, string break [, int cut]]]) Länge, wobei das angegebene Zeichen verwendet wird URL-Funktionen Funktionsprototyp string base64_decode (string encoded_data) string base64_encode (string data) array parse_url (string url) string rawurldecode (string str) string rawurlencode (string str) string urldecode (string str) string urlencode (string str) Beschreibung Entschlüsselt MIME-BASE64-Daten Verschlüsselt Daten mittels MIME BASE64 Parst einen URL und gibt dessen Komponenten zurück Entschlüsselt einen URL-codierten String Verschlüsselt einen URL mit der Methode, die in RFC1738 beschrieben wird Entschlüsselt einen URL-codierten String URL-verschlüsselt einen String Variablen-Funktionen Funktionsprototyp double doubleval (mixed var) boolean empty (mixed var) string gettype (mixed var) array get_defined_vars () string get_resource_type (resource handle) int intval (mixed var [, int base]) bool is_array (mixed var) bool is_bool (mixed var) bool is_double (mixed var) bool is_float (mixed var) Beschreibung Gibt einen double-Wert zurück, der dem Wert der Variablen entspricht Prüft, ob der Wert einer Variablen gesetzt ist Gibt den Typ einer Variablen zurück Gibt ein Array mit den Namen aller definierten Variablen zurück Gibt einen String zurück, der den Ressourcentyp einer Variablen beschreibt, der eine Ressource repräsentiert Gibt einen ganzzahligen Wert zurück, der dem Wert einer Variablen entspricht Prüft, ob eine Variable ein array ist Prüft, ob eine Variable ein bool-Wert ist Prüft, ob eine Variable ein double-Wert ist Prüft, ob eine Variable ein float-Wert ist I 558 PHP 4 IT-Tutorial Funktionsprototyp bool is_int (mixed var) bool is_integer (mixed var) bool is_long (mixed var) bool is_null (mixed var) bool is_numeric (mixed var) bool is_object (mixed var) bool is_real (mixed var) bool is_resource (mixed var) bool is_scalar (mixed var) bool is_string (mixed var) int isset (mixed var) void print_r (mixed expression) string serialize (mixed value) boolean settype (mixed var, string Typ) string strval (mixed var) mixed unserialize (string str) void unset (mixed var [, mixed var [, ...]]) void var_dump (mixed expression) Beschreibung Prüft, ob eine Variable ein int-Wert (Ganzzahl) ist Prüft, ob eine Variable ein int-Wert ist Prüft, ob eine Variable ein long-Wert ist Prüft, ob der Wert einer Variablen ein nullWert ist Prüft, ob eine Variable eine Zahl oder ein numerischer String ist Prüft, ob eine Variable ein Objekt ist Prüft, ob eine Variable ein real-Wert ist Prüft, ob eine Variable eine Ressource ist Prüft, ob eine Variable ein Skalar ist Prüft, ob eine Variable ein String ist Prüft, ob der Wert einer Variablen gesetzt ist Druckt für Menschen lesbare Informationen über eine Variable Erzeugt eine speicherbare Repräsentation eines Wertes Setzt den Typ einer Variablen Gibt den Stringwert zurück, der dem Wert einer Variablen entspricht Erstellt einen PHP-Wert aus einer gespeicherten Repräsentation Setzt den Wert einer Variablen zurück Druckt Informationen über eine Variable Verschiedene Funktionen Funktionsprototyp int connection_aborted () int connection_status () mixed constant (string name) int define (string name, mixed value [, int case_insensitive]) int defined (string name) void die (string message) mixed eval (string code_str) void exit (mixed status) Beschreibung Gibt true zurück, wenn der Client getrennt wurde Gibt den Status der aktuellen Verbindung zurück Gibt den Wert einer Konstanten zurück Definiert eine benannte Konstante Prüft, ob eine benannte Konstante existiert Gibt eine Meldung aus und beendet das aktuelle Skript Interpretiert einen String als PHP-Code Beendet das aktuelle Skript Anhang I: PHP-Funktionen Funktionsprototyp object get_browser ([string user_agent]) bool highlight_file (string filename) bool highlight_string (string str) int ignore_user_abort ([int setting]) array iptcparse (string iptcblock) void leak (int bytes) string pack (string format [,mixed args ...]) bool show_source (string filename) void sleep (int seconds) int uniqid (string prefix [,bool lcg]) array unpack (string format, string data) void usleep (int micro_seconds) 559 Beschreibung Gibt die Fähigkeiten des Client-Browsers zurück Druckt eine Datei mit hervorgehobener Syntax Druckt einen String mit hervorgehobener Syntax Legt fest, ob eine Unterbrechung der Verbindung zum Client die Ausführung des Skripts abbrechen sollte Parst einen binären IPTC-Block (International Press Telecommunications Council) in einzelne Tags Erzeugt für Testzwecke absichtlich Speicherlecks Packt Daten in einen binären String Druckt eine Datei mit hervorgehobener Syntax Verzögert die Ausführung um die angegebene Zeitspanne Erzeugt eine statistisch eindeutige ID Entpackt Daten eines binären Strings Verzögert die Ausführung um die in Mikrosekunden angegebene Zeitspanne Verzeichnisfunktionen Funktionsprototyp Beschreibung bool chroot (string dir) Ändert das Stammverzeichnis des aktuellen Prozesses bool chdir (string dir) Ändert das aktuelle Arbeitsverzeichnis new dir (string dir) Erstellt ein Verzeichnisobjekt void closedir (resource dir_handle) Schließt ein Verzeichnis-Handle string getcwd () Gibt das aktuelle Arbeitsverzeichnis zurück resource opendir (string path) Öffnet ein Verzeichnis-Handle string readdir (resource dir_handle) Liest einen Eintrag eines Verzeichnis-Handles void rewinddir (resource dir_handle) Setzt ein Verzeichnis-Handle zurück I 560 PHP 4 IT-Tutorial Zeichenfunktionen Funktionsprototyp bool ctype_alnum (string c) bool bool bool bool bool ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph (string (string (string (string (string c) c) c) c) c) bool ctype_print (string c) bool ctype_punct (string c) bool ctype_space (string c) bool ctype_upper (string c) bool ctype_xdigit (string c) Beschreibung Prüft auf ein oder mehrere alphanumerische Zeichen Prüft auf ein oder mehrere alphabetische Zeichen Prüft auf ein oder mehrere Steuerzeichen Prüft auf ein oder mehrere numerische Zeichen Prüft auf einen oder mehrere Kleinbuchstaben Prüft auf ein oder mehrere druckbare Zeichen, ausgenommen Leerzeichen Prüft auf ein oder mehrere druckbare Zeichen Prüft auf ein oder mehrere druckbare Zeichen, die weder Whitespace-Zeichen noch alphanumerische Zeichen sind Prüft auf ein oder mehrere Whitespace-Zeichen Prüft auf einen oder mehrere Großbuchstaben Prüft auf ein oder mehrere Zeichen, das bzw. die eine Hexadezimalzahl repräsentieren Stichwortverzeichnis Stichwortverzeichnis Symbols ! 120 $ 188 $$ 100 %-Zeichen 193 & (Referenz) 155 && 120 * (Metazeichen) 504 * Multiplikation 45 + Addition 45 – Subtraktion 45 / Division 45 = 40 => 166 ? (Metazeichen) 504 \ 188 \$ 38 \\ 38 \n 38 \r 38 \t 38, 188 || 120 Numerics 1:0-Beziehung 326 1:1-Beziehung 326 1:N-Beziehung 326 A Abfragestring 76, 92 abgeleitete Klasse 408 Ablaufzeitpunkt von Cookies 217 abs(x) 48 absoluter Pfad 240 Access-Methoden 411 Addition 45 addslashes() 527 addslashes()-Funktion 391 Aggregatfunktionen 346 Allaire 23 ALTER TABLE-Befehl 334 AND 120 Anführungszeichen 38, 190 Anhänge 283 Apache-Webserver 478, 480, 484 append 250 Arbeitsverzeichnis 240, 241, 500 ändern 271 ermitteln 270 Argumente 48, 144 Argumentenliste 148 Array 43 assoziatives 167 Elemente 43 elementweise durchlaufen 170 stringindiziertes 167 array()-Funktion 168 Array-Funktionen 531 Arrays sortieren 179 ASCII-Codes 189 AS-Klausel 347 attachments 283 Aufrufen von Funktionen 144 Ausdrücke 45 Ausgabekontrollfunktionen 533 Auskommentieren 453 Ausloggen 496 Ausnahmebehandlung 446 Ausrichtungszeichen 192 Auswahlliste 65 Authentifizierung 526 AUTO_INCREMENT 371 Autorisierung 526 B Backslash 38 basename()-Funktion 271 BASH 496 Basisklasse 408 Basisverzeichnis 493 Bedingungsausdrücke 118 Bedrohungen 524 Bedrohungstypen 525 benutzerdefinierte PHP-Funktionen 148 Benutzergruppen 235, 490, 494 Benutzer-ID 247 Benutzerkonten 239, 490, 493 Benutzernamen 526 Berechtigungen 237, 490, 494, 507, 526 Dateien 236 Verzeichnisse 243 561 562 PHP 4 IT-Tutorial Besitzer 495, 507 Besitzer von Dateien 235 Beziehungskardinalitäten 326 Bildschaltfläche 74 BLOB 331 body 282 boolesche Ausdrücke 118 Bourne-again-Shell 496 Bourne-Shell 496 break-Befehl 127, 172 Browser 86 Bugs 441 C caption 58 carriage return 38 case-Befehl 127 Casting 102 Cat-Operator 47 ceil(x) 48 CGI-Protokoll 92 Challenge-und-Response-Verfahren 526 CHAR 331 chdir()-Funktion 271 check box 64 chgrp-Befehl 235 chmod()-Funktion 249, 272 chmod-Befehl 237 Clark, James 396 Client-Port-Adresse 93 cols-Attribut 63 CONTENT_LENGTH 92 CONTENT_TYPE 92 continue-Befehl 173 Cookies 216 Ablaufzeitpunkt 217 erstellen 217 löschen 219 Werte speichern 220 Zugriff auf 216 copy()-Funktion 266 count()-Funktion 171 cp-Befehl 234 CREATE TABLE-Befehl 333 current()-Funktion 176 D Data Definition Language 333 Data Manipulation Language 338 Database Management System 318 DATE 331 date()-Funktion 109 Datei Besitzer ändern 249 Dateiattribute 246 Dateiberechtigungen 249 Datei-Control 67 Dateien 230, 490 anzeigen 232 Berechtigungen 236, 494 Berechtigungen ändern 507 Besitzer 235 Besitzer festlegen 507 Bytes lesen 254 Gruppenbesitzer 235 Inhalte ausgeben 257 Inhalte durchsuchen 509 komprimieren 510 kopieren 234, 266, 504 lesen 254 löschen 234, 268, 503 Name 491 Navigation 257 öffnen 250 Pfad 493 schließen 253 schreiben 259 sperren 263 suchen 508 Textzeilen lesen 255 Typ ermitteln 509 umbenennen 234, 267, 504 vergleichen 509 Datei-Handle 250 Dateiinformationen 231 Dateisystemfunktionen 534 Dateitypen 235 Dateizeiger 250 Position abfragen 259 Daten sortieren 346 Datenbanken abfragen 338 entwerfen 323 implementieren 323 Infos abfragen 384 normalisieren 327 relationale 316 sichern 528 Zugriffsrechte 335 Datenbanktreiber 318 Datenbankverwaltungssystem 318 Stichwortverzeichnis Datensicherheit 320 Datentypen 36 MySQL 331 Datumsfunktionen 536 DB2 318 DBMS 318 DDL 333 Debuggen 440, 451 DECIMAL 331 default-Befehl 127 Denial of service 525 DESC 346 Detail-Tabelle 353 Dezimalkomma 36 Dezimalpunkt 36 dirname()-Funktion 271 Division 45 DML 338 do while-Befehl 132 DOCUMENT_ROOT 92 Dokument Stammverzeichnis 92 Dokumentation 26 Dollarzeichen 38 DOS 525 DOUBLE 331 Doubles 36 drivers 453 DROP TABLE-Befehl 334 Dummy-Routine 163 dump_mailbox_status()-Funktion 293 Dynamische Variablen 99 E each()-Funktion 177 echo-Befehl 86 Einkapselung 406 Einloggen 496 Elemente eines Arrays 43 else-Befehl 125 elseif-Befehl 126 Elternklasse 408 Elternverzeichnis 239, 491 emacs 22, 502 E-Mail 282 empfangen 287 senden 282 E-Mail-Client 499 ENT_COMPAT 392 ENT_NOQUOTES 392 ENT_QUOTES 392 Entities 324 Entity 316 Entity-Header 219 Entity-Relationship-Modellierung 323 Entscheidungen 118 Equivalence Partitioning 456 E-R-Diagramm 326 Ergebnismengen 373, 377 E-R-Modell 331 E-R-Modellierung 323 error_log()-Funktion 449 Escape-Sequenzen 38, 188 Escape-Zeichen 390 Execute-Berechtigung 494 exit()-Funktion 149 Extensible Markup Language 396 F false 118 FastTemplate 430 fclose()-Funktion 253 Fehler beheben 455 Laufzeitfehler 443 logische Fehler 445 lokalisieren 453 verstehen 455 Fehlerbehandlung 446 Fehlerbehandlungsfunktionen 537 Fehlermeldungen protokollieren 449 unterdrücken 367, 448 vermeiden 447 feof()-Funktion 256 Fernzugriff 28 fgetc()-Funktion 254 fgets()-Funktion 255 file control 67 file pointer 250 filegroup()-Funktion 247 fileowner()-Funktion 247 filesize()-Funktion 255 Fließkommazahlen 36 FLOAT 331 flock()-Funktion 263 floor(x) 48 Fluchtsequenzen 38 fopen()-Funktion 250, 251 for-Befehl 130 foreach-Befehl 174 563 564 PHP 4 IT-Tutorial Formatieren %-Zeichen 193 Ausrichtungszeichen 192 Formatzeichen 193 Füllzeichen 192 Genauigkeit 192 Größenangabe 192 Formatzeichen 193 form-Tag 56, 59 Formulare 54 Formularvariablen 152 Fragezeichen-Doppelpunkt-Operator 129 fread()-Funktion 254 Fremdschlüssel 317 identifizieren 326 fseek()-Funktion 258 ftell()-Funktion 259 FTP 512 ftp-Befehl 512 FTP-Beispielsitzung 29 FTP-Client 28 FTP-Funktionen 538 Füllzeichen 192 Funktionen 144 Array-Funktionen 531 aufrufen 144 Ausgabekontrollfunktionen 533 Dateisystemfunktionen 534 Datumsfunktionen 536 Fehlerbehandlungsfunktionen 537 FTP-Funktionen 538 HTTP-Funktionen 539 IMAP-Funktionen 539 Kalenderfunktionen 542 Klassenfunktionen 543 Listenfunktionen 176 Mail-Funktionen 544 Mathematische Funktionen 544 MySQL-Funktionen 546 NNTP-Funktionen 539 Objektfunktionen 543 PHP-Informationsfunktionen 548 PHP-Optionsfunktionen 548 POP3-Funktionen 539 POSIX-Funktionen 550 Programmausführungsfunktionen 550 Protokollfunktionen 537 Rechtschreibfunktionen 552 Regex-Funktionen 551 Sitzungsverwaltungsfunktionen 552 Stringfunktionen 553 URL-Funktionen 557 Variable Funktionen 557 Verschiedene Funktionen 558 Verzeichnisfunktionen 559 Zeichenfunktionen 560 Zeitfunktionen 536 Funktionen, numerische abs(x) 48 ceil(x) 48 floor(x) 48 min(x,y,...) 48 pow(x,n) 48 sqrt(x) 48 strftime(f) 48 fwrite()-Funktion 259 G Ganzzahlen 36 GATEWAY_INTERFACE 92 Genauigkeit 192 General-Header 219 get_object_vars()-Funktion 298 getcwd()-Funktion 270 Get-Methoden 411 Gleichheit 42 Gleichheitszeichen 40 Globale Variablen 152, 153 GNU-zip-Methode 510 GRANT-Befehl 335 Großbuchstaben 197 Größenangabe 192 GROUP BY-Klausel 347 Gruppen 235 Gruppenbesitzer 235, 495 Gültigkeitsbereich 152 H Handle 250 HAVING-Klausel 348 HIDDEN-Attribut 67 HomeSite 23 Home-Verzeichnis 240, 493 Host prüfen 499 Host-Name 93 Webserver 93 HotScripts.com 486 HTML-Controls 54, 57 Auswahlliste 65 Kontrollkästchen 64 Menüs 65 Stichwortverzeichnis Name 57 Optionsfelder 65 Passwortfeld 64 Textbereiche 63 Textfelder 62 verborgene Felder 66 HTML-Formulare entwerfen 54 erstellen 54 Felder anzeigen 61 Struktur 56 Verarbeitungsskript 61 HTML-Seiten Controls 57 mit mehreren Formularen 75 HTML-Sonderzeichen 391 htmlspecialchars()-Funktion 391 HTML-Steuerelemente 54 HTML-Struktur 56 HTTP 527 HTTP Accept:-Header 92 HTTP Accept-Charset:-Header 92 HTTP Accept-Encoding:-Header 92 HTTP Accept-Language:-Header 92 HTTP Connection:-Header 92 HTTP Host:-Header 92 HTTP User-Agent:-Header 92 HTTP_ACCEPT 92 HTTP_ACCEPT_CHARSET 92 HTTP_ACCEPT_ENCODING 92 HTTP_ACCEPT_LANGUAGE 92 HTTP_CONNECTION 92 HTTP_COOKIE_VARS 217 HTTP_HOST 92 HTTP_REFERER 92 HTTP_USER_AGENT 92 HTTP-Anfragemethode 93 HTTP-Funktionen 539 HTTPS 527 imap_fetch_overview()-Funktion 296 imap_headerinfo()-Funktion 298 imap_headers()-Funktion 296 imap_mailboxmsginfo()-Funktion 293 imap_num_ msg()-Funktion 292 imap_open()-Funktion 288 imap_reopen()-Funktion 291 IMAP-Funktionen 294, 539 IMAP-Ordner 290, 308 erstellen 309 löschen 310 umbenennen 309 IMAP-Server 288 INBOX-Ordner 290 Include-Datei 145 Include-Pfad 251 Index 131 Initialisierungsausdruck 131 input-Tag IMAGE-Typ 74 Kontrollkästchen 64 Optionsfeld 65 Passwortfeld 64 Textbereich 63 Textfeld 62 INSERT-Befehl 342 Instanzen 407 Instrumentierung 455 INTEGER 331 Integer 36 Interbase 318 Interim Mail Access Protocol 282, 287 IP-Adresse 92 Iteration 170 iterative Befehle 130 I IDE 23 if-Befehl 122 Verschachtelung 126 IIS 264, 484 image button 74 IMAP 282, 287 installieren 479 imap_body()-Funktion 297 imap_close()-Funktion 292 K Kalenderfunktionen 542 Kandidatenspalten 323 Kardinalitäten 326 Kartesisches Produkt 353 key()-Funktion 177 Kindklasse 408 Klassen 407 definieren 410 Klassenfunktionen 543 J Join-Operator 47 Joins 352 565 566 PHP 4 IT-Tutorial Kommentare 26 Kompilieren 442 Konfigurationsoptionen 389 Konstanten 98 Konstruktor 407 Konstruktoren 412 Konten 493 Kontrollbefehle 118 break 127 case 127 default 127 else 125 elseif 126 if 122 switch 127 Kontrollkästchen 64 Körper 282 Körper der Funktion 148 Kryptographie 527 L Laufzeitfehler 443 LDAP 396 Lebensdauer 153 Left-Join 354 Left-Outer-Join 354 Lightweight Directory Access Protocol 396 line feed 38 Linux 28 Linux Guruz 486 Linux-Server 28 list()-Funktion 178 Listenfunktionen 176 Literale 39 logische Fehler 445 logischer Operator 120 Lokale Variablen 152, 153 ls-Befehl 235 lynx 481 M magic_quotes_gpc-Option 389 magic_quotes_runtime-Option 390 magic_quotes_sybase-Option 390 Magic-Quotes 388 mail()-Funktion 282 Mailbox Infos abfragen 292 öffnen 288 schließen 291 Mail-Funktionen 544 Mailing-Listen für PHP 487 Man-Page 499, 505 Master-Detail-Beziehung 353 Master-Tabelle 353 Mathematische Funktionen 544 max(x,y,...) 48 message headers 282, 297 Metazeichen 504 method-Attribut 56 Methoden überschreiben 416 Microsoft Visual C++ 23 MIME 67, 92 min(x,y,...) 48 mkdir()-Funktion 273 mkdir-Befehl 243 mktime()-Funktion 218 more-Befehl 232 Multiplikation 45 Multipurpose Internet Mail Extensions 67 Mutator-Methoden 411 MySQL 318, 322 Datentypen 331 Fehlersuche 366 installieren 479 konfigurieren 480 mysql_affected_rows()-Funktion 370 mysql_close()-Funktion 368 mysql_connect()-Funktion 366 mysql_errno()-Funktion 366 mysql_error()-Funktion 366 mysql_fetch_array()-Funktion 375, 383 mysql_fetch_field()-Funktion 381 mysql_fetch_row()-Funktion 374, 383 mysql_field_flags()-Funktion 379 mysql_field_len()-Funktion 379 mysql_field_name()-Funktion 378 mysql_field_table()-Funktion 380 mysql_field_type()-Funktion 380 mysql_list_dbs()-Funktion 384 mysql_list_tables()-Funktion 385 mysql_num_fields()-Funktion 378 mysql_num_rows()-Funktion 385 mysql_query()-Funktion 369 MySQL-Datenbanken 364 MySQL-Funktionen 349, 546 MySQL-Library 366 MySQL-Operatoren 349 MySQL-Server 364 MySQL-Website 486 Stichwortverzeichnis N N:N-Beziehung 327 Nachrichten abfragen 295 in Ordner kopieren 310 in Ordner verschieben 311 Körper abfragen 297 löschen 299 Nachrichten-Header 282, 297 Nachrichten-ID 295 Name-Globbing 504 Network News Transfer Protocol 301 Newsgroups für PHP 487 next()-Funktion 176 NNTP 301 NNTP-Funktionen 539 nobody-Konto 245 Normalformen 327 Normalisierung 327 Notepad 22 NUMERIC 331 O Oberverzeichnis 491 Objekt instantiieren 411 Objekt-Array 418 objektbasiert 409 Objekte 407, 408 Objektfunktionen 543 objektorientiert 409 Objektorientierte Programmierung 406 ODBC 395 ODBC-Funktionen 318 Oktalziffern 237 Open Database Connectivity 395 Operanden 45 Operatoren 45 logische 120 Präzedenz 120 relationale 118 Optionsfelder 65 Optionsinhalt 66 option-Tag 66 OR 120 Oracle 318 ORDER BY-Klausel 346 Ordner 239, 491 others 495 Output an Browser senden 86 formatieren 191 P Parser 396 Passwort 526 ändern 498 Passwortfeld 64 PATH 92 pathinfo()-Funktion 271 Pfade 490, 492 absolute 493 manipulieren 271 relative 493 Pfadname 93 PHP E-Mail senden und empfangen 282 installieren 478, 484 Mailing-Listen 487 mit Dateien arbeiten 245 Newsgroups 487 Operatoren 45 Ressourcen 486 Sicherheit 524 Skriptsprachen 84 Webseiten erstellen 428 Websites 486 Websites erstellen 428 PHP Base Library 429 PHP Classes Repository 486 PHP Code Exchange 486 PHP Conference Material 486 PHP Editors 486 PHP Ressource Index 486 PHP Web Ring 486 php.ini 389, 449 PHP-Arrays 166 PHP-Benutzer 487 PHPBuilder 486 PHP-Code einbinden 145 PHP-Datentypen 36, 101 Array 43 dynamische Variablen 99 Konstanten 98 Literale 39 Skalare 43 Strings 38, 188 Variable 39 Zahlen 36 Zeichenketten 38, 188 567 568 PHP 4 IT-Tutorial PHP-Funktionen 144 ASCII-Codes 189 beenden 149 benutzerdefinierte 148 Dateien 230 definieren 147 rekursive 149 Standardargumente 150 Verzeichnisse 230 phpinfo()-Funktion 93, 217 PHP-Informationsfunktionen 548 PHP-Optionsfunktionen 548 PHP-Programme auf Daten zugreifen 84 Codegerüst 22 debuggen 440 erstellen 22 Operationen 25 Steuerbefehle 118 und Datenbanken 316 Wahrheitswerte 118 PHP-Server 28 PHP-Skripts ausführen 28, 30 dokumentieren 26 erstellen 22 Fehler suchen 32, 440 heraufladen 28 URL 31 PHP-Umgebungsvariablen 91 phpinfo()-Funktion 93 PHP-Variablen 86 PHP-Website 486 phpWizard.net 486 pico 22, 502 Pine 232 pine 499, 502 Platzhalterfunktionen 453 Platzhalterroutinen 163 Platzhalterzeichen 504 POP3-Funktionen 539 posix_getgrgid()-Funktion 247 posix_getpwuid()-Funktion 247 POSIX-Funktionen 550 Post-Dekrement 47 Postgresql 318, 394 Post-Inkrement 47 pow(x,n) 48 Prä-Dekrement 47 Prä-Inkrement 47 Präzedenz 120, 121 precedence 47 prev()-Funktion 176 Primärschlüssel 317 identifizieren 325 printf()-Funktion 193 Programmausführungsfunktionen 550 Programme debuggen 451 testen 456 Protokolldatei 449 Protokolle 93 Protokollfunktionen 537 putty 497 pwd-Befehl 241 PWS 484 Q query string 76 QUERY_STRING 92 quotemeta()-Funktion 391 Quotes 388 R radio button 65 rand()-Funktion 144 rawurldecode()-Funktion 392 read 250 Read-Berechtigung 494 readdir()-Funktion 273 REAL 331 Rechtschreibfunktionen 552 recurser()-Funktion 150 Red Hat Linux 478 Referenzen 152 Regex-Funktionen 551 Regression 456 Regressionstest 456 Reguläre Ausdrücke 203 Rekursive Funktionen 149 Relationale Datenbanken 316 Grundbegriffe 316 relationaler Operator 118 relativer Pfad 240 REMOTE_ADDR 92 REMOTE_HOST 93 REMOTE_PORT 93 rename()-Funktion 267 Request for Comment 76 REQUEST_METHOD 93 REQUEST_URI 93 Request-Header 218 Stichwortverzeichnis require-Befehl 145 resultset 373 REVOKE-Befehl 336 rewind()-Funktion 257 RFC 76 Risiken 524 rm-Befehl 234 rmdir()-Funktion 274 rmdir-Befehl 243 root 239 Root-Verzeichnis 240, 491 rows-Attribut 63 RPM-Pakete 478 Rückgabewerte 144 S Schleifenbefehle do while 132 for 130 while 132 Schleifenvariable 131 Schrittausdruck 131 schwache Typisierung 445 scp-Programm 512 SCRIPT_FILENAME 93 SCRIPT_NAME 93 SEEK_CUR 258 SEEK_END 258 SEEK_SET 258 select 65 SELECT-Abfragen 373 SELECT-Befehl 338 select-Tag 65 sequenzielles Array 171 Server 28 Ausführungspfad 92 SERVER_ADMIN 93 SERVER_HOST 93 SERVER_PORT 93 SERVER_PROTOCOL 93 SERVER_SIGNATURE 93 SERVER_SOFTWARE 93 Serverkonfiguration 527 Server-Response-Header 218 setcookie()-Funktion 221 Set-Methoden 411 Shells 496 Sicherheit 524 Authentifizierung 526 Autorisierung 526 Datenbanken 528 Kryptographie 527 Ressourcen 528 Serverkonfiguration 527 Sicherheitsmaßnahmen 526 Simple Mail Transfer Protocol 282 Sitzungsverwaltungsfunktionen 552 Skalare 43 Skript-Kiddies 524 Skripts 30 Pfadname ermitteln 93 URL 93 Skriptsprachen 84, 442 SMALLINT 331 SMTP 282 SMTP-Server 283 Software-Defekt 441 Software-Inspektion 445 Sonderzeichen 76 Sortieren 179 Spalten Ausdrücke 349 identifizieren 323 sprintf()-Funktion 193 SQL 319 Aggregatfunktionen 346 Joins 352 Mustererkennung 341 qualifizierte Namen 353 Stringliterale 340 Vergleichsoperatoren 340 SQL Server 318 SQL-Abfragen 369 sqrt(x) 48 SSH 28, 496 Stammverzeichnis 491 Standardargumente 150 Stapelüberlauf 150 Statische Variable 154 Steuerbefehle 118 Steuerelemente 54 stop()-Funktion 149 str_replace()-Funktion 202 strcmpcase()-Funktion 181 strftime(f) 48 strikte Typisierung 445 Stringfunktionen 553 stringindiziertes Array 167 Strings 38, 188 Anführungszeichen 190 569 570 PHP 4 IT-Tutorial anzeigen 188 beschneiden 196 durchsuchen 200 erstellen 188 Großbuchstaben 197 Länge ermitteln 195 manipulieren 195 Reguläre Ausdrücke 203 Substring ersetzen 202 Substrings 200 Teilstrings 200 Variablen einbetten 88 vergleichen 198 stripslashes()-Funktion 221, 390 strlen()-Funktion 195 strncasecmp()-Funktion 198, 200 strncmp()-Funktion 200 strpos()-Funktion 201 strtolower()-Funktion 197 strtoupper()-Funktion 197 Structured Query Language 319 stub 163 stubs 453 SUBMIT-Schaltfläche 58 mit Bildern 74 substr_replace()-Funktion 202 Substrings 200 Subtraktion 45 superuser 239 switch-Befehl 127 Syntax 25 Syntaxfehler 442 Systemadministrator 494 T Tabellen 316 ändern 334, 342 ermitteln 385 erstellen 333 löschen 334 sperren und entsperren 352 Tabulator 38 tar 511 Tarballs 511 tar-Datei 511 Tausendertrennkomma 36 Tausendertrennpunkt 36 Teile-und-herrsche-Methode 453 Teilstrings 200 Telnet 28, 496 Template-Datei 430 Template-Klassen 428 Templates 428 einsetzen 429 ternärer Operator 129 Testausdruck 131 Testen 440, 456 textarea-Tag 63 Textbereiche 63 Textfelder 62 Textzeilen lesen 255 TIME 332 TIMESTAMP 332 Treiberfunktionen 453, 454 true 118 Typ der Variablen 41 Type-Casting 102 Typumwandlung 101 Typzuweisung 101 U übergeordnete Klasse 408 übergeordnetes Verzeichnis 491 Umgebungsvariablen 91 Unescaping 390 UNIX 28 Grundbegriffe 490 Online-Hilfe 505 UNIX-Befehle 490, 496 eingeben 497 UNIX-Dateinamen 230 UNIX-Dateisystem 230 UNIX-Editoren 232 UNIX-Epoche 109 UNIX-Verzeichnisse 239 UNIX-Zeit 109 unlink()-Funktion 268 Unterverzeichnis 491 Unterverzeichnisse 239, 490 UPDATE-Befehl 343 URI 93 URL Sonderzeichen 76 von Skripts 93 Webseite des Client-Browsers 92 URL encoded 76 URL-codiert 76 urldecode()-Funktion 392 URL-Funktionen 557 Stichwortverzeichnis URLs codieren 392 von PHP-Skripts 31 USENET 487 usort()-Funktion 181 V VARCHAR 332 Variable 39 Namen 40 Variable Funktionen 557 Variablen Formularvariablen 152 globale 152, 153 Gültigkeitsbereich 152 in Strings einbetten 88 lokale 152, 153 PHP-Umgebungsvariablen 91 Referenzen 152 statische 154 verborgene Felder 66 Vererbung 408, 414 Verkettungsoperator 86, 188 Verschachtelung 126 Verschiedene Funktionen 558 Verzeichnisberechtigungen 243 Verzeichnisfunktionen 559 Verzeichnisinhalte anzeigen 500 Verzeichnisse 230, 239, 490, 491 aktuelles 500 anzeigen 242 Basisverzeichnis 493 Berechtigungen 243, 494 Berechtigungen ändern 272, 507 Berechtigungen anzeigen 272 Besitzer festlegen 507 Elternverzeichnis 491 erstellen 243, 273, 503 Inhalte lesen 272 löschen 243, 274, 503 Namen 492 Oberverzeichnis 491 Pfad 492 Root-Verzeichnis 491 Stammverzeichnis 491 übergeordnetes Verzeichnis 491 Unterverzeichnis 491 Wurzelverzeichnis 491 vi 22, 502 Vorrang 47 W Wagenrücklauf 38 Wahrheitswerte 118 Warnungen unterdrücken 367 WeberDev.com 486 Webseite URL 92 Webseiten 428 Webserver 93 Port 93 Version 93 Webserver, sicherer 527 Websites 428 Websites für PHP 486 WHERE-Klausel 339 while-Befehl 132 Whitespace-Zeichen 196 Wiederholungsgruppe 328 Wildcards 504 Windows 28 Windows_98/ME 484 Windows_NT/2000 483 wrap-Attribut 63 write 250 Write-Berechtigung 494 Wurzelverzeichnis 491 X XML 396 XOR 120 xpat-Library 396 Xtemplate 429 Z Zeichenfunktionen 560 Zeichenketten 38, 188 Zeilenvorschub 38 Zeitfunktionen 536 Zend.com 486 zip-Methode 510 Zugriffsmethoden 411 Zugriffszähler 262 Zuweisung 40, 42 Zuweisungsbefehl 40 571