PHP und MySQL für Kids

23,3 mm 6. Auflage anke Johann-Christian H ISBN 978-3-8266-8649-8 Der Bestseller aktualisiert in der 6. Auflage! Alles...

228 downloads 4123 Views 15MB Size Report

This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!

Report copyright / DMCA form



Breite festlegen über Inline-CSS Fehlt noch die Breite (width). Richtig, das könnten wir in der CSS-Datei festlegen. Zu umständlich! Es handelt sich schließlich nur um eine einzige Angabe. Wir lösen das Ganze deshalb kurz und schmerzlos mit Inline-CSS. Bei Inline-CSS werden die CSS-Anweisungen direkt im Tag notiert. Ich habe es dir in Zusammenhang mit text-align (Absatzausrichtung), border (Rahmen), width (Breite) und height (Höhe) schon gezeigt! Eine Inline-CSS-Passage beginnt mit dem Attribut style="...". Die CSS-Regeln werden nun innerhalb der Gänsefüßchen notiert. Inline-CSS ist dann ideal, wenn man kurze Anweisungen festlegen möchte, die sich nicht wiederholen sollen. 58

Eine Umfrage! Wie findest du meine Page? Gehe deshalb in das einschaltende
. Ergänze style="width: 600px;". Insgesamt sieht das Tag also so aus:


Exakte Breite durch die CSS-Regel width: 600px;

Eine Umfrage! Wie findest du meine Page? Du möchtest wissen, wie deine Seite bei den Besuchern ankommt? Erstelle eine Umfrage! Dazu nimmst du einfach eine neue Seite, die wir im Beispiel umfrage.html nennen. Speichere sie ebenfalls unter C:/phpkid/html.

>

Baue die Seite auf dem schon bekannten Grundgerüst auf. Füge ebenfalls den schon verwendeten CSS-Link zur Datei phpkid.css ein! Eine Umfrage mit Radioknöpfen – Der Besucher wählt eine Option aus.

Ein Formular mit Radioknöpfen Und hier zeige ich dir den kompletten Quelltext dieser Umfrage. Denke zuallererst an den Titel. Passe den Bereich zwischen an. Setze eine Überschrift in das Dokument.

59

Kapitel

1

Deine coole Homepage mit HTML Aus Platzgründen habe ich den HTML-Code im Gegensatz zur index.html nicht eingerückt. Es ist schließlich keine Pflicht. Und wenn du doch einrücken willst: Es gibt in PSPad eine clevere Automatik. Mehr dazu gleich …

Umfrage: Wie findest du meine Seite? <meta http-equiv="content-type" content="text/html; charset=utf-8">

Wie findest du meine Page?

echt super
ziemlich gut
geht so



Das eigentliche Formular beginnt mit dem
-Tag. Du musst hier außerdem das Attribut action eintragen. Wir haben es jedoch leer gelassen. (Vergiss nicht, das Formular mit
auch wieder abzuschalten.) Im Formular selber arbeiten wir mit sogenannten Radiobuttons. Dieser Typ wurde tatsächlich von alten Röhrenradios abgeschaut. Drückt man einen Knopf rein, springt der andere heraus. Radiobuttons werden auch als Kontrollkästchen bezeichnet. Radiobuttons werden mit erzeugt. Gib allen zusammengehörigen Buttons den gleichen Namen. Dazu dient das Attribut name. Im Beispiel heißen alle Buttons ergebnis. Der value wiederum ist der Wert, den der Button beim Absenden »mitschickt«. Hier bekommt jeder Button einen eigenen Wert, z. B. 1, 2 und 3. Das dient zum späteren Wiedererkennen. Du als »Formularbesitzer« bekommst schließlich das Name-Werte-Paar zugeschickt, z. B. ergebnis="1". 60

Tipps und Tricks zu PSPad

Submit! Doch wo bleibt die Action? Jedes Formular benötigt zum Abschicken einen Submit-Button. Submit steht für Versenden, übermitteln. Dieser Button sieht im Beispiel so aus:

Der Wert hinter dem Attribut ist übrigens die Beschriftung. Du könntest hier auch »Los!« oder »Klicken auf eigene Gefahr« eintragen. Aber darauf will ich nicht hinaus. Klappe die Erste. Und Action! Wenn du auf den Submit-Button klickst, geht die »Action« los. Es passiert … nichts. Oder fast nichts. Kunststück. Schließlich passiert das, was wir im einleitenden
-Tag hinter action notiert haben. Doch da steht bis jetzt ebenfalls nichts. So ganz stimmt das nicht mit dem »nichts«. Schaue doch einmal in die Adress-Leiste des Browsers. Nach dem Klicken wird hinter die Adresse noch ein Fragezeichen angehangen. Nun steht hier plötzlich z. B. ergebnis=2 (je nachdem, welche Auswahl du getroffen hast). Das ist doch sehr interessant! Mehr können wir an dieser Stelle jedoch nicht machen. Zum Auswerten des Formularinhalts kommen wir allein mit HTML nicht weiter. Hier brauchen wir PHP.

Ein Grund mehr, PHP zu lernen!

Tipps und Tricks zu PSPad PSPad ist ein toller Editor mit vielen genialen Funktionen. Man muss sie nur kennen.

HTML-Quellcode automatisch ausrichten Du möchtest den HTML-Quellcode schön einrücken und formatieren? Damit es ordentlich und übersichtlich aussieht? HTML-Kenner wissen: Zusätzliche Umbrüche und Leerzeichen im Editor werden nicht im Browser dargestellt. Fazit: Gliedere und formatiere den Quellcode so, wie du magst. Per Leerzeichen eingerückt, mit zusätzlichen Leerabsätzen und und und … Keine Lust, das Gliedern von Hand zu erledigen? PSPad bietet dir gleich zwei Tools. Die »sanfte« Variante findest du unter HTML|HTML-CODE NEU

61

Kapitel

1

Deine coole Homepage mit HTML STRUKTURIEREN.

Der Code wird ausgerichtet und automatisch eingerückt. Ab und an musst du noch ein überschüssiges Leerzeichen entfernen, denn in dieser Beziehung ist das Tool noch nicht perfekt. Schärfere Geschütze führt »Tidy« auf, tidy up heißt saubermachen. Wähle z. B. HTML|TIDY|TIDY CLEAN DOCUMENT WRAP oder TIDY CLEAN DOCUMENT NOWRAP und staune! Tidy darfst du aber nur bei reinen HTML-Dateien anwenden. Sobald PHP mit dazukommt, ist dieser »Code-Verschönerer« tabu! Tidy schreibt automatisch eine zusätzliche Meta-Zeile in das Dokument: <meta name="generator" content="HTML Tidy for Windows...

Diese Zeile kannst du löschen.

Automatischen Zeilenumbruch einfügen Du hast den Quellcode automatisch ausgerichtet, aber auf die Umbrüche verzichtet? Die Zeilen sind nun so lang, dass du ständig scrollen musst? Schalte die automatischen Zeilenumbrüche an. Wähle ANSICHT|ZEILENUMBRUCH. Der Umbruch erfolgt jetzt rein optisch für die Anzeige im Editor, wird jedoch nicht mitgespeichert.

Mehr Überblick in der Codeansicht Der Quellcode wird zu klein angezeigt, du kannst ihn nicht lesen? Oder du möchtest alles auf einen Blick sehen? Na dann zoome doch einfach – so wie vom Internetbrowser oder aus der Textverarbeitung bekannt. Halte die Taste [Strg] gedrückt und drehe am Mausrad.

Lesezeichen für mehr Übersicht Genial finde ich auch die Möglichkeit, mit Lesezeichen zu arbeiten. So kannst du dir besonders bei langen Codeabschnitten wichtige Zeilen besser »merken«. Mit [Alt] + [æ] setzt du ein (gelbes) Lesezeichen. Mit [Alt] + [Æ] dagegen kannst du ein einmal gesetztes (gelbes) Lesezeichen wieder löschen. Mit den Tastentricks [Alt] + [¼] bzw. [Alt] + [½] springst du zwischen mehreren Lesezeichen hin und her. Weitere (rote) Lesezeichen gibt es auch. Die setzt du am besten über das Kontextmenü. Nach dem Schließen der Datei werden die Lesezeichen automatisch gelöscht.

Datei vom Windows-Explorer aus öffnen 62

Eines der genialsten Features von PSPad? Das ist für mich eindeutig die Möglichkeit, Dateien direkt vom Windows-Explorer aus laden zu können.

Tipps und Tricks zu PSPad Und zwar über das Kontextmenü. Klicke also mit der rechten Maustaste auf die zu öffnende Datei, beispielsweise die index.html. Wähle den Befehl PSPAD. Schön öffnet sich die entsprechende Datei. Du kannst dabei übrigens auch mehrere Dateien auswählen, beispielsweise den Inhalt des gesamten Ordners. Alle Dateien werden auf einen Schlag in PSPad geladen!

Arbeit mit Verknüpfungen Besonders nützlich ist auch die Arbeit mit Verknüpfungen. So kannst du dir zu den wichtigsten Ordnern Querverweise direkt in PSPad anlegen. Nach Klick springt PSPad sofort zum entsprechenden Ordner im Mini-Explorer. Verknüpfungen heißen in PSPad Links. Sie gehören ins Register mit dem Herz. Und so erstellst du einen Link zum Ordner xampp/htdocs.

>

Achte darauf, dass das Toolfenster sichtbar ist (ANSICHT|TOOLFENSTER). Wechsle ins Favoriten-Register, du erkennst es am Herz.

>

Klicke mit der rechten Maustaste auf das Ordner-Symbol und wähle den Befehl Neuen Link hinzufügen.

>

Das Dialogfenster Neuen Link hinzufügen erscheint. Schaue rechts neben das Feld Pfad / URL und klicke auf die Schaltfläche mit den drei Punkten. Suche den gewünschten Ordner heraus.

>

Nach Klick auf OK ist der neue Link fertig – eine praktische Verknüpfung zum gewünschten Ordner!

Lege dir so viele Verknüpfungen an, wie du brauchst.

Werkzeuge und Suchfunktion Schau dir doch auch die pfiffigen Werkzeuge von PSPad an. Du findest sie im gleichnamigen Menü. Mir hat es neben der schon getesteten Farbauswahl besonders der Code-Explorer angetan. Dieses Tool zeigt dir die Elemente der aktiven Datei in einer baumartigen Struktur. Ausprobieren! Mein zweitliebstes Tool heißt Text-Diff: Aktuelle Datei vergleichen. So kannst du zwei verschiedene Versionen eines Dokuments laden. PSPad hebt die Unterschiede farblich hervor. Auch die ausgefeilte Suchfunktion benötige ich recht häufig, du findest sie im gleichnamigen Menü. Mein Favorit heißt Suchen/Ersetzen in Dateien. Damit kannst du beispielsweise ganze Ordner durchsuchen.

63

Kapitel

1

Deine coole Homepage mit HTML

Schlussbemerkung Uff! Das war eine ganze Menge HTML auf einmal. Gute HTML-Kenntnisse sind jedoch die Voraussetzung für die PHP-Programmierung. Immerhin bist du jetzt schon ein kleiner »HTML-Experte«. Beim Thema HTML haben wir uns für die klassische Version HTML 4 entschieden, wobei ich schon in Richtung HTML 5 vordenke. Wir lassen die strengere und weniger beliebte XHTML-Syntax außen vor. Du möchtest tiefer in (X)HTML (und CSS) einsteigen und die modernsten Versionen und neusten Techniken kennenlernen? Dann empfehle ich dir die wunderbaren Bücher »HTML für Kids« und »CSS für Kids« von meinen Autorenkollegen Robert Agular bzw. David Sigos. Vor allem das letztgenannte Buch bietet dir eine hervorragende Einführung in schickes Seitenlayout. Die Beispieldateien findest du übrigens auch auf der CD zum Buch. Schaue in den Unterordner beispiele/kapitel01.

Zusammenfassung 0 Du kannst mit dem PSPad blitzschnell das Grundgerüst eines HTMLDokuments »zaubern«. Wähle im Menü DATEI den Befehl NEU und doppelklicke auf den entsprechenden Eintrag. 0 Du fügst mit den entsprechenden Tags ganz lässig Überschriften (z. B.

) und Absätze ein. Setze den entsprechenden Text einfach innerhalb der Tags ein. 0 Du weißt, wie du mit dem Tag eine Grafik in deine Homepage einfügst. Ziehe die Grafikdatei einfach aus der Dateiliste des Toolfensters in dein HTML-Dokument. Passe die Attribute und Werte des Tags dann wunschgemäß an. 0 Du kannst mit
    Aufzählungen und mit
      Listen mit HTML erstellen. Du notierst beliebig viele Listen-Einträge zwischen
    1. . 0 Du erstellst Hyperlinks nach dem Muster Text für Hyperlinks. 64

      0 Du schreibst HTML-Tabellen mit den entsprechenden Tags
      , , und .

      Ein paar Fragen … 0 Du erstellst externe CSS-Dateien und steuerst damit das Aussehen deiner Homepage. Das sind Textdateien mit der Endung .css. Hier notierst du mit Hilfe von Attributen, wie die einzelnen Tags formatiert werden sollen. Das Attribut für die Schriftart heißt z. B. font-family. 0 Du arbeitest mit Farben, legst die Breite fest mit Hilfe eines
      -Containers und dem Attribut width. 0 Du weißt, wie du mit den
      -Tags und mit Kontrollkästchen ein Umfrageformular vorbereiten kannst und hast den SUBMITButton ausprobiert.

      Ein paar Fragen … Und jetzt bist du an der Reihe. Beantworte zuerst ein paar Fragen und löse dann ein paar Aufgaben. Viel Spaß und viel Erfolg! 1. Zwischen welchen Tags wird der Kopfbereich des Dokuments notiert? 2. Wie heißt der Farbname für kastanienbraun? Wie lautet der dazugehörige hexadezimale Farbcode und wie die RGB-Syntax? 3. Wie sehen die Kommentarzeichen aus, die in CSS-Dateien verwendet werden? Die Antworten zu den Fragen stecken allesamt auf der CD zum Buch. Schaue im Ordner fragen nach!

      … und ein paar Aufgaben 1. Schaue in die Seite index.html. Füge unter der Aufzählung deiner Hobbys eine Linie ein. Welches Tag verwendest du dafür? 2. Setze ganz oben auf die Seite index.html einen neuen Absatz, und zwar unterhalb von
      . Füge dort einen Verweis auf die zweite Seite umfrage.html ein. Schreibe als Linktext: Zur Umfrage. Setze ganz oben auf der Umfrage-Seite (direkt unter ) ebenfalls einen Absatz ein. Hier soll einen Link zurück verweisen. Dieser soll heißen: Zur Startseite.

      65

      Kapitel

      Deine coole Homepage mit HTML

      1

      Verlinke dein Projekt mit internen Querverweisen.

      3. Prüfe deine Seiten auf Korrektheit. Surfe dazu zum »Prüfdienst« des W3C. (Dahinter stecken die Leute, die HTML erfunden haben.) Surfe zu http://validator.w3.org. Gehe ins Register Validate by File Upload. Klicke auf den Button DURCHSUCHEN. Suche die zu prüfende Datei heraus und klicke auf CHECK. Die Prüfung funktioniert nur richtig, wenn die Datei eine DokumenttypDeklaration besitzt. Du darfst diese erste Zeile mit . So sparen wir uns in Zukunft auch das Schreiben dieser Passage. Die Lösungen für die Aufgaben findest du, falls möglich, stets auf der CD zum Buch, und zwar unter dem Ordner loesungen. Schaue im Beispiel unter loesungen/kapitel01 nach! Und wundere dich nicht – ich habe den HTML-Quellcode mit Tidy automatisch eingerückt.

      66

      2 Installiere deinen eigenen Webserver! In diesem Kapitel wird es richtig spannend! Du installierst deinen eigenen Webserver und testest, ob alles funktioniert. Reiten wir gemeinsam »mit den Apachen durch die Prärie«! In diesem Kapitel lernst du also $ wie du deinen eigenen Webserver mit PHP und MySQL installierst $ wie du testest, ob alles funktioniert An alle, die jetzt Angst bekommen: Du kannst deine Eltern, Tanten und anderweitige potenzielle Geldgeber beruhigen. Der eigene Webserver ist kein schwerer Kasten, den du nun zusätzlich in deine Stube schieben musst. Es kostet nichts extra, dein eigener Rechner genügt. Alles, was du zusätzlich brauchst, liefere ich dir auf CD mit! Doch bevor es losgeht, lass mich etwas ausholen … Wir müssen da so einige Dinge klären!

      67

      Kapitel

      2

      Installiere deinen eigenen Webserver!

      Warum eigentlich ein Webserver? Warum eigentlich ein Webserver? Und was ist das für ein Ding? Fragen über Fragen, die wir vorher unbedingt beantworten müssen.

      Der Webserver ist ein Computer … Zum einen ist der Webserver ein Computer. Es ist der Rechner im Internet, auf dem deine Webseiten liegen. Dieser Webserver steht in einem großen Rechenzentrum. Er wird von deinem Dienstleister für dich bereitgehalten. (Und um ganz offen zu sein: In den meisten Fällen legt dein Dienstleister unzählige weitere Homepages auf diesem Server ab, um Platz zu sparen.)

      Der exklusive Server für die eigene Homepage? Zu teuer! Muss nicht sein!

      Kommen wir gleich auf die für dich wohl wichtigste »Kommunikation« mit dem Webserver zu sprechen, auf das Hochladen. Denn wenn du mit dem Erstellen deiner Homepage fertig bist, lädst du die fertigen Seiten auf den Webserver. Zum Hochladen deiner Seiten brauchst du ein sogenanntes FTPProgramm. Aber keine Sorge, das findest du ebenfalls in diesem Buch. Auch wie man eine Seite auf den Webserver lädt, erkläre ich dir ebenfalls, und zwar weiter hinten. Schaue einfach in den Anhang B! Der Webserver sorgt nun dafür, dass deine Homepage für alle sichtbar ist. Besucher können zu deiner Adresse surfen und sehen deine Seiten. So weit, so gut. Fazit: Ohne Webserver geht es nicht. Denn solange deine Seiten noch auf deinem eigenen Rechner daheim liegen, kann sie niemand außer dir sehen. (Oder außer deinen Freunden, denen du die Seite zeigst.) 68

      Warum eigentlich ein Webserver?

      … und der Webserver ist ein Programm! Zum anderen ist der Webserver aber auch eine Software, ein Programm. Dieses Programm sorgt dafür, dass die Seite weltweit abgerufen werden kann. Dieses Programm läuft nun – du ahnst es schon – auf dem Webserver. Versuche dir einmal vorzustellen, wie das mit dem Surfen funktioniert: Der Webserver-Rechner mit Webserver-Programm steht »irgendwo im Internet«, in irgendeinem Rechenzentrum. Dort liegt deine Homepage, wie eben geklärt. Doch was passiert, wenn ein »Surfer« deine Homepage betrachten möchte? Dann tippt sie oder er erst einmal die entsprechende Webadresse in den Browser ein, z. B. http://www.phpkid.de. Nach Druck auf [Enter] erhält der Webserver (also dieser Computer im Internet) eine Anforderung zum Abruf der Seite. Fachleute sprechen von einem sogenannten HTTP-Request. Der Webserver sucht deine Homepage »aus seinem Speicher heraus« und schickt sie zum Betrachter zurück. Der Betrachter an seinem heimischen PC sieht nun deine Homepage in seinem Browser und kann sie lesen. Dieser Betrachter wird übrigens als Client bezeichnet. Der Client schaut sich die Seiten auf dem Server an. Und schon haben wir die schönste Client-Server-Beziehung.

      Warum unbedingt ein eigener Webserver? Das mit dem Webserver ist ganz schön und gut. Doch wozu brauchst du deinen eigenen Webserver? Reicht denn nicht dieses Teilchen beim Dienstleister im Internet? Leider nicht! Die Programmiersprache PHP ist eine Programmiersprache, die auf dem Webserver läuft. Ohne Webserver funktioniert sie nicht. In Zusammenhang mit PHP spricht man deshalb auch von »WebserverProgrammierung«. Daraus folgt: Wenn du PHP ausprobieren möchtest, bist du auf einen Webserver angewiesen. Eine derartige Programmiersprache wird Server-seitige Programmiersprache genannt. Wie gesagt: PHP läuft nur auf dem Server, auf dem Webserver. Der Browser allein kann mit PHP nichts anfangen. Wenn du versuchst, eine PHP-Seite direkt im Browser aufzurufen, wird das nicht zum gewünschten Ziel führen! 69

      Kapitel

      2

      Installiere deinen eigenen Webserver! Da du PHP sicher auf deinem heimischen Rechner ausprobieren möchtest, musst du wohl oder übel einen eigenen Webserver installieren. Darum also brauchst du den eigenen Webserver.

      Und warum geht das so problemlos bei JavaScript? Kennst du Raffael Voglers tolles, aber leider nicht mehr erhältliches Buch »JavaScript für Kids«? Oder den gleichnamigen Nachfolgetitel von Frank Biet? (JavaScript ist eine weitere Programmiersprache, mit der man Webseiten aufpeppen kann.) Oder hast du dich vielleicht schon anderweitig über JavaScript informiert und einiges ausprobiert? Dann wirst du an dieser Stelle möglicherweise die Stirn runzeln. Moment mal, wirst du protestierend einwerfen. Der Autor spinnt. Von wegen Webserver! Bei JavaScript ist dieser ganze WebserverZirkus doch auch nicht nötig. Du öffnest deine Seite direkt im Browser – es funktioniert. JavaScript wird ausgeführt. Du brauchst keinen Webserver. Warum? Nun, JavaScript läuft direkt im Browser! Fachleute sagen: JavaScript wird vom Client (Client = Browser) interpretiert. Im Klartext: JavaScript wird vom Browser des Betrachters ausgeführt. Der beste Beweis für diese Aussage: Schalte doch einmal JavaScript im Browser ab. Viele Seiten werden jetzt nicht mehr richtig funktionieren. Ganz im Gegensatz zu PHP ist JavaScript also eine Clientseitige Programmiersprache. Fassen wir zusammen: JavaScript wird vom Browser ausgeführt. (Und wenn du im Browser JavaScript abschaltest, geht gar nichts mehr). PHP dagegen wird nur vom Server ausgeführt. Der Browser bekommt stets eine HTML-Seite zugeschickt. Das hat einen großen Vorteil. Für PHP ist es egal, welchen Browser der Betrachter verwendet. PHP funktioniert immer! Das ist natürlich toll. Doch wo Licht ist, gibt es auch viel Schatten. Und da kommen wir schon zum ersten Haken!

      70

      Wie teuer ist die Homepage mit PHP/MySQL?

      Wie teuer ist die Homepage mit PHP/MySQL? Wir sprachen eben darüber, dass an der Sache mit PHP ein Haken ist: PHP funktioniert nur dann, wenn dir dein Dienstleister einen Webserver mit PHP-Unterstützung bietet. Und spätestens an dieser Stelle fängt es an, richtig ärgerlich zu werden. Du führst deine Homepage bisher bei T-Online, AOL oder Freenet? Fehlanzeige! Diese Dienstleister sind ungeeignet. Aber auch preiswerte »WebVisitenkarten« bzw. »Starterangebote« z. B. von 1 und 1, Strato, Domainfactory usw. bieten oft kein PHP an. Auch hier kommst du also nicht weiter. Fazit: Du benötigst einen Dienstleister mit PHP- und MySQL-Unterstützung. Schauen wir uns deshalb einige dieser Dienstleister einmal an. Wir benötigen PHP 5-Unterstützung, um ganz genau zu sein. MySQL sollte mindestens in Version 4.1, besser in Version 5 oder höher vorliegen.

      Kostenlos, aber nicht umsonst: MultiMania Gerade kein Geld übrig? Das macht nichts! Der Anbieter MultiMania bietet unter www.multimania.de eine kostenlose Homepage an. Das alleine ist nichts Besonderes, kostenlose Homepages kannst du an vielen Stellen im Netz bekommen. Interessant ist, dass MultiMania PHP und – täterätäää – auch MySQL-Unterstützung bietet. Sogar das Administrations-Tool phpMyAdmin zum Einrichten von Datenbanken ist schon vorinstalliert. Der Haken: Du musst dich mit Zwangswerbung auf deiner Seite abfinden. Auch an deine E-Mail-Adresse wird Werbung geschickt. Abgesehen davon sind die dort eingerichteten Versionen von MySQL und phpMyAdmin nicht aktuell. Auch die neuen MySQLi-Funktionen von PHP funktionieren zum Zeitpunkt des Schreibens noch nicht. Du kannst dann beim Datenbankteil (vorerst) leider nicht mitmachen. Doch zumindest für den Einstieg in PHP ist MultiMania gut geeignet! Immerhin kannst du zumindest PHP nach Herzenslust ausprobieren, ohne einen Cent zu bezahlen. MultiMania ist ein Angebot der Conversis Hosting GmbH. Früher gehörte der Dienst zu Lycos und hieß »Tripod«. 71

      Kapitel

      2

      Installiere deinen eigenen Webserver!

      Bei MultiMania registrieren Du hast dich für dieses Angebot entschieden? Trage deinen Usernamen und das Passwort ein. Das Passwort musst du aus Sicherheitsgründen zweimal angeben. Klicke auf LOS GEHTS!:

      Bei der Anmeldung legst du Benutzernamen und Passwort fest.

      Dann füllst du das entsprechende Formular aus. Der Mitgliedsname ist besonders wichtig. Dieser Name wird später zum letzten Teil der Adresse deiner Homepage. Du musst aber auch dein Geburtsdatum, dein Geschlecht und eine schon existierende E-Mail-Adresse angeben. Du hast das Anmelde-Formular ausgefüllt und abgeschickt? Dann bekommst du nun eine E-Mail. Erst mit dieser E-Mail wird die Anmeldung perfekt: Aktiviere den Hyperlink aus der E-Mail. Du landest auf einer »Bestätigungs-Seite«. Gib Mitgliedsnamen und Passwort ein. Geschafft! Du bist Mitglied bei MultiMania!

      Login bei MultiMania Zum Einloggen gehst du zu http://www.multimania.de. Nun gibst du Benutzernamen und Passwort ein und klickst auf ANMELDEN. Schon bist du im Verwaltungsbereich. Wie bekommst du deine Homepage auf den MultiMania-Server? Mit FTP! Wie das funktioniert und welche Daten du dafür benötigst, zeige ich dir im Anhang B ganz genau! 72

      Wie teuer ist die Homepage mit PHP/MySQL? Hat alles geklappt? Dann findest du deine Seite im Endeffekt möglicherweise unter dem Namen http://mitglied.lycos.de/mitgliedsname – mit Mitgliedsname ist hier natürlich der von dir selbst gewählte Benutzername gemeint. Auf jeden Fall zeigt dir MultiMania die Adresse der Seite gleich nach dem Einloggen an.

      Kostenlos, aber nicht umsonst: Massive Werbung bei jedem Laden der Seite.

      Für »ältere Kids«: Eigene WWW-Domain Nase voll von der MultiMania-Reklame? Du bist schon ein etwas »größeres Kid«? Oder die »Augenaufschlag-Papi-ist-der-Beste-Taktik« war erfolgreich? Dann lohnt es sich vielleicht, über eine eigene Domäne nachzudenken! Das ist eine Adresse, die z. B. nach dem Muster www.deinName.de aufgebaut wird. Die Vorteile sind groß: Deine Webseite ist unter einer kurzen, von dir selbst wählbaren Adresse zu finden. Gerade hier werben unzählige Dienstleister (sogenannte Webhoster) um deine Gunst. Viele dieser Firmen bieten natürlich auch »Hosting-Pakete« mit PHP-Unterstützung, in aller Regel auch gleich mit MySQL. Leider kostet die PHP/MySQL-Option bei einigen Anbietern ordentlich viel Knete. Nicht so bei der Firma Neue Medien Münnich. Hier gibt es eine Homepage mit eigener Domäne und PHP/MySQL-Unterstützung für recht Taschengeld-freundliche 4,95 Euro pro Monat. Dafür, dass dieser Dienstleister zu den besten gehört, ist das eine gute Leistung! Informiere dich auf der Seite www.all-inkl.com genauer über Preise und Leistungen! Ebenfalls überzeugt bin ich von der Schwarzkünster GbR unter www.schwarzkuenstler.info. Hier gibt es PHP-fähige Webpakete schon ab mageren 1,45 Euro pro Monat. Noch einen Tick günstiger ist die Hosting-Firma MW Internet mit dem Paket Zero Light. Hier gibt es PHP- und MySQL-Unterstützung schon ab 1,40 Euro im Monat. Und das alles ohne Werbung, dafür aber mit 250 Megabyte Speicherplatz: www.mw-internet.de. (Tipp für alle mitlesenden Eltern: Dieser Anbieter ist nicht nur sehr günstig, sondern vergibt auch Geschenkgutscheine! Und zwar in der Rubrik Sonstiges.) Und es geht sogar noch günstiger. Bei http://webnet-service.de bekommst du das günstigste PHP- und MySQL-fähige Paket ab 1,29 pro Monat. 73

      Kapitel

      2

      Installiere deinen eigenen Webserver!

      Neue Medien Münnich und Schwarzkünstler GbR haben einen großen Vorteil: Du kannst deren Angebot vorab kostenlos auf Herz und Nieren prüfen! Bei Neue Medien Münnich dauert dieser Test 7 Tage. Suche einfach nach der Option Jetzt gratis testen. Bei Schwarzkünstler GbR kannst du das Angebot bis zu 10 Tage testen. Suche die Rubrik Testen Sie uns! Mit diesem kostenlosen Testaccount erfährst du zum einen, wie so ein Anbieter tickt. Zum anderen bekommst du eine zeitlich befristete Testhomepage mit PHP und MySQL und damit kannst du schon alles machen. Arbeite das Buch durch und teste die Skripte auf deren Server! Im nächsten Bild siehst du die Begrüßungsseite von Neue Medien Münnich. Die Schaltfläche JETZT GRATIS TESTEN führt zum kostenlosen Testaccount:

      All-inkl.com ist nicht nur einer der günstigsten, sondern auch besten Anbieter.

      Ich habe mich bei den meisten der bisher genannten Dienstleister angemeldet und bin zufrieden. Hallo Eltern, Großeltern, Tanten, Onkels, Verwandte: Vielleicht wäre das ein tolles Weihnachts-, Oster-, Geburtstags-, Tauf-, Konfirmations- bzw. Jugendweihegeschenk? Die eigene Domain für die Tochter, für den Sohn? Du suchst den günstigsten und besten Anbieter? Du möchtest dich vorher über Preise und Leistungen informieren? Surfe zur Seite www.webhostlist.de und informiere dich. Hier ist besonders die Übersicht zu den Top Ten interessant. Du findest hier Geschwindigkeitstests und Erfahrungsberichte von anderen Nutzern. Außerdem führt der Autor auf www.phpkid.de/?billig_hosten eine Liste besonders preiswerter Anbieter, die er mithilfe seiner Leser zusammengetragen hat. 74

      How! Im Reich des »Apachen«

      Lasse dir beim Anmelden von einem Erwachsenen helfen. Denn gerade bei der Registrierung von Domänen-Namen müssen rechtliche Aspekte beachtet werden. Du darfst z. B. keinen geschützten Markennamen für deine Homepage verwenden. Nicht nur bei gewerblicher Nutzung (früh übt sich, hehe!) benötigst du außerdem ein ordentliches Impressum. Das ist ein Bereich, der deine Adresse, Telefonnummer, Steuernummer usw. enthält. Verstöße können dazu führen, dass du teure »Strafgebühren« entrichten musst. Viel mehr dazu, was erlaubt ist und was nicht, verrate ich dir auch in meinem Buch »Bloggen mit WordPress für Kids«.

      How! Im Reich des »Apachen« Nun haben wir uns auf den vorangegangenen Seiten ausführlich über Webserver unterhalten. Es gibt den Webserver als Rechner und natürlich auch das Webserver-Programm. Das Webserver-Programm? Gibt es da nur ein Programm? Und was kostet diese Software? Interessante Fragen! Die gute Nachricht: Webserver-Programme gibt es viele. Zum einen teure wie den sogenannten Internet Information Server von Microsoft. Zum anderen auch kostenlose. Und – du wirst es nicht glauben – am beliebtesten ist der frei verfügbare Webserver namens Apache. How! Und weil der so gut ist und weil der weiter nichts kostet, wird er auf den meisten Webservern im Internet eingesetzt. Es handelt sich dabei um sogenannte Open Source Software. Die Nutzung ist kostenlos. Das Projekt wird von vielen Leuten weiterentwickelt. Es gibt Versionen des »Apachen« für Unix/Linux (das Betriebssystem im Web) und natürlich auch für Windows. Im Klartext: Du kannst dir dieses tolle Programm gemütlich auf deinem heimischen Windows-Rechner installieren.

      Ganz einfach: Webserver selbst installiert! Genau das machen wir. Wir installieren uns den Apache-Webserver auf unserem heimischen Rechner. Damit schaffen wir uns eine tolle Testumgebung. Ideal auch als Trostpflaster, wenn du noch keine Möglichkeit hast, deine Seiten im Internet zu veröffentlichen. 75

      Kapitel

      2

      Installiere deinen eigenen Webserver!

      Nach der herkömmlichen Methode musst du zuerst den ApacheWebserver einzeln installieren. Dann installierst du PHP, zum Schluss noch MySQL und phpMyAdmin. Nach jedem Schritt nimmst du unzählige schwierige Konfigurations-Einstellungen in irgendwelchen Textdateien vor. Wenn man sich da nur ein einziges Mal verschreibt, geht gar nichts mehr! Arghh. Da bekommt man schon am Anfang die ganz große Krise! Unser Buch bleibt krisenfrei! Wir sind pfiffig und nutzen eine spezielle »Installations-Software«. Ich meine das Installationspaket XAMPP von den Apachefriends. Hinter den Apachefriends stecken Kai Oswald Seidler, Carsten Wiedmann und Kay Vogelgesang – die Entwickler dieses tollen Installationspakets. Frisch ans Werk! Installiere deinen eigenen Webserver auf der lokalen Festplatte. Nebenbei werden außerdem gleich PHP, MySQL und das geniale Tool phpMyAdmin eingerichtet. Das Beste: Alle diese »Kostbarkeiten« liegen für dich auf der CD bereit, und zwar unter programme/xampp. Unser Dank geht an Kai, Carsten und Kay, die sich freuen, dass wir ihr XAMPP mit auf unsere CD legen! Die XAMPP-Homepage – übrigens mit einem Hilfe-Forum auch bei Installationsproblemen – findest du unter http://www.apachefriends.org. Kleiner Tipp für Mac-Nutzer: Auch für dich gibt es eine praktische Alternative: MAMP. Du kannst dir das Paket unter www.mamp.info herunterladen, für die Buch-CD war es etwas zu groß. (Sonst hätten die Videos nicht mehr gepasst.) Die Installation von MAMP geht zwar anders vor sich als die von XAMPP. (Sie wird auf www.mamp.info bei Dokumentation erklärt.) Vom Prinzip her arbeitet MAMP jedoch genau wie XAMPP.

      So installierst du XAMPP Und so einfach gelingt die Installation unter Windows. Es funktioniert bei allen Windows-Versionen ab Windows 2000 bis Windows 7. Und zwar sowohl auf der lokalen Festplatte als auch transportabel auf USB-Stick. (Du kannst dir die Schrittfolge auch zeigen lassen. Das entsprechende Video für dieses Kapitel 2 findest du auf der CD im Ordner videos.)

      > 76

      Zuerst achte darauf, dass kein Programm auf deinem Rechner aktiv ist. Das könnte die Installation stören. Gehe nun in den entsprechenden Ordner für XAMPP auf der CD, und zwar in programme/xampp.

      Ganz einfach: Webserver selbst installiert!

      Der Doppelklick startet die Installation.

      >

      Doppelklicke auf die Datei xampp-win32-1.7.3.exe. (Falls du die neuste Version von XAMPP aus dem Internet geladen hast, lautet der Dateiname vielleicht schon xampp-win32-1.7.4.exe.) Es handelt sich um ein selbstauspackendes RAR-Archiv. Die Installation wird automatisch gestartet. Unter Windows Vista und 7 musst du vorher in aller Regel noch eine Sicherheitswarnung bestätigen.

      >

      Das Fenster XAMPP for Windows erscheint. Schaue zum Feld Destination Folder. Steht bei dir auch C:\ in diesem Feld? Super! Hier sollte auf jeden Fall der Laufwerksbuchstabe hin – wobei das Laufwerk auch ein USB-Stick oder eine externe Festplatte sein darf!

      Der Installationspfad (Destination Folder) sollte im Beispiel C:\ lauten.

      >

      Klicke auf INSTALL und gedulde dich – die Dateien werden entpackt! Das kann eine ganze Weile dauern. Im Ergebnis entsteht unter C: bzw. dem von dir gewählten Laufwerk ein Extraordner namens xampp. (Davon kannst du dich gleich nach erfolgreicher Installation überzeugen.)

      77

      Kapitel

      2

      Installiere deinen eigenen Webserver!

      >

      Nun erscheinen nacheinander merkwürdige schwarze Setup-Bildschirme! Dort musst du jeweils den aktiven Buchstaben (y wie yes bzw. n wie no) mit [Enter] bestätigen bzw. ggf. wunschgemäß anpassen, damit der Einrichtungsprozess abgeschlossen werden kann.

      Shortcuts (Verknüpfungen) auf dem Desktop und im Startmenü sind eine feine Sache. Das »y« für »yes« ist voreingestellt. Bestätige mit [Enter]!

      >

      Drücke jetzt immer wieder auf [Enter], um die Fragen zu bestätigen.

      An einer Stelle wirst du gefragt: Should I make a portable XAMPP without drive letters? Wenn du XAMPP nur auf der lokalen Festplatte installierst, könntest du das »n« für no eigentlich belassen. Soll XAMPP jedoch als portable (tragbare) Version auf einem USB-Stick oder einer tragbaren Festplatte eingerichtet werden, darfst du keine drive letters (Laufwerksbuchstaben) zulassen. Aber auch auf der lokalen Festplatte entscheide ich mich dagegen. So kann ich XAMPP immer schnell mal »mitnehmen«. Einfach den XAMPP-Ordner nachträglich auf den USB-Stick kopieren und direkt am Computer von Freunden nutzen! Ist doch super, oder? Folge meiner Empfehlung und tippe an dieser Stelle vorher auf alle Fälle ein »y« für yes. Drücke erst dann auf [Enter].

      >

      78

      Es geht weiter mit dem [Enter], [Enter] um die nächsten beiden Fenster zu bestätigen. Am Schluss landest du bei dieser Auswahl:

      Ganz einfach: Webserver selbst installiert!

      >

      Tippe ruhig erst einmal ein x für exit. Durch Druck auf [Enter] verlässt du das Setup-Skript und kannst dich in Ruhe umsehen.

      Apropos installiert: XAMPP hinterlässt dabei keinerlei Spuren. Keine Einträge in irgendwelchen Registrierdatenbanken, kein nichts! Wenn du XAMPP löschen möchtest, löschst du einfach den kompletten Ordner xampp! (Oder du rufst die Datei uninstall_xampp.bat aus dem xampp-Ordner auf.)

      So startest du XAMPP Du möchtest XAMPP starten? Und damit den Apache Webserver, PHP, MySQL und phpMyAdmin? Kein Problem! Wozu gibt es denn das neue Verknüpfungssymbol auf dem Desktop? Doppelklicke einfach auf das Symbol XAMPP Control Panel bzw. rufe diesen Eintrag über das Startmenü auf. Das geniale XAMPP Control Panel startet. Damit »zündest« du nun den Apache-Webserver und den MySQL-Datenbankserver. Dafür benötigst du nur die beiden oberen START-Schaltflächen. Klicke zuerst auf den obersten START-Knopf, den rechts neben Apache. Warte ein paar Sekunden. Wähle danach den START-Knopf darunter, den rechts neben MySQL.

      Starte den Apache-Webserver (oberstes Modul) und MySQL (zweites Modul von oben) jeweils durch Klick auf die daneben angeordnete START-Schaltfläche. Der Text Running erscheint und die START-Schaltfläche verwandelt sich in eine STOP-Schaltfläche.

      Nach Klick auf die jeweilige START-Schaltfläche meldet sich gegebenenfalls ein warnendes Fenster deiner Firewall. Das geht in Ordnung, Windows passt schließlich auf. Erlaube je nach Firewall den Zugriff bzw. Einsatz des Webservers und von MySQL in deinem lokalen Netz.

      79

      Kapitel

      2

      Installiere deinen eigenen Webserver!

      Nanu, es gibt Probleme mit XAMPP? Achte darauf, dass kein konkurrierendes Webserver-Programm aktiv ist. Unter Windows 2000 bzw. XP Professional könnte das der Internet Information Server sein. Den darfst du nicht aktivieren, da dieser den Apache-Webserver behindern würde. Auch das »Telefonierprogramm« Skype (www.skype.com) musst du ggf. herunterfahren, da es sich oft nicht mit XAMPP bzw. dem lokalen Apache-Webserver verträgt. Es kann auch sein, dass eine lokale Firewall oder ein im Hintergrund arbeitender Virenscanner dafür sorgt, dass XAMPP nicht richtig läuft. Auch die aktuellen Browser präsentieren ggf. alle möglichen Sicherheitsabfragen und Warnungen, ehe sie dich an XAMPP heranlassen. Im Zweifelsfalle gilt: Versuch macht klug! Trenne dich während der Arbeit mit XAMPP unbedingt vom Internet – aus Sicherheitsgründen! Schalte erst dann die Firewall aus bzw. überwinde die Sicherheitsmechanismen deines Browsers.

      So beendest du XAMPP Du möchtest deine PHP-MySQL-XAMPP-Sitzung beenden? Dann musst du beide Module durch Klick auf STOP wieder herunterfahren. Schalte erst MySQL ab und warte einige Sekunden. Stoppe danach den Apache-Webserver. Der grüne Text Running muss an beiden Stellen verschwunden sein. Auch wenn du das Fenster des XAMPP Control Panel schließt – das Steuerpult bleibt aktiv! Es nistet sich ganz rechts unten im Systembereich ein. Du findest es neben der Uhrzeit. Ein Doppelklick auf dieses Symbol zaubert das Steuerpult hervor.

      Du möchtest nun auch das XAMPP-Steuerpult beenden? Klicke im XAMPP Control Panel auf die Schaltfläche EXIT. Du findest sie als unterste Schaltfläche in der rechten »Reihe«. Erst jetzt ist XAMPP wirklich inaktiv.

      80

      Nur noch etwas Handarbeit … und fertig!

      Wo liegen die Dateien von XAMPP? XAMPP hat nun alles installiert, Webserver, PHP, MySQL, phpMyAdmin usw. Fantastisch. Doch wo liegen die ganzen »Module«? XAMPP legt den Apache-Webserver, PHP, MySQL, phpMyAdmin usw. in Unterordnern unter C:\xampp ab. 0 Den Apache-Webserver findest du unter C:\xampp\apache 0 Die PHP-Dateien liegen unter C:\xampp\php 0 MySQL findest du z. B. unter C:\xampp\mysql Auch andere Module wie Perl, Mercury Mail Server und der FileZilla-FTPServer werden installiert. Diese Komponenten benötigen wir jedoch nicht, du kannst sie ignorieren. Was für uns wichtig ist: Für deine eigenen Daten hat XAMPP den Ordner htdocs eingerichtet. Du findest dieses Verzeichnis unter C:\xampp\htdocs. Merke dir diesen Ordner gut! Noch einmal langsam und zum Mitschreiben: Alles, was du jetzt PHP-mäßig anstellen wirst, legst du ab unter C:\xampp\htdocs!

      Nur noch etwas Handarbeit … und fertig! Hat alles perfekt funktioniert? Probiere es aus! Teste, ob dein lokaler Webserver funktioniert. Die Startseite für deinen lokalen Webserver findest du stets unter der Adresse http://127.0.0.1. Tippe diese Adresse einfach in deinen Browser ein. Falls dir diese Nummer zu kryptisch ist, kannst du dir auch die Adresse http://localhost merken. Last but not least gibt es noch eine dritte Methode. Kennst du den Namen deines PCs? Meiner heißt z. B. Monarch. Dann tippe ich http://monarch und drücke [Enter]. Auch das geht also, es führen tatsächlich drei Wege zum gleichen Ziel!

      81

      Kapitel

      2

      Installiere deinen eigenen Webserver! Wir einigen uns am besten auf http://localhost! Tippe diese Adresse ein und drücke [Enter]. Je nach Version von XAMPP siehst du – nach Klick auf den Link Deutsch – diese oder eine ähnliche Seite:

      XAMPP begrüßt dich mit einer Begrüßungs-Seite.

      Dahinter verbirgt sich aber nichts weiter als eine Status- und Demoseite, die die Macher von XAMPP für dich vorinstalliert haben. Du wunderst dich, warum in diesem Ordner schon so viel drin steckt? Das sind vor allem Demo- und Beispielprogramme. Du kannst diese Dateien und Ordner bedenkenlos löschen. Du traust dich nicht, das alles zu löschen? Dann habe ich einen anderen Tipp: Benenne den Ordner htdocs um in htdocs_alt. Erstelle nun unterhalb von xampp einen neuen, leeren Ordner namens htdocs. Auch das funktioniert! (Wenn du dich nicht beim Ordnernamen verschrieben hast!) Nach dem Druck auf [Enter] will sich dein PC stets ins Internet »einwählen«? Versuche eine Option wie »Offline bleiben«. Wähle z. B. den Befehl DATEI|OFFLINEBETRIEB. Probiere es dann erneut.

      82

      Testen: phpinfo() auf localhost

      Testen: phpinfo() auf localhost Wunderbar, jetzt hast du deinen eigenen Webserver. Teste doch einmal, ob alles funktioniert. Zuerst prüfen wir, ob unsere eigenen HTML-Seiten angezeigt werden.

      Zuerst eine HTML-Seite … Erinnerst du dich an deinen Ordner html, den du unter C:\phpkid eingerichtet hattest? Ich meine unser kleines Projekt aus Kapitel 1. Das kommt uns wie gerufen, denn hier gibt es eine Datei index.html. Das ganze Projekt binden wir einfach zur Probe in unseren Webserver ein!

      >

      Kopiere diesen Ordner html komplett nach C:\xampp\htdocs. Der neue Pfad muss also lauten C:\xampp\htdocs\html!

      >

      Rufe diese Seite nun auf. Dazu tippst du http://localhost/html. Wenn alles klappt, wird die im ersten Kapitel erstellte Seite index.html aufgerufen! Es klappt: Aufgerufen wird die index.html aus dem Ordner html.

      Aber auch hier sind die Vorteile eines Webservers noch nicht ersichtlich. Es macht keinen großen Unterschied, ob du die Datei direkt von PSPad bzw. dem Windows Explorer aus startest, oder über den Webserver »abrufst«.

      Die »Magie« der index.html Du könntest diese Datei index.html auch direkt durch Doppelklick starten. Da es eine reine HTML-Seite ist, macht das keinen Unterschied – zumindest vom Erscheinungsbild her. Bemerkst du etwas? Wenn du sie über http://localhost/html öffnest, dauert das ein wenig länger. 83

      Kapitel

      2

      Installiere deinen eigenen Webserver! Schließlich muss der Webserver die Anfrage (HTTP-Request) erst bearbeiten und die passende Seite zurück zum Browser schicken. Apropos http://localhost/html! Gezeigt wird die index.html, obwohl du diesen Namen überhaupt nicht getippt hattest? Der Engländer würde jetzt sagen How come, was ist los? Nun, eine index.html wird immer dann angezeigt, wenn du den entsprechenden Ordnernamen eintippst. Wenn keine index.html vorhanden ist, reicht oft auch eine index.htm oder sogar eine index.php als Startdatei. Das ist ziemlich praktisch. So musst du nicht erst umständlich http://localhost/html/index.html tippen, da http://localhost/html genügt!

      … und nun ein PHP-Test Und nun folgt ein kleiner PHP-Test! Dafür schreibst du deine erste PHPDatei. Diese nennen wir info.php und legen sie in den Ordner C:\xampp\htdocs. Richtig, diesmal direkt in den Stammordner deines »lokalen Webs«. Wie geht das?

      > > >

      Starte PSPad. Wähle nun im Menü DATEI den Befehl NEU. Bleibe im voreingestellten Register Leere Datei erstellen und doppelklicke auf PHP. Eine Datei wird erzeugt, wirklich leer ist sie allerdings nicht. Du findest hier schon die PHP-Tags vor. Klicke in die leere Zeile zwischen

      >

      Notiere folgenden Befehl: phpinfo();

      >

      84

      Vergiss nicht, die Datei zu speichern. Zur Erinnerung: Wir wollten sie info.php nennen (Endung .php!).

      Testen: phpinfo() auf localhost

      Achte unbedingt darauf, die Datei in XAMPP zu speichern. Und zwar im Ordner xampp, Unterordner htdocs. Denn nur wenn sie in htdocs (oder einem Unterordner von htdocs) liegt, wird PHP ausgeführt.

      >

      Rufe die Seite nun folgendermaßen auf. Tippe in den Browser: http://localhost/info.php

      und bestätige mit [Enter]. Wenn alles geklappt hat, siehst du solch ein oder ein ähnliches Bild: Es funktioniert: PHP ist auf deinem System korrekt installiert.

      Das ist zum einen der Beweis, dass PHP funktioniert. Zum anderen gibt dir die Funktion umfangreiche Auskünfte. Welche PHP-Version ist auf deinem System installiert? Wir arbeiten mit PHP 5.3.1. Welches Betriebssystem wird verwendet? Welche Einstellungen wurden vorgenommen? Für den Kenner ist diese Anzeige eine wahre Fundgrube. Für uns Grund, einen Indianer-Freudentanz aufzuführen!

      85

      Kapitel

      2

      Installiere deinen eigenen Webserver!

      Du versuchst, die info.php direkt aufzurufen? Das wird misslingen. Entweder du siehst den Quelltext. Oder Windows beschwert sich, weil es mit diesem Dateityp nichts anfangen kann. Spätestens an diesem Beispiel merkst du, wie wichtig der Webserver ist. Erst der Webserver sorgt dafür, dass die PHP-Anweisung – hier die Funktion phpinfo() – ausgeführt wird. Wichtig zu wissen: Der PHP-Befehl wird ausgeführt, aber nicht angezeigt. Der Browser erhält reinen HTML-Code zugeschickt. Wenn du’s nicht glaubst, mache den Test: Tippe noch einmal die Adresse http://localhost/info.php. Wähle nun im Browser je nach Version den Befehl SEITE|QUELLCODE ANZEIGEN, ANSICHT|QUELLTEXT bzw. SEITENQUELLTEXT ANZEIGEN. Du wirst keine einzige Zeile PHP finden! Was du siehst, ist der HTML-Quellcode, der durch die phpinfo() entstanden ist!

      Noch ein Test: Funktioniert phpMyAdmin? Hattest du auf der ursprünglichen XAMPP-Begrüßungsseite den Punkt TOOLS entdeckt? Dort steckt auch phpMyAdmin, unser Datenbankverwaltungsprogramm. Wir brauchen es zwar erst später – trotzdem solltest du jetzt schon testen, ob der Zugriff funktioniert! Ich empfehle dir, dieses Tool nicht über den Link, sondern stets direkt aufzurufen. Dazu tippst du in die Adresse-Zeile des Browsers: http://localhost/phpmyadmin Normalerweise startet phpMyAdmin ohne Kommentar. Bei dir erscheint eine Dialogbox zur Eingabe von Benutzernamen und Passwort? Dann tippst du als Benutzernamen einfach root, das Passwort-Feld jedoch lässt du frei. Das sind übrigens die gleichen Daten, die du später auch für MySQL verwenden wirst: root und nichts.

      Schlussbemerkung Viel Theorie, ich weiß. Aber das war wichtig. Außerdem weißt du jetzt, wo du Platz für deine PHP-Homepage bekommst. Und du bist stolzer Besitzer eines eigenen lokalen Webservers. Und das ist doch schon allerhand!

      86

      XAMPP gibt es übrigens auch für Mac und für Linux. Dort ist die Vorgehensweise leider etwas anders. Lies dir die entsprechenden Anleitungen auf www.apachefriends.de durch. Du bist Macianer und kommst mit XAMPP nicht zurecht? Dann solltest du das schon erwähnte MAMP ausprobieren. Dieses Tool bekommst du unter www.mamp.info.

      Zusammenfassung

      Zusammenfassung 0 Du weißt jetzt, wozu ein Webserver dient. Hier liegen die Seiten. Der Betrachter kann sie über Eintippen der entsprechenden Webadresse anfordern. Diese Anforderung heißt »HTTP-Request«. 0 Du kennst einige Dienstleister mit PHP/MySQL-Unterstützung. Du kennst z. B. MultiMania (vormals Tripod bei Lycos), einen werbefinanzierten Anbieter einer kostenlosen PHP/MySQL-Homepage. 0 Du weißt, wie das beste Webserver-Programm heißt – Apache Webserver. Es ist ein frei verfügbares Programm. 0 Wir haben den Apachen selber auf unserem Rechner eingerichtet. Dabei half uns ein Installations-Tool namens XAMPP. Angenehmer Nebeneffekt: Jetzt laufen auch PHP und MySQL ganz automatisch auf deinem heimischen Rechner. 0 Du weißt, wie du dein eigenes Web aufrufst. Tippe http://localhost in die Adresse-Zeile des Browser. Drücke [Enter]. 0 Du hast am Beispiel der Funktion phpinfo() herausgefunden, dass eine PHP-Datei nur beim Aufruf über den Webserver richtig angezeigt wird. Grund: PHP wird vom Webserver ausgeführt. Der Browser bekommt jedoch reinen HTML-Code zugeschickt.

      Ein paar Fragen … 1. Kannst du bei Anbietern wie T-Online oder AOL deine Homepage mit PHP/MySQL installieren? 2. Wie heißt das Programm, welches dir den Apache-Webserver, PHP, MySQL und noch viel mehr auf deinem heimischen Computer einrichtet? 3. Unter welchem Pfad legst du deine PHP-Dateien ab, wenn du den Apache-Webserver mit XAMPP installierst hast? 4. Welche Endung hat eine PHP-Datei? 5. Wozu brauchst du einen eigenen Webserver?

      87

      Kapitel

      2

      Installiere deinen eigenen Webserver!

      … und eine Aufgabe Diese Aufgabe wendet sich an Windows-Nutzer, die mit PSPad arbeiten. Und damit es nicht so schwer wird, beginne ich mit einem Trick. Du möchtest noch schneller ein HTML-Grundgerüst in PSPad einfügen? Klicke auf den Pfeil rechts neben der NEU-Schaltfläche (Sie heißt eigentlich NEUE DATEI ERSTELLEN) und wähle HTML. Oder wähle DATEI|NEU und bleibe im Register Leere Datei erstellen. Doppelklicke auf HTML. Auch jetzt wird ein HTML-Dokument im Standard 4.01 Transitional eingefügt – sogar mit verkürzter DTD. (Allerdings ohne lang="de" und utf-8.) Und nun kommt endlich deine Aufgabe: Finde heraus, welche Vorlage sich dahinter verbirgt. Passe diese Vorlage an deine Wünsche an. Sorge also dafür, dass unser perfektes HTML-Grundgerüst von Seite 32 eingebunden wird. Meinetwegen mit verkürzter DTD und gerne auch ohne Einrückung der Zeilen. (Damit die Einrückung von PHP besser zur Geltung kommt.) Aber bitte dafür wieder mit CSS-Link von Seite 50.

      88

      3 Hallo echo – »Hallo Welt« Die mühevollen Vorarbeiten sind geschafft! Der Webserver läuft. Höchste Zeit, mit dem Programmieren richtig loszulegen. In diesem Kapitel lernst du: $ wie du mit PHP Daten ausgibst $ wie du mit Variablen arbeitest, den »variablen Platzhaltern« $ wie du Zeilenumbrüche setzt $ wie du Sonderzeichen »maskierst« $ wie du Fehler erkennst und vermeidest

      89

      Kapitel

      3

      Hallo echo – »Hallo Welt«

      Daten ausgeben mit echo Gleich zu Anfang stelle ich die wichtigste Sprachanweisung von PHP vor – echo. Und ich verspreche dir, es ist eine Anweisung »mit Nachhall«. Doch vorher klären wir, wie PHP-Dokumente überhaupt aufgebaut sind und wo du die PHP-Anweisungen notierst.

      Wie sind PHP-Dokumente aufgebaut? Die PHP-Notation ist unkompliziert. Was musst du wissen? Nicht viel! PHP-Dokumente sind eigentlich nichts weiter als HTML-Dokumente. Sie besitzen die Endung .php. Sie enthalten zusätzlich Abschnitte mit PHPCode. Diese PHP-Abschnitte notierst du ganz einfach irgendwo innerhalb des HTML-Quelltexts. Wo, ist im Prinzip fast egal. Hauptsache du machst deutlich, dass es sich um einen PHP-Abschnitt handelt.

      Wie kennzeichne ich meinen PHP-Code? Ganz einfach. Zu Beginn des PHP-Teils notierst du Folgendes:
      Am Schluss des PHP-Abschnitts schreibst du dagegen: ?>

      Das war’s schon. Das ist die Form, die ich dir empfehle. Du könntest aber auch schreiben:
      und ?>

      wobei du dann die Kurzform gewählt hättest. (Ich zeige es dir deshalb, damit du dich nicht wunderst, wenn dir diese Schreibweise bei anderen Skripten begegnet.) Wir bleiben bei der Langform, da sie zu 100% dem Standard entspricht. Warum ist die Kennzeichnung des PHP-Abschnitts eigentlich so wichtig? 90

      Daten ausgeben mit echo

      Erst durch diese Kennzeichnung »weiß« der Webserver, dass es sich um PHP-Abschnitte handelt. Denn diese Abschnitte werden nicht einfach so an den Browser geschickt. Sie werden vorher interpretiert, ausgeführt. Vergiss nicht: Der Benutzer bekommt nur eine HTML-Seite mit HTMLAnweisungen »zugeschickt«. Den PHP-Code bekommt er nie zu Gesicht!

      »Hallo Welt« – dein erstes Skript Unter Programmierern ist es eine hübsche Tradition, die »Welt« am Anfang mit einem kräftigen »Hallo« zu begrüßen. Schreibe ein Skript, welches den Text »Hallo Welt« ausgibt. Das Dokument soll hallo.php heißen und in unserem htdocs-Ordner unter C:\xampp abgelegt werden.

      >

      Erzeuge mit deinem bevorzugten Code-Editor (PSPad, Aptana Studio usw.) eine neue, leere HTML-Datei. In PSPad wählst du DATEI|NEU, gehst ins Register Neue Datei aus Vorlage erstellen und doppelklickst auf die Vorlage HTML 4.01 Transitional. (Falls du die Aufgabe von Seite 88 gelöst hast, gibt es auch einen schnelleren Weg.)

      >

      Nun erscheint das schon bekannte Grundgerüst einer HTML-Datei. Bereite zwischen einen PHP-Bereich vor. Kleide die PHP-Tags außerdem durch

      ein. Damit sorgst du dafür, dass der Text innerhalb des obligatorischen HTML-Blockelements notiert wird. Der Bereich innerhalb von sieht dann so aus:



      >

      Notiere zwischen den PHP-Tags jetzt folgende PHP-Zeile: echo "Hallo Welt!";

      >

      Nicht vergessen: Speichere dein Dokument. Wähle den Namen hallo.php. Denke an den korrekten Speicherpfad: xampp/htdocs!

      PSPad bietet dir beim Speichern den Dateityp HTML Document an. Doch wir brauchen PHP. Stelle daher im Listenfeld bei Dateityp vorher Alle Dateien (*.*) ein. Notiere dann den Dateinamen im Dateiname-Feld. 91

      Kapitel

      3

      Hallo echo – »Hallo Welt«

      Die Sprachanweisung echo sorgt dafür, dass die entsprechenden Daten ausgegeben werden. Die auszugebenden Daten notierst du innerhalb von Gänsefüßchen. Die Zeile wird am Ende durch ein Semikolon abgeschlossen.

      Quelltext für die hallo.php So sieht das gesamte Beispiel aus. Ich habe den Titel in der vierten Zeile angepasst und außerdem eine beschreibende Überschrift eingefügt. Aber Hallo – der eigentliche PHP-Teil ist nur ganz kurz: Hallo-Welt-Skript <meta http-equiv="content-type" content="text/html; charset=utf-8">

      Hallo-Welt-Skript



      Du möchtest auch mit einer externen CSS-Datei arbeiten? Damit die sechste Zeile im Quelltext Sinn macht? Dann vergiss nicht, dass du die Datei phpkid.css ebenfalls in den Ordner htdocs kopieren musst. Sonst werden deine »Stile« nicht angezeigt!

      Teste dein Dokument mit dem Webserver Sicher bist du neugierig, ob alles funktioniert. Rufe dein Dokument im Webserver auf. Da du es direkt im Wurzelordner htdocs gespeichert hast, ist das ganz einfach. Tippe http://localhost/hallo.php und drücke auf [Enter]. Wenn alles geklappt hat, müsstest du folgendes Bild sehen: 92

      Daten ausgeben mit echo

      Der PHP-Code wird interpretiert: Der Browser gibt den Hallo Welt-Text aus.

      Hat’s funktioniert? Herzlichen Glückwunsch! Huch, bei dir gibt es eine Fehlermeldung? Oder der Text wird nicht angezeigt? Beachte, dass die Anzeige nur funktioniert, wenn du die Seite über den Webserver startest. Das direkte Aufrufen mit Doppelklick führt dazu, dass der PHP-Abschnitt nicht interpretiert wird. Kunststück, wenn du den Webserver umgehst? Weitere Fehlermöglichkeiten bespreche ich ein paar Seiten weiter hinten im Abschnitt Fehlermeldung. Also, cool bleiben!

      PSPad: Raffinierte Farbhervorhebung Mal was anderes: Ist dir eigentlich die interessante farbliche Darstellung in PSPad aufgefallen? Sowohl die HTML- als auch die PHP-Befehle werden durch unterschiedliche Farben optisch gut hervorgehoben. Dafür sorgt der HTML multihighlighter – eine raffinierte Farbhervorhebungsautomatik.

      Der HTML Multihighlighter ist automatisch aktiv. Du erkennst es an der entsprechenden Anzeige in der Statuszeile.

      Stelle zur Probe einmal einen anderen Highlighter ein. Dazu klickst du einfach auf den Text HTML multihighlighter aus der Statuszeile. Nun erscheint

      93

      Kapitel

      3

      Hallo echo – »Hallo Welt« ein Dialogfenster und zeigt dir eine Auswahl vieler anderer Farbhervorhebungs-Module. Probiere doch einmal die Einstellung »HTML«. So wird nur der HTML-Code farblich hervorgehoben. Du kannst den Fokus aber auch ausschließlich auf PHP legen. Du musst den Highlighter aber normalerweise nicht von Hand wählen. PSPad erkennt den Dateityp automatisch anhand der Endung einer Datei. Rufe doch einmal die phpkid.css auf und prüfe, welcher Highlighter gewählt ist. Richtig: Cascading Style Sheets.

      Variablen: Mein rechter, rechter Platz ist leer Die Welt haben wir schon begrüßt. Wunderbar! Richten wir unser Augenmerk deshalb auf die nächste Umgebung: Auf Katja, Leon, Peer, Manja und auf wen auch immer. Schmettere einem dieser lieben Menschen ebenfalls einen freundlichen Gruß entgegen. Bleiben wir im Beispiel einfach bei Katja. Begrüße sie mit PHP! Erstelle ein neues PHP-Dokument. Nenne es katja.php und lege es wieder in den Ordner htdocs. Als Titel und Überschrift schlage ich Persönliche Begrüßung mit Variablen vor. Doch was sind Variablen?

      Was sind Variablen? Variablen sind Platzhalter! Es sind Speicherstellen im Hauptspeicher des Rechners. Stell dir eine Variable einfach als Behältnis vor. Es ist ein Behältnis, welches dir für die Dauer der Programmausführung zur Verfügung steht. Was du hineinpackst, bleibt dir überlassen. Du kannst den Inhalt der Variablen beliebig ändern und erweitern. Auch den Namen des »Behälters« selbst kannst du frei wählen. Na ja, fast frei zumindest.

      94

      Die Namen von Variablen beginnen immer mit einem Dollarzeichen. Verwende keine Umlaute, Leer- oder Sonderzeichen! So wäre $eimer ein erlaubter Variablenname, nicht aber $meine schüssel. Der Unterstrich (_) ist jedoch gestattet. Er dient oft als Ersatz für das verbotene Leerzeichen. So wäre $dein_name eine wunderbare Variable. Selbst kurze Variablen wie $i oder $k kannst du verwenden. Weiterhin gilt: Groß- und Kleinschreibung werden unterschieden. So sind $vorname und $Vorname zwei unterschiedliche Variablen. (Damit solche Probleme gar nicht erst auftreten, rate ich zu genereller Kleinschreibung!)

      Variablen: Mein rechter, rechter Platz ist leer

      Beachte zusätzlich: Einige in PHP reservierte Wörter dürfen nicht als Variablenname verwendet werden. Das sind Wörter wie while, if, switch, for usw. usf. Außerdem ganz wichtig: Beginne Variablennamen nie mit einer Zahl. Nicht funktionieren wird ein Name wie $68name. (In der Variablen selbst sind jedoch Ziffern gestattet.)

      Der Platzhalter $vorname Für unser »Katja-Beispiel« habe ich mir die Variable $vorname ausgedacht. Dieser muss ich nur noch einen Wert zuweisen. Im Beispiel soll es der Name Katja sein. Wie mache ich das? So: $vorname = "Katja";

      Die Variable selbst steht links. Danach folgt ein sogenannter Zuweisungsoperator. Dann notiere ich den eigentlichen Wert des »VariablenPlatzhalters«. Und dieser befindet sich rechts, getreu dem Motto »Mein rechter, rechter Platz ist leer«. Warum notiere ich den Namen Katja in Gänsefüßchen? Weil es sich um Text handelt. In diesem Zusammenhang spricht man von einem sogenannten String. Strings werden stets im Gänsefüßchen notiert. Bei Zahlen dagegen brauchst du keine Gänsefüßchen zu setzen. Klar? Der gesamte Quelltext des PHP-Bereichs sieht so aus.

      Denke an das Semikolon am Zeilenende. Jede Zeile wird in PHP in der Regel durch ein Semikolon abgeschlossen!

      Hallo Katja! So sieht mein Beispiel aus.

      95

      Kapitel

      3

      Hallo echo – »Hallo Welt« Das Beispiel findest du auf der CD im Ordner kapitel03. Schaue in die Datei katja1.php.

      Wie funktioniert das Skript? Ganz einfach! In der ersten Zeile taucht die Variable $vorname das erste Mal auf. Du weist ihr gleich den Wert Katja zu. Doch warum steht Katja in Gänsefüßchen? Bei Katja handelt es sich um Text. Und Text entspricht dem sogenannten Datentyp String. Das muss durch Gänsefüßchen verdeutlicht werden, denn Strings müssen stets in Gänsefüßchen stehen. Neben dem Datentyp String kennt PHP noch den Datentyp Integer. Dieser Datentyp steht für eine normale Ganzzahl wie 5 oder 9834. Als weiteren Datentyp gibt es in PHP den Datentyp Float (Kommazahl). Später lernst du den Typ Boolean für Wahrheitswerte wie true oder false kennen. Wie du siehst, sind es alles in allem nur wenige Datentypen. Da PHP die Datentypen automatisch erkennt, musst du dich darum nicht weiter kümmern. (Der Fachmann sagt: Die Variablen sind nicht typisiert.) In Zeile 1 hast du die Variable also initialisiert, wie der Profi sagen würde. Nicht vergessen: Die Zeile wird dann durch ein Semikolon abgeschlossen. Noch einmal im Klartext: Wir haben uns unseren eigenen »Behälter« namens $vorname eingerichtet und dort den Text Katja hineingetan. Nun zur zweiten Zeile. Hier sorgt die echo-Anweisung nun dafür, dass etwas ausgegeben wird. Das »Ausgabegut« steht übrigens wieder in Gänsefüßchen. Auch hier handelt es sich um Text. Richtig erkannt: Es wird ein String ausgegeben! Nach dem Wort Hallo und einem Leerzeichen hat unsere Variable $vorname ihren großen Auftritt. Nun wird der Wert ausgegeben, der in der Variablen gespeichert ist. Dieser lautet Katja. Fazit: Im Browser erscheint der Text Hallo Katja!

      Ausgabe verschönern mit HTML-Tags Die Ausgabe gefällt dir noch nicht? Verschönere sie einfach! Du kannst im Zusammenhang mit echo ganz problemlos HTML-Tags einsetzen. Die »Version 2« des Katja-Beispiels sieht folgendermaßen aus: 96

      Wie Pech und Schwefel: Strings verketten $vorname!"; ?>

      Wie du siehst, kannst du ganz problemlos HTML-Tags in deinen AusgabeString einfügen. Hier habe ich zusätzlich mit dem Tag-Paar für bold (fett) gearbeitet. Passe dein Beispiel dementsprechend an. Speichere und aktualisiere die Ansicht im Browser. Dazu drückst du die Funktionstaste [F5]. Das geht natürlich nur, wenn du die Seite http://localhost/katja.php noch aufgerufen hast.

      Der Beweis: Ansicht im Browser und im HTMLQuelltext.

      Wie du in der Abbildung siehst, werden die Tags korrekt ausgegeben. Zum Vergleich habe ich den Quelltext der »Webseite« aufgerufen. Das solltest du ruhig ebenfalls einmal probieren. Wähle dazu im Menü ANSICHT den Befehl QUELLTEXT. Vergewissere dich! Im Quelltext der »Webseite« ist tatsächlich kein PHPCode mehr enthalten. Denn schließlich sorgt der Webserver dafür, dass PHP interpretiert, ausgeführt wird. Und der Webserver schickt halt den HTML-Code Hallo Katja! an den Browser. Das Beispiel findest du auch auf der CD, und zwar wieder im Ordner kapitel03. Der Dateiname dieser Version lautet katja2.php.

      Wie Pech und Schwefel: Strings verketten PHP ist einfach! Unter dem Motto »Freiheit für Kettenhunde« reden wir nun über die »Hundeleine« in PHP. Ich meine den Verkettungsoperator Punkt. Doch eigentlich brauchen wir über diesen Punkt gar nicht so viele Worte zu

      97

      Kapitel

      3

      Hallo echo – »Hallo Welt« verlieren. Der große Vorteil: Strings und Variablen müssen nicht verkettet werden. Zumindest gilt das in den meisten Fällen. Doch was ist mit Verketten überhaupt gemeint? Unter Verketten versteht man das Verbinden von zwei oder mehr Zeichenketten. Dazu wird normalerweise ein sogenannter Verkettungsoperator verwendet. Als Verkettungsoperator dient in PHP der Punkt. Schaue dir doch noch einmal unser Beispiel von eben an: $vorname!"; ?>

      Du setzt die Variable einfach so mir nichts dir nichts in die Zeichenkette hinein. Das spart viel Schreibarbeit und scheint für uns ganz selbstverständlich zu sein. Ist es auch, denn diese raffinierte Technik ist eine Spezialität von PHP. Bei herkömmlichen Programmiersprachen gilt jedoch: Eine Variable darf grundsätzlich nicht so einfach innerhalb von Gänsefüßchen notiert werden. Sie muss stets ohne Gänsefüßchen stehen. Das können wir mit PHP »nachspielen«. Schau dir zum Vergleich dieses vereinfachte Beispiel an. Hier geben wir nur den Wert aus der Variablen aus:

      Die Variable selber wurde dank der Gänsefüßchen schon in der ersten Zeile als Zeichenkette »gekennzeichnet«. Es ist also völlig überflüssig, in der zweiten Zeile noch Gänsefüßchen aufzuschreiben.

      Strings und Variablen verketten? Meist unnötig! Eine Variable wird normalerweise nicht in Gänsefüßchen gesetzt. Der Rest jedoch muss als Zeichenkette gekennzeichnet werden. Um Variable und umgebende Zeichenketten zu verbinden, bedient man sich in »herkömmlichen« Programmiersprachen der Technik des Verkettens. 98

      Wie Pech und Schwefel: Strings verketten Warum? In diesen Sprachen darf die Variable nicht einfach Teil des Strings sein. Sie muss mit dem String verkettet werden. Was in anderen Programmiersprachen das einzig Wahre ist, geht natürlich auch in PHP. Du kannst das Beispiel von oben also auch in dieser »Verkettungs-Variante« aufschreiben. Hier als die »Version 3« des »Katja-Beispiels«: " . $vorname . "!"; ?>

      Interessant ist die zweite Zeile. Das Ergebnis entspricht der Version 2. Nur die Schreibweise ist komplizierter geworden. Die Variable wird zu ihrer linken und rechten je mit dem umgebenden String verkettet. Die Ausgabe jedoch ändert sich nicht, es erscheint weiterhin der Text Hallo Katja! im Browser. Wie schon erwähnt: In PHP ist das umständliche Verketten von Strings mit Variablen in den meisten Fällen nicht nötig. Die Variable verträgt es, mit in das »Gänsefüßchen-Boot« genommen zu werden. Wir haben uns in diesem Beispiel also zu viel Arbeit gemacht. Dieses »Zuviel an Arbeit« findest du zum Vergleichen unter dem Namen katja3.php auf der Buch-CD.

      Strings verketten – manchmal geht’s nicht ohne! Warum habe ich dir diese umständliche Variante hier schon gezeigt? Nun, in manchen Fällen kommst du um das Verketten nicht drum herum! Zum Beispiel bei Funktionen. Oder bei den sogenannten Feldvariablen, den Arrays. Einverstanden, die Arrays kennst du noch nicht. Das verschieben wir also auf später. Doch mit einer Funktion können wir uns an dieser Stelle schon beschäftigen. Nix verstehen? Nehmen wir ein Beispiel! Angenommen, du möchtest den markigen Satz: Hallo Katja, willkommen in 2010! ausgeben. Weiterhin wünschst du, dass das Jahr automatisch erzeugt wird. (Wenn du das Buch in 2011 oder 2012 liest, soll natürlich auch 2011 bzw. 2012 ausgegeben werden.) Wie geht das? Mit einer Funktion! Du nimmst einfach eine entsprechende Funktion mit dem passenden Argument.

      99

      Kapitel

      3

      Hallo echo – »Hallo Welt«

      Zum Ausgeben der aktuellen Jahreszahl dient die Funktion date("Y") oder auch date('Y'). Um genauer zu sein: Es ist eine Funktion mit Argument. Die Funktion selbst lautet dabei date(). Das Argument ist hierbei "Y". Und nun noch ein paar Worte zu den Gänsefüßchen: Ob du die doppelten oder die einfachen Gänsefüßchen wählst, ist eigentlich egal. Da du aber Gänsefüßchen nicht einfach ineinander verschachteln darfst, musst du in manchen Fällen die Variante mit den einfachen Gänsefüßchen wählen. Entscheide also von Fall zu Fall.

      Die Jahreszahl wird durch die Funktion date("Y") erzeugt.

      Schreibe die entsprechende Zeile also folgendermaßen: echo "Hallo $vorname, willkommen in " . date("Y") . "!";

      Hier haben wir mit Hilfe der Verkettung dafür gesorgt, dass die Funktion »funktioniert«. Das Jahr wird korrekt berechnet. (Vergleiche, wenn du magst, mit dem Vorbild-Beispiel katja4.php auf der CD.) Achte beim Verketten unbedingt darauf, dass Leerzeichen mit berücksichtigt werden müssen. So musst du im Beispiel nach dem Wort in unbedingt ein Leerzeichen setzen, bevor du das schließende doppelte Gänsefüßchen setzt. Da das Ausrufungszeichen jedoch direkt hinter der Jahreszahl notiert werden soll, ist dort kein Leerzeichen nötig. Würdest du auf die Verkettung verzichten, wäre das Ergebnis grausam. Bei der Variante mit doppelten Gänsefüßchen date("Y") würde es Fehlermeldungen hageln. Warum? Weil du versucht hast, Gänsefüßchen ineinander zu verschachteln. Das solltest du dir also nicht antun. Aber auch eine Veränderung von date("Y") in date('Y') führt nicht zum gewünschten Ergebnis. Zugegeben, das Gänsefüßchen-Problem haben wir damit auf raffinierte Art gelöst. Folgender Quellcode 100

      echo "Hallo $vorname, willkommen in date('Y')!";

      Kleine Zeilenumbruchkunde führt jedoch zu dieser Anzeige:

      Die Funktion wird nicht ausgeführt, sondern im Klartext angezeigt.

      Was ist passiert? Statt die Funktion auszuführen, zeigt sie der Webserver im Klartext an. Kunststück, die Funktion wurde als String behandelt, als einfache Zeichenfolge. Und das ist natürlich Quatsch mit Soße, denn so kann sie nicht funktionieren.

      Kleine Zeilenumbruchkunde Kennst du den »Breakdance«? Oder das berühmt-berüchtigte englische »Breakfast«? Alles hat irgendwie mit »Brechen« zu tun. Beim Breakdance bricht man sich womöglich die Knochen, beim englischen »Breakfast« … nein, lassen wir das jetzt.

      Mit
      einen HTML-Zeilenumbruch erzeugen Ich wollte eigentlich auf den Break hinaus, auf den Umbruch. Ich zeige dir, wie du problemlos einen Zeilenumbruch (
      ) in dein Dokument zauberst. Dafür erweitern wir einfach mal unser Katja-Beispiel. Ich greife dafür auf eine frühere Fassung zurück, auf unsere Version 2: Hier noch einmal der PHP-Teil: $vorname!"; ?>

      Und jetzt ergänzen wir eine zweite echo-Zeile! Damit die neue Zeile auch wirklich auf die »neue Zeile« rutscht, füge ich zusätzlich einen HTMLUmbruch ein. Dafür sorgt das Zeichen
      .

      101

      Kapitel

      3

      Hallo echo – »Hallo Welt«

      $vorname!
      "; echo "Super, dass du mal vorbeischaust."; ?>

      Im Browser sieht das Ganze so aus, zusätzlich habe ich über den Befehl SEITE|QUELLTEXT ANZEIGEN (Internet Explorer) bzw. ANSICHT|SEITENQUELLTEXT ANZEIGEN (Firefox) gleich den HTML-Quelltext aufgerufen.

      Im Quelltext siehst du zwar das Tag
      , aber keinen Zeilenumbruch.

      Bisher haben wir nur einen Umbruch im Browser erzeugt. Im Hintergrund findet jedoch kein Zeilenumbruch statt. Dieses Beispiel kannst du unter dem Namen katja-br.php von der CD abrufen.

      Umbruch im Editor: Der Befehl \n wie new line Wie wäre es zusätzlich noch mit einem Umbruch im Editor? Zugegeben, bei zwei Zeilen ist das vielleicht nicht so wichtig. Doch wenn du häufiger mit echo arbeitest, entsteht irgendwann eine »Endlos-Zeile« im Editor. Wenn du hinter den Kulissen einen Zeilenumbruch wünschst, verwendest du den PHP-Befehl new line. Das entsprechende Zeichen heißt: \n Vor dem n wird lediglich ein Backslash notiert, ein rückwärtsgelehnter Schrägstrich. Das n selbst steht als Abkürzung für new line. Und so sieht das renovierte Beispiel aus, ich habe gleich zweimal mit \n gearbeitet:

      102

      $vorname!
      \n"; echo "Super, dass du mal vorbeischaust.\n"; ?>

      Maskenball: Das Escape-Zeichen »\« Beim Aufruf im Browser wirst du keinen Unterschied zur vorherigen Variante feststellen. Nur der Blick in den Quelltext offenbart den kleinen, aber feinen Unterschied:

      Mit \n erzeugst du die Zeilenumbrüche auch im Quelltext.

      Vergleiche mit der Datei katja-nl.php von der CD.

      Maskenball: Das Escape-Zeichen »\« Mit dem Backslash hat es eine besondere Bewandtnis. Eben habe ich dir diesen »schiefen Kollegen« im Zusammenhang mit dem »Zeilenumbruch« vorgestellt. Mit \n wird eine neue Zeile im Editor erzeugt, du erinnerst dich. In diesem Fall wird unser »Strich-Kumpel« also zu einem Steuerbefehl für die Anzeige des Quelltextes.

      Die wichtigsten Umbruch-Steuerbefehle Es gibt übrigens noch mehr solcher interessanten Steuerbefehle. Die wichtigsten davon stelle ich dir in dieser Tabelle vor: \n erzeugt neue Zeile

      \r \t erzeugt return (neuen Absatz) erzeugt Tabulatorschritt (Sprung)

      Gut, damit haben wir die eine Bedeutung geklärt. Doch hast du schon einmal darüber nachgedacht, was das komische Zeichen »\« wohl sonst noch bedeuten mag?

      103

      Kapitel

      3

      Hallo echo – »Hallo Welt«

      Backslash als »Escape-Zeichen« Dieser Backslash (\) wird auch als »Escape-Zeichen« bezeichnet. Denn normalerweise dient er zum Maskieren bestimmter Sonderzeichen, die du sonst nicht so einfach ausgeben darfst. So darfst du z. B. Gänsefüßchen nicht einfach »im Klartext« in dein Skript hineinschreiben. Gänsefüßchen signalisieren schließlich, dass ein String beginnt bzw. endet. Doch wenn du unbedingt die Gänsefüßchen benötigst? Vielleicht, weil du eine Passage in Anführungszeichen setzen willst? Die eine Möglichkeit lautet: Ersetze die Gänsefüßchen durch einfache Gedankenstriche. Die andere Lösung: »Maskiere die Gänsefüßchen« durch das EscapeZeichen. \"$vorname\"!
      \n"; ?>

      Das Ergebnis im Browser sieht dann so aus:

      Nach dem »Escapen« werden auch Gänsefüßchen korrekt angezeigt.

      Vergleiche mit der Datei escape.php auf der Buch-CD. Du musst auch das Dollar-Zeichen ($) oder den Backslash (\) maskieren, falls du diese Zeichen per echo als HTML ausgeben willst. Denn auch diese Zeichen haben normalerweise eine Sonderbedeutung. 104

      Keinen Durchblick? Kommentare setzen!

      Keinen Durchblick? Kommentare setzen! Steigst du noch durch deinen Quelltext durch? Klar doch! Bei zwei oder drei Zeilen ist das alles noch kein Problem! Doch wie sieht das bei umfangreichen Projekten aus? Weißt du nach Wochen immer noch genau, was die geniale Zeile 87 macht? Und wozu die schließende geschweifte Klammer in Zeile 145 dient? Der Mensch vergisst … (und auch Buffi-Hunde haben nicht gerade das beste Gedächtnis.) Gewöhne dir deshalb frühzeitig an, mit Kommentaren zu arbeiten! Das sind Bereiche, die nur von dir gesehen werden, aber auf den Programmablauf keinen Einfluss haben. Kommentare helfen dir, den PHP-Quellcode zu erklären.

      Einzeilige Kommentare Willst du schnell mal einen einzeiligen Kommentar setzen, verwendest du den Doppelslash //: // Das ist ein einzeiliger Kommentar

      Du kannst diesen Kommentar auch direkt an das Ende einer Zeile setzen, z. B. folgendermaßen: $vorname = "Katja"; // Variable $vorname initialisieren

      Kommentare über mehrere Zeilen ziehen Wenn du dagegen »ganze Romane« schreiben möchtest, bietet dir PHP auch dafür eine Möglichkeit. Fasse deine mehrzeiligen Kommentare zwischen den Zeichen /* und */ zusammen: /* Das ist ein Kommentar, der sich im Beispiel gleich über mehrere Zeilen erstreckt und Platz im Buch verschwendet */

      105

      Kapitel

      3

      Hallo echo – »Hallo Welt«

      Also ich habe es mir inzwischen angewöhnt, ausgiebig mit Kommentaren zu arbeiten. Ich kann dir diese Vorgehensweise nur empfehlen. Ein anderer Trick besteht darin, dein Skript einfach durch Leerzeilen zu gliedern. Tippe ruhig auf [Enter], um vor und nach einer wichtigen Zeile eine Leerzeile zu erzeugen. Das erhöht die Übersicht enorm. Der Programmablauf wird dadurch jedoch nicht gestört.

      Fehlermeldung? Cool bleiben! Es ist zum Auswachsen! Du tippst deinen Code und lädst das Dokument in den Webserver? Eine Fehlermeldung taucht auf. Du korrigierst, lädst erneut – der Fehler bleibt. Ach ja, das Speichern. Du hattest vergessen, vor dem Aktualisieren zu speichern. Neu laden und – was sehen deine vom Bildschirmflimmern überanstrengten Äuglein jetzt? Eine neue Fehlermeldung! Es ist manchmal fast zum Auswachsen und es gibt Momente, da würden Hund Buffi und Buchautor Hanke den PC mitsamt Monitor am liebsten gemeinsam aus dem Fenster werfen. Doch halt! Cool bleiben, lautet die Devise. Hier ein paar Tipps, wie du Fehler vermeiden kannst.

      Semikolon ; am Zeilenende vergessen? Vergiss nicht, dass eine Programmier-Zeile am Ende mit einem Semikolon abgeschlossen werden muss. Das vergessene Semikolon ist einer der häufigsten Fehler. Praktisch alle Zeilen müssen mit einem Semikolon abgeschlossen werden. (Nur in Ausnahmefällen lässt du das Semikolon weg. Aber darauf kommen wir noch zu sprechen!)

      Grausam: Schon ein vergessenes Semikolon führt zu einer Fehlermeldung.

      Schau dir die Abbildung an. Das Gemeine an der Geschichte: Die Fehlermeldung bezieht sich nicht etwa auf die Zeile, in der das Semikolon fehlt. Es wird die nächste Zeile (hier Zeile 14) moniert. Klar, denn da du das Semikolon vergessen hast, weiß der »PHP-Interpreter« nicht, dass die Zeile schon zu Ende war. 106

      Fehlermeldung? Cool bleiben!

      Variablen korrekt benannt? Ein anderer typischer Fehler schleicht sich immer wieder bei den Variablen ein. Hast du dem Variablennamen auch wirklich ein Dollarzeichen vorangestellt? Verschreiber bei den Variablennamen gehören ebenfalls zu den häufigen Fehlern.

      Wenn ich Dollarzeichen sage, meine ich auch Dollarzeichen. Mir passiert es gelegentlich, dass ich eine Variable statt $vorname als §vorname schreibe. Was ich hier im guten Glauben richtig gemacht zu haben glaubte, ist natürlich ein Fehler. Hast du die Groß- und Kleinschreibung bei Variablen beachtet? Wenn du die Variable mit $Vorname initialisierst und versuchst, mit $vorname darauf zuzugreifen, kann das einfach nicht gelingen. Variablen dürfen außerdem nicht mit einer Zahl beginnen, eine Bezeichnung $68vorname würde ebenfalls zu einer Fehlermeldung führen.

      Gänsefüßchen richtig gesetzt? Ein anderer typischer Fehler ist das Vergessen eines Gänsefüßchens. Wenn du statt $vorname = "Katja";

      einfach schreibst $vorname = "Katja;

      gibt es auf jeden Fall Probleme. Jedes »einschaltende« Gänsefüßchen benötigt auch ein »Ausschalt-Pendant«.

      Falsche Klammersetzung? Apropos Ein- und Ausschalten. Im Verlauf des Buches wirst du mit »Klammer-Blöcken« arbeiten. Nutze die schon von CSS bekannten geschweiften Klammern { }, um mehrere Zeilen zu einem Block zusammen zu fassen. Bei den sogenannten Fallunterscheidungen oder den Schleifen zeige ich dir dieses Prinzip später noch ganz genau. Soviel schon vorweg: Auch das versehentliche Vergessen einer öffnenden oder schließenden Klammer führt natürlich zu Fehlermeldungen.

      107

      Kapitel

      3

      Hallo echo – »Hallo Welt« Probleme gibt es vor allem dann, wenn du mehrere »Klammern-Blöcke« ineinander verschachteln musst, und nicht mehr durchblickst, wo welche Klammer nun geschlossen werden soll. Auch hier schon an dieser Stelle mein Tipp: Kommentare setzen! Notiere, wo du welche Klammer öffnest und wieder schließt. Bei dir wird der PHP-Code überhaupt nicht ausgeführt? Nur der HTMLTeil der Seite erscheint? Hast du denn die Seite über den Webserver aufgerufen? Also z. B. über http://localhost/katja.php? Das einfache Doppelklicken auf den Eintrag funktioniert nicht. Vergiss nicht, dass PHP erst durch den »Webserver gezogen werden muss«: Bei PHP handelt es sich schließlich um Server-Programmierung!

      Schlussbemerkung Was für ein Kapitel! Du kannst nun programmieren. Na gut, ein wenig zumindest schon. Du kennst Variablen, weißt, wie du Text ausgibst und kämpfst (hoffentlich erfolgreich) mit einer Vielzahl von Fehlern.

      Zusammenfassung 0 Du weißt, dass PHP-Dokumente HTML-Dokumente mit der Endung .php sind. Du weißt, dass PHP-Bereiche von umschlossen werden. 0 Du kennst die Sprachanweisung echo zur Ausgabe von Daten. Setze den auszugebenden String in Gänsefüßchen, schließe die Zeile durch ein Semikolon ab: echo "Hallo Welt!"; 0 Du kennst das Konzept der Variablen, der »variablen Platzhalter«. Du möchtest eine Variable initialisieren? Notiere die Variable links, den Wert rechts. Setze dazwischen das Gleichheitszeichen, hier Zuweisungsoperator genannt: $vorname = "Katja"; (Die Leerzeichen vor und nach dem Istgleichzeichen haben lediglich eine optische Funktion.) 0 Du weißt, dass du bei der Ausgabe mit echo selbst mit HMTL-Tags arbeiten kannst. Notiere Strings und Variablen einfach innerhalb eines Gänsefüßchen-Paars. Du benötigst keinen Verkettungsoperator, wenn du mehrere Elemente zu einem String zusammensetzen möchtest. Eine Zeile wie echo "Hallo $vorname!"; ist für PHP kein Problem. 108

      Ein paar Fragen … 0 In wenigen Fällen musst du doch den Verkettungsoperator Punkt verwenden, beispielsweise bei der Rückgabe von Werten aus Funktionen. Du hast den Verkettungsoperator im Zusammenhang mit der Funktion date() kennengelernt. 0 Du kennst den Steuerbefehl \n, mit dem man einen Zeilenumbruch auch im Editorfenster erzeugt. Du weißt, dass man mit \ sonst nicht darstellbare Sonderzeichen wie " oder $ maskieren (escapen) kann: Schreibe z. B. \" bzw. \$ 0 Du kennst meine Empfehlung zum Setzen von Kommentaren. Einzeilige Kommentare notierst du hinter //, mehrzeilige Kommentare kleidest du in die Zeichen /* und */ ein. 0 Wir haben besprochen, woher viele Fehler herrühren. Vergiss keinesfalls das Semikolon am Zeilenende oder das schließende Gänsefüßchen. Achte stets auf die korrekte Schreibweise der Variablen.

      Ein paar Fragen … 1. Wie nennt man das Gleichheitszeichen zwischen Namen und Wert einer Variablen? 2. Nenne drei Datentypen für Variablen in PHP! 3. Mit welchem Steuerbefehl erzeugst du eine neue Zeile im Editor?

      … und ein paar Aufgaben 1. Schreibe ein PHP-Dokument, welches den Satz »PHP macht Spaß!« ausgibt. Nenne es fun.php. 2. Wie heißt dein bester Kumpel? Speichere ihren/seinen vollständigen Namen in zwei Variablen. Nenne die erste Variable $vorname, die zweite $nachname. Gib den Namen mit PHP aus, indem du diese beiden Zeichenketten gemeinsam ausgibst. Speichere das Dokument unter dem Namen kumpel.php. 3. Füge in die Datei kumpel.php einen Kommentar ein, der dir jede Zeile erklärt.

      109

      4 Spaß mit Datum und Uhrzeit Time is money, Zeit ist Geld! So lautet das »gnadenlose Motto« vieler Erwachsener. Ich habe mir für dieses Kapitel einen ungleich besseren Wahlspruch ausgedacht. Er lautet: Time is fun, Zeit macht Spaß. In diesem Sinne stürzen wir uns nun ins Abenteuer Zeit. In diesem Kapitel lernst du: $ wie du mit den entsprechenden Funktionen Zeit und Datum ausgibst $ wie du mit if-else-Kontrollstrukturen eine tageszeitabhängige Begrüßung programmierst $ wie du mit sogenannten Feldvariablen (Arrays) die Wochentage ausgibst $ wie du mit Arrays in der Kurzform umgehst $ wie du Monatsnamen in sogenannten assoziativen Arrays speicherst

      111

      Kapitel

      4

      Spaß mit Datum und Uhrzeit

      Immer up to date Bist du up to date? Ich bin es nicht! Wenn mich einer nach dem Datum fragt, zucke ich meist mit der Schulter. Wozu gibt es denn Computer? Fragen wir doch einmal den Webserver, welches Datum wir gerade haben! Bei den nun zu besprechenden Funktionen wird stets Datum und Uhrzeit des Webservers zurückgegeben. Du arbeitest am heimischen PC? Dann sind Datum und Uhrzeit natürlich identisch mit den Angaben deines PCs. Auch bei den zu Beginn besprochenen Dienstleistern sollte es keine Probleme geben. Wenn deine Seiten jedoch auf einem amerikanischen Webserver liegen, handelt es sich bei der Serverzeit natürlich um die amerikanische Zeit!

      Das Datum ermitteln Du möchtest Datum und Uhrzeit ermitteln? Dann brauchst du die Funktion date()! Erinnerst du dich? Wir hatten uns diese Funktion im vorigen Kapitel kurz angeschaut, allerdings nur im Zusammenhang mit dem Jahr. Der Code zum Ermitteln des aktuellen Jahrs lautet: date("Y"). Als Ergebnis bekommst du eine vierstellige Jahresanzeige wie 2008. Doch das Jahr alleine reicht mir nicht aus. Selbst der schusselige Buchautor kennt in der Regel den richtigen Jahrgang! Wo bleiben die Monate, die Tage? Die holen wir uns schnell dazu! Füge der Funktion einfach weitere »Schalter« hinzu. Angenommen, du möchtest das Datum im Format 1.8.08 ausgeben. Also den Tag und den Monat ohne führende Null und das Jahr mit zwei Stellen. Dann schreibst du z. B. echo date("j.n.y");

      Wichtig sind die Buchstaben j, n und y. Die Punkte dienen lediglich zum »Gestalten«. Ran an die Praxis, probiere das doch gleich einmal aus! Erstelle eine neue PHP-Datei, ich schlage den Namen datum1.php vor. Wir wollen das aktuelle Datum mit der eben besprochenen Funktion ausgeben. Ich zeige dir auf der nächsten Seite, was ich zwischen den Tags notiert habe:

      112

      Immer up to date

      Das aktuelle Datum ausgeben



      Diese Funktion verrät dir stets das aktuelle Datum.

      Die Schalter zur Ermittlung des Datums In der folgenden Tabelle habe ich dir alle Schalter zur Ermittlung des Datums aufgeschrieben. Bitte bekomme keinen Schreck, denn hinterher probieren wir das Ganze an weiteren Beispielen aus! Schalter j d n m S y Y D l (kleines »L«) M F w z t

      Erklärung Monatstag ohne führende Null Monatstag mit führender Null Monatszahl ohne führende Null Monatszahl mit führender Null englisches Aufzählungszeichen (st, rd, th) Jahreszahl mit zwei Stellen Jahreszahl mit vier Stellen Wochentag, Kurzschreibweise Wochentag, Langschreibweise Monatsname, Kurzschreibweise Monatsname, Langschreibweise Wochentag als Zahl (0=Sonntag) Tag des Jahres als Zahl Anzahl der Monatstage

      Beispiel 1 bis 31 01 bis 31 1 bis 12 01 bis 12 1st 3rd 5th 10 2010 Mon Monday Jan January 0 bis 6 0 bis 365 28 bis 31

      Weitere Praxisbeispiele Schauen wir uns ein paar Praxisbeispiele an! Du möchtest nur den Wochentag in der Langform ausgeben? Dann genügt folgende Zeile. echo date("l");

      113

      Kapitel

      4

      Spaß mit Datum und Uhrzeit Solle es das Datum in voller Pracht sein? Wochentag und Monat jeweils mit führender 0, also nach dem Muster 01.05.? Und das Jahr in vierstelliger Schreibweise? Dann notierst du einfach: echo date("d.m.Y");

      Du wünschst z. B. folgende englische Schreibweise: 3rd of July 2010? Dann versuche Folgendes – es funktioniert aber nicht unter allen PHP-Versionen: echo date("jS of F Y");

      Wie du siehst, kannst du die Ausgabe des Datums sogar gestalten. Arbeite innerhalb von date() mit Leerzeichen und in Grenzen selbst mit anderen Zeichen wie hier mit dem Punkt! Setze diese Zeichen einfach an der gewünschten Stelle innerhalb von date("") ein, wie bei diesem Beispiel: date("d.m.Y")! Die Punkte dienen hier lediglich als kosmetisches Beiwerk. Nicht alle Zeichen lassen sich jedoch verwenden, deshalb würde ich mich auf Leerstellen und den Punkt beschränken. Im Zweifelsfalle lautet die Devise: Probieren geht über Studieren. Du möchtest angeben, wie viele Tage der aktuelle Monat hat? Du willst den aktuellen Monat dabei ausschreiben (auf Englisch). Dann notierst du beispielsweise folgenden Code (auf einer Zeile): echo "Der " . date("F") . " hat " . date("t") . " Tage.";

      Beachte, dass du hierbei wieder mit einer Verkettung arbeiten musst. Ansonsten wird die Funktion nicht aktiviert.

      Mit den entsprechenden Schaltern gelingt dir die gewünschte Schreibweise im Nu.

      114

      Schau dir zum Vergleichen meine Beispieldatei an. Du findest sie im Ordner kapitel04 unter dem Namen datum2.php.

      Wer hat an der Uhr gedreht?

      Wer hat an der Uhr gedreht? Niemand, hoffe ich! Zumal die Zeitanzeige in PHP sowieso digital erfolgt. Das Drehen an irgendwelchen Zeigern ist schon aus diesem Grund gar nicht möglich. Wie zeigt man die Uhrzeit an? Auch hier hilft uns die Funktion date() aus der Patsche. Und wieder brauchen wir – du ahnst es sicher längst – ganz bestimmte Schalterchen für diesen Zweck. Die wichtigsten Schalter lauten H (Stunden im 24-Stunden-Format), i (Minuten mit führender Null von 00 bis 59) und s (Sekunden von 00 bis 59). Wenn du die Stunden, Minuten und Sekunden anzeigen möchtest, schreibst du: echo date("H:i:s");

      Wie du siehst, arbeite ich auch hier mit Formatierzeichen. Diesmal verwende ich den für die Uhrzeit typischen Doppelpunkt (:).

      Alle Uhrzeitschalter im Blick In der folgenden Tabelle habe ich dir alle Schalter zur Ausgabe der Uhrzeit aufgeschrieben. Tröstlich – es sind im Gegensatz zum Datum viel weniger: Schalter a A h H i s

      Erklärung am oder pm AM oder PM Stunde im 12-h-Format Stunde im 24-h-Format Minuten von 00 bis 59 Sekunden von 00 bis 59

      Beispiel am AM 1 bis 12 1 bis 24 04 12

      Die Zeit vergeht … ein kleines Beispiel Zum Ausprobieren schlage ich ein kleines Beispieldokument vor. Nenne es uhrzeit.php. Ich zeige dir lediglich den Teil zwischen den Tags , der Rest ist ganz normales HTML.

      Beim Aufruf dieser Seite war es genau ...



      115

      Kapitel

      Spaß mit Datum und Uhrzeit

      4 Für die genaue Uhrzeit musst du ständig auf den Reload-Button klicken.

      Ist PHP dafür gedacht, um ständig die ganz aktuelle Uhrzeit auszugeben? Und zwar sekundengenau? Die Antwort lautet: Nein! Denn dann müsste das Skript im Sekundentakt immer wieder aufgerufen werden. Die Seite müsste also sechzigmal pro Minute vom Server abgerufen und an den Browser geschickt werden. Das ist nicht Sinn der Sache, denn dann wäre der »Arbeitsaufwand« (die »Last«) für den Server zu groß. Für solche Aufgaben bietet sich dagegen die Skriptsprache JavaScript an. Diese läuft schließlich direkt im Browser.

      Pause muss sein: Die if-elseEntscheidungsstruktur Wenn, ja wenn das Wörtchen wenn nicht wär’ … Dann wär’ das Leben nur halb so schwer. Stoßen deine Eltern, Tanten oder Bekannten auch manchmal solche hilflosen Drohungen aus wie: »Wenn du nicht gleich dein Zimmer aufräumst, gibt es kein Fernsehen« oder »Wenn du nicht sofort deine Hausaufgaben machst, darfst du nicht runter auf die Straße«? Egal ob »unerfreuliche Gegenwart« oder »düstere Vergangenheit«. In diesem Buch sehen wir alles von der optimistisch-heiteren Seite! Glaube es oder nicht: Mit diesen »Beweisen erzieherischer Intoleranz« haben dir deine Erzeuger ganz unbewusst wertvollen Anschauungsunterricht zur Informatik erteilt. Es geht um die Entscheidungsstrukturen.

      Die Entscheidungsstruktur if-else Nehmen wir doch einmal das »Fernseh-Beispiel«. Formulieren wir es streng logisch: »Wenn du dein Zimmer aufräumst, gibt es Fernsehen, sonst gibt es kein Fernsehen«. 116

      Pause muss sein: Die if-else-Entscheidungsstruktur Die dazugehörige Schreibweise in der Programmiersprache PHP sieht folgendermaßen aus – die Betonung liegt hierbei auf wenn und sonst: Wenn (Zimmeraufräumen) { Fernsehen; } sonst { kein Fernsehen; }

      Zugegeben, in der Programmiererei »spricht man« Englisch. Aus wenn wird if und aus sonst else. Und da man beim Programmieren schlecht mit »Fernsehen« und »kein Fernsehen« arbeiten kann, fassen wir es allgemeiner. Nennen wir die beiden Fälle Fall A und Fall B. Dann sieht unser Grundgerüst folgendermaßen aus: if (Bedingung) { Fall A; } else { Fall B; }

      Mit anderen Worten: Es wird eine Bedingung geprüft. Wenn diese Bedingung wahr ist, tritt Fall A in Kraft. Sonst – also wenn die Bedingung nicht wahr ist – führt das Programm Fall B aus. Übrigens kann der sogenannte else-Zweig auch weggelassen werden. Dann sieht die if-Konstruktion vom Schema her so aus: if (Bedingung) { Fall A; }

      Es genügt also, ganz einfach die Bedingung zu prüfen. Von der Logik her macht das Sinn. Auch beim »Fernseh-Beispiel« weiß Tochter oder Sohn ganz genau was ihr oder ihm blüht, wenn er das Zimmer nicht aufräumt.

      Geschweifte Klammern: Wichtiges Know-how Sicher fällt dir schon an diesem Beispiel ein interessantes »Detail« ins Auge. Zusammengehörende Ausdrücke wie bei diesen if-Strukturen werden in PHP in der Regel durch ein Paar geschweifter Klammern zusammengehalten { }. Dadurch fasst du diese Ausdrücke zu einem sogenannten Block 117

      Kapitel

      4

      Spaß mit Datum und Uhrzeit zusammen. Dabei gilt: Die Zeile mit der Klammer wird ausnahmsweise nicht mit einem Semikolon abgeschlossen. if (Bedingung) {

      Ich empfehle dir sehr die von mir verwendete Schreibweise: Schau dir das Beispiel an. Die öffnende geschweifte Klammer setzt du direkt nach einem Leerzeichen an das Ende der Zeile. So wirst du auch besser daran erinnert, an dieser Stelle kein Semikolon zu setzen. Der schließenden geschweiften Klammer spendierst du dagegen eine eigene Zeile. Auch hier ist kein Semikolon erlaubt: }

      Ich habe noch einen ganz heißen Tipp für dich: Immer wenn ich eine öffnende geschweifte Klammer schreibe, setze ich sofort das Gegenstück. Egal, wie viele Codezeilen ich später noch dazwischen schreiben muss. Warum? So habe ich immerhin schon einmal den Block geschlossen. Denn das Vergessen einer schließenden Klammer ist eine häufige Fehlerursache! Mit meinem Trick ersparst du dir oft stundenlanges Suchen. Hier noch einmal in Kurzform: Wenn du eine öffnende Klammer schreibst, drückst du ein paar Mal auf [Enter] und notierst danach die schließende Klammer. Sicher hast du es längst bemerkt: Passagen innerhalb von geschweiften Klammern werden eingerückt. Dabei tippst du vor den einzurückenden Zeilen 2–4 Leerzeichen. Mehr zu den Einrückregeln erfährst du in einer PDF-Datei auf der Buch-CD unter dokumente/code_einrueckung und ganz ausführlich auch im Nachfolgeband »PHP und MySQL Praxisbuch für Kids« im Kapitel 2.

      Wir machen … Mittagspause Grau ist alle Theorie (und zwar selbst bei Farbfernsehen). Deshalb machen wir gemeinsam eine Pause – eine Mittagspause! Und damit es auch alle Besucher deiner Website merken, teilst du es ihnen einfach mit.

      118

      Das folgende Beispiel soll zwischen 12:00 Uhr und 13:00 Uhr (genauer zwischen 12:00 Uhr und 12:59 Uhr und 59 Sekunden) den Text anzeigen: »Wir machen Mittagspause«. Ansonsten soll der Text »Willkommen auf unserer Seite« erscheinen. Wie geht das? Ganz einfach! Du brauchst lediglich die Funktion date() mit dem Schalter H. Schließlich verrät dir date("H") ganz genau, »was die Stunde geschlagen hat«.

      Pause muss sein: Die if-else-Entscheidungsstruktur Hier mein Musterbeispiel, welches ich pause.php nenne. Ich zeige dir den wichtigsten Teil der Datei:

      Pause zwischen 12:00 und 13:00 Uhr!



      Zwischen Zwölf und Eins macht jeder seins … Mittagspause!

      Du kannst gerne mit dem Musterbeispiel von der Buch-CD vergleichen. Schaue in den Ordner kapitel04.

      So funktioniert das Beispiel Jetzt schauen wir uns die Funktionsweise dieses Beispiels einmal genauer an. Zuerst schreibst du das Schlüsselwort if und tippst ein Leerzeichen. In den runden Klammern wird nun die Bedingung auf ihren Wahrheitswert überprüft. Die Funktion date("H") ist dir vertraut, doch was hat das doppelte Gleichheitszeichen an dieser Stelle verloren? Das doppelte Gleichheitszeichen (==) ist der sogenannte Vergleichsoperator. Aus dem Mathematikunterricht kennst du das einfache Istgleich. Das gibt es in PHP auch, wie ich dir im vorigen Kapitel bewiesen habe. Das einfache Istgleich (=) ist jedoch nur der Zuweisungsoperator. Mit $vorname = "Katja"; hast du der Variablen $vorname z. B. den String Katja zugewiesen. Damit es nicht zu Verwechslungen kommt, hat man als Vergleichsoperator in PHP deshalb das doppelte Istgleich (==) gewählt. Achtung aufgepasst! Verwechsle die beiden Operatoren deshalb auf keinen Fall, du musst zum Vergleichen unbedingt das doppelte Istgleich (==) verwenden! 119

      Kapitel

      4

      Spaß mit Datum und Uhrzeit Der Vergleich liest sich also so: Wenn es wahr ist, dass die Uhrzeit der Zahl 12 entspricht, dann wird die nächste Zeile ausgeführt. Diese Zeile macht nichts weiter, als den Text »Wir machen Mittagspause« auszugeben. Tipp: Falls es bei dir zufällig nicht gerade 12 Uhr ist, kannst du diesen Wert probeweise verändern. (Oder du stellst einfach mal die Uhr deines PCs um.) Wenn dieser Vergleich jedoch nicht wahr ist? Dann wird der else-Zweig ausgeführt. Und dieser gibt lediglich den Satz »Willkommen auf unserer Seite!« aus. Eigentlich ganz einfach, oder? Beachte unbedingt die korrekte Klammersetzung. Wir haben es in diesem Beispiel mit zwei Blöcken zu tun. Zum einen mit dem if-Block, zum anderen mit dem else-Block. Wie wichtig die richtige Klammersetzung ist, kannst du durch ein Experiment feststellen. Entferne doch zur Probe einmal die Klammer hinter else. Bei mir ist das in Zeile 15. Nach dem erneuten Aufruf der Seite im Browser bekommst du eine Fehlermeldung. Diese weist jedoch auf Zeile 17 hin. Klar, denn PHP wusste ja nicht, dass du in Zeile 15 einen Block öffnen wolltest. Das Programm meckert deshalb die schließende Klammer in Zeile 17 an! Falls es bei dir öfter zu solchen Problemen kommt, empfehle ich dir noch einmal die »heißen Hundetipps« von den Vorseiten: Setze zur öffnenden geschweiften Klammer stets sofort das schließende Pendant! Übrigens: Gute Editoren wie PSPad, Notepad++ oder Aptana Studio heben die dazugehörige schließende Klammer farblich hervor, sobald du die öffnende markierst! Achte einmal darauf!

      Vergleichsoperatoren im Überblick Kompliziert? Eigentlich nicht! Mit dem doppelten Istgleich testet man auf Gleichheit. Das ist jedoch noch nicht alles. Höchste Zeit, dass ich dir nun auch die anderen Vergleichsoperatoren zeige. Operator == != > < >= <=

      Bedeutung Gleich Ungleich Größer als Kleiner als Größer gleich Kleiner gleich

      Diese sechs Operatoren sind relativ einfach zu verstehen. Den Gleichheitsoperator hast du schon kennengelernt, das doppelte Istgleich. 120

      Pause muss sein: Die if-else-Entscheidungsstruktur Du kannst jedoch auch prüfen, ob zwei Elemente ungleich sind. So ist 12 ungleich 13. Du kannst auch testen, ob das erste Element größer oder kleiner als das zweite ist. Die 13 ist z. B. größer als die 12. Oder du prüfst, ob gilt: Das erste Element ist größer gleich bzw. kleiner gleich dem zweiten Element. Die 12 ist größer gleich 12. Damit ergeben sich sehr interessante Einsatzmöglichkeiten. Zum Beispiel für eine etwas längere Mittagspause? Apropos Mittagspause. Angenommen, du machst zwischen 11:00 und 13:00 Uhr eine »Brotzeit«. Wie baust du diesen Tatbestand in den Vergleich ein? Nichts leichter als das! Schreibe einfach zwei Vergleiche und verknüpfe diese miteinander. Beide Teilausdrücke müssen wahr sein. Moment mal, verknüpfen? Wie geht das denn? Da kommen uns die nächsten Operatoren doch wie gerufen!

      Na logo! Logische Operatoren zum Verknüpfen Zum Verknüpfen von Vergleichen benötigst du die sogenannten logischen Operatoren. Hier stehen dir die folgenden zwei Operatoren zur Verfügung: Operator Bedeutung && bzw. and Logisches Und, alle Teilausdrücke müssen wahr sein || bzw. or Logisches Oder, mindestens ein Teilausdruck muss wahr sein

      Wundere dich nicht, dass es zwei Schreibweisen gibt. Ich zeige dir beide, damit du auch mit der jeweils anderen Schreibweise vertraut bist. Ich jedoch bevorzuge für das logische Und das doppelte kaufmännische Und (&&). Beim logischen Oder empfehle ich dir die zwei senkrechten Striche, die »Pipe-Zeichen« (||). Wie erzeugst du die Pipe-Zeichen? Kein Problem! Halte die Taste [AltGr] gedrückt. Tippe dann die zweite Taste von links in der zweiten Reihe von unten. Die mit den spitzen Klammern, die Taste [<]!

      Lange Mittagspause per Und-Verknüpfung Doch jetzt probieren wir diese Operatoren ganz schnell einmal aus! Es ging schließlich um unsere »lange Mittagspause«. Hier das Skript, welches ich und.php getauft habe.

      Pause zwischen 11:00 und 13:00 Uhr!


      121

      Kapitel

      4

      Spaß mit Datum und Uhrzeit if (date("H") >= 11 && date("H") < 13) { echo "Wir machen Mittagspause."; } else { echo "Willkommen auf unserer Seite!"; } ?>



      Interessant ist vor allem die vierte Zeile. Hier habe ich zwei Bedingungen mit dem Und-Operator (&&) miteinander verknüpft. Nur wenn beide Teilausdrücke wahr sind, wird der Satz »Wir machen Mittagspause« ausgegeben. Beide Teilausdrücke? Richtig! Es muss zum einen wahr sein, dass die Stunde größer oder gleich 11 ist. Damit wären zuerst einmal 11, 12, 13 usw. zugelassen. Der nächste Teilausdruck beschränkt den Bereich jedoch auf alle Werte unter 13. Hier wird verlangt, dass die Stunde kleiner 13 ist. Mit anderen Worten: Nur wenn die Stundenzahl zwischen 11 und 13 liegt, ist die Bedingung wahr. Um noch genauer zu sein: Die Zeitspanne muss zwischen 11:00 Uhr und 12:59 Uhr liegen, da die 13 selber nicht erreicht werden darf. Probiere es aus!

      Wo gibt’s denn so was? Zwei Pausen am Tag! Fehlt zum Schluss noch die Oder-Verknüpfung. Diese sorgt schließlich dafür, dass mindestens ein Teilausdruck wahr sein muss. Was kompliziert erscheint, wird mit dem nächsten Beispiel sicher ganz einfach! Nehmen wir unser »Mittagspausen-Beispiel«. Wie wäre es mit zwei Mittagspausen? Die eine recht früh von 11:00 bis 11:59 Uhr. Die andere dagegen von 14:00 bis 14:59 Uhr, praktisch als Siesta. Da hilft folgende Vergleichs-Konstruktion. if (date("H") == 11 || date("H") == 14) { echo "Wir machen Mittagspause."; }

      Dank des Oder-Operators zeigt die Seite den »Mittagspausen-Satz« nun in den oben genannten zwei »Zeitfenstern« an. Zum einen, wenn es zwischen 11:00 und 11:59 Uhr ist; zum anderen aber auch dann, wenn der Zeiger zwischen 14:00 und 14:59 »pendelt«. Vergleiche mit der Datei oder.php, wo ich diese Änderung eingebaut habe. 122

      Der Tag vergeht: Zwischentöne mit elseif

      Der Tag vergeht: Zwischentöne mit elseif Eltern haben ja manchmal Phantasie. Sie versuchen, Tochter oder Sohn durch unterschiedliche »Vergütungsmodelle« zu motivieren. Nehmen wir zum Beispiel das Taschengeld. Wenn du sofort das Zimmer aufräumst, wird das mit 3 Euro Taschengeld honoriert. Räumst du das Zimmer dagegen später auf, gibt es immerhin noch 2 Euro. Wenn du das Zimmeraufräumen jedoch vergisst, gibt es überhaupt kein Taschengeld. Auch mit diesem Modell haben uns unsere Erzeuger wieder eine wunderbare Informatik-Lektion erteilt! Um das Beispiel darzustellen, müssen wir unsere if-else-Konstruktion um einen weiteren Zweig ergänzen.

      Einbau eines elseif-Zweigs Und schon sind wir beim sogenannten elseif-Zweig angelangt. Der elseif-Zweig ist immer dann interessant, wenn man mehrere konkrete Fälle voneinander unterschieden möchte. Das »Taschengeld-Beispiel« lässt sich folgendermaßen symbolisieren: if (Zimmeraufräumen sofort) { 3 Euro Taschengeld; } elseif (Zimmeraufräumen später) { 2 Euro Taschengeld; } else { kein Taschengeld; }

      Ziemlich praktisch und raffiniert, findest du nicht? Dabei können sogar noch mehr elseif-Zweige eingebaut werden. Der nächste elseif-Zweig wird nur ausgeführt, wenn die Prüfung im übergeordneten Zweig nicht wahr war. Also wenn das if oder elseif nicht zum Erfolg geführt hat. Auch hier gilt: Der else-Zweig ganz am Schluss kann wieder weggelassen werden.

      123

      Kapitel

      4

      Spaß mit Datum und Uhrzeit

      Tageszeitabhängige Begrüßung Wie wäre es mit einem sinnvollen Beispiel? Schreibe doch einmal ein Skript, welches die Besucher je nach Uhrzeit mit einem anderen Spruch begrüßt. Von 0:00 Uhr bis 10:59 Uhr soll die Begrüßung lauten: »Guten Morgen!«. Von 11:00 Uhr bis 14:59 Uhr dagegen »Mahlzeit!«. Bis 16:59 Uhr schlage ich »Willkommen zur Kaffeezeit!« vor. Ansonsten (also wenn keiner der obigen Fälle zutrifft), soll das Skript »Guten Abend« einblenden. Das ist ein Fall für elseif, und zwar gleich in doppelter Verpackung. Schau dir mein Beispiel an, ich zeige dir wieder den wichtigen Teil zwischen . Ich habe das Dokument willkommen.php genannt.



      Mahlzeit! Mit elseif wird die Entscheidungsstruktur erweitert.

      Auch hier noch ein interessantes Syntax-Detail: Wenn du mit else oder elseif arbeitest, notierst du dieses Schlüsselwort und die dazugehörige öffnende geschweifte Klammer am besten in der gleichen Zeile wie die schließende geschweifte Klammer des vorhergehenden Blocks. Das spart Platz und erhöht die Übersicht. 124

      Feldvariablen: Wochentage aufschreiben

      Feldvariablen: Wochentage aufschreiben Zurück zur Funktion date(), zurück zu den Wochentagen. Blättere ruhig ein paar Seiten zurück und schaue dir die Tabelle an. Wenn du den Wochentag als Namen ermitteln möchtest, verwendest du den Schalter l: date("l")

      Die ganze Sache hat einen Haken: Der Wochentag wird in Englisch ausgegeben, in der Schreibweise Sunday, Monday, Tuesday usw. Für pfiffige englischkundige Schüler und Fachbuchautoren ist das kein Problem. Doch ob Otto Normalsurfer immer die englischen Wochentage kennt? Es wäre doch schön, wenn man die Wochentage auf Deutsch anzeigen könnte!

      Wochentage auf Deutsch ausgeben Richtig! Man könnte für jeden Wochentag eine eigene Variable verwenden! Dann könnte man eine if-else-Kontrollstruktur schreiben, die aus Monday Montag, aus Tuesday Dienstag usw. macht. Es geht aber auch anders! Warum eine Variable für jeden Tag? Eine Variable für alle Tage ist viel besser! Eine sogenannte Feldvariable, ein Array! Wenn man mehr als einen Wert in einer Variablen speichern möchte, kommen die sogenannten Feldvariablen ins Spiel. Eine Feldvariable bildet ein »Feld« zusammengehöriger Elemente. Stelle es dir vor wie eine Fußballmannschaft oder wie die Schulklasse. Die Feldvariable ist der 1. FC Pokalsieg oder die Klasse 8c. Die einzelnen »Elemente« sind die Spieler bzw. Schüler der Klasse.

      Feldvariablen werden Array genannt Feldvariablen werden auch als Arrays bezeichnet, als Werteliste. Das Wort Array betonst du auf der letzten Silbe. Das »A« am Anfang wird kurz gesprochen. Die Syntax wiederum sieht folgendermaßen aus: $Variablenname[Index-Wert]

      125

      Kapitel

      4

      Spaß mit Datum und Uhrzeit Im Klartext: Zuerst notierst du den Variablennamen wie gewohnt. Dann setzt du ohne Leerzeichen ein paar eckige Klammern. Doch wie unterscheidet man die einzelnen Elemente voneinander? Wie macht man kenntlich, dass es sich um Fußballspieler 1 oder Schüler 5 handelt? Das leistet der sogenannte Index-Wert. Dieser wird in eckigen Klammern notiert. Der Index-Wert ist eine Art Zähler zur Durchnummerierung! Er wird auch als key (Schlüssel) bezeichnet. Ganz wichtig: Der erste Wert in einem Array trägt per Voreinstellung die Schlüssel-Nummer 0. Der erste Index-Wert lautet also 0 und nicht 1. Weil das so wichtig ist, wiederhole ich es noch einmal: In einem Array beginnt die Zählung bei 0. Der 8. Spieler der Fußballmannschaft würde also den Index-Wert 7 tragen! Fassen wir zusammen: Arrays, die Wertelisten, bestehen aus mehreren Werten. Diese werden von PHP intern durchnummeriert. Der entsprechende Zähler nennt sich Index-Wert oder auch Schlüssel (key). Der key (Zähler) beginnt in der Voreinstellung stets bei 0.

      Die Tage als Array Zurück zu unseren Wochentagen! Schau dir die Sache am Beispiel an! Die Variable selbst nennen wir $tag. Die einzelnen Wochentage werden durchnummeriert. Wir fangen beim Sonntag an. Der Sonntag bekommt die 0 (bei 0 beginnen!) und wird so notiert: $tag[0]. Der Montag sieht so aus $tag[1] usw. usf. Liste einfach alle Tage auf und weise die entsprechenden Werte zu. Als Test gibst du den Donnerstag mit der Sprachanweisung echo aus. Ich habe mein Dokument wochentage.php genannt. Ich zeige dir hier den PHP-Teil.

      126



      Feldvariablen: Wochentage aufschreiben Beachte, dass ich hier mit einem Kommentar arbeite (Zeichen //), um das Skript direkt im Quellcode erläutern zu können.

      Da Sonntag Tag 0 ist, muss der Donnerstag Tag 4 sein.

      Welcher Tag ist heute? Das bisherige Skript reißt dich sicher nicht gerade zu Begeisterungsstürmen hin. Mich auch nicht! Um lediglich das Wort Donnerstag auszugeben, hätten wir uns den Stress mit dem Array auch ersparen können. Viel interessanter ist der heutige Wochentag, als der Tag, an dem du das Buch liest. Wie ermittelst du mit PHP den Wochentag? Ganz einfach: Dafür sorgt die Funktion date() im Zusammenspiel mit dem Schalter w: date("w"). Das Schöne an date("w") ist, dass am Sonntag 0 und am Samstag 6 zurückgegeben wird. Was für ein Zufall, denn das passt ganz hervorragend für unsere Zwecke. Schließlich beginnt die Zählung bei Arrays ja auch bei 0! Mit dem folgenden Skript kannst du den aktuellen Wochentag auf Deutsch dynamisch im Dokument ausgeben. Vergleiche einfach mit der Datei heute.php aus dem Ordner kapitel04.

      Das Prinzip ist einfach! Ich ermittle die »tagnummer« mit Hilfe der Funktion date("w") und speichere sie in der gleichnamigen Variablen. Diese Zahl übergebe ich der Feldvariablen $tag[] in den eckigen Klammern. Heraus kommt … der aktuelle Wochentag.

      127

      Kapitel

      4

      Spaß mit Datum und Uhrzeit

      Arrays die Zweite: Es geht auch kürzer! Bei der bisherigen Array-Schreibweise handelt es sich um die sogenannte Langform. Da Programmierer faul sind, mögen sie besonders die alternativen Kurzformen. Die sieht für das Wochentage-Array folgendermaßen aus:

      Nach dem Schlüsselwort array folgt die Werteliste. Diese notierst du in runden Klammern. Jeder Wert wird vom nächsten durch ein Komma getrennt. Da es sich um Strings handelt, notierst du die Tage selbstverständlich in Gänsefüßchen. Beachte, dass es sich trotz des Umbruchs im Buch um eine Zeile handelt! Wenn du aus Platzgründen ebenfalls einen Umbruch einbauen möchtest, dann nur nach einem Komma. Zerreiße keinesfalls Text, der innerhalb von Gänsefüßchen notiert wurde. Das Komma hat eine besondere Bedeutung. Alle Werte werden durch Komma voneinander getrennt. Die Zuweisung der keys (Index-Werte) erfolgt dabei automatisch hintereinander. Du musst sie nicht extra notieren. Das Beispiel findest du unter dem Namen heutekurz.php.

      Array-Elemente zählen Wie viele Tage hat die Woche? Wie viele Schüler befinden sich in deiner Klasse? Zähle die Array-Elemente doch einfach einmal durch! Stelle es fest mit der Funktion count(). Und wie geht das nun mit count()? Die Funktion funktioniert ganz einfach: In runden Klammern übergibst du Namen des Arrays. Und zwar ohne irgendwelche eckigen Klammern. Schließlich beziehst du dich nicht auf ein einziges Element. Das gesamte Array wird »ausgewertet«. 128

      Assoziativ: Monatsnamen als Array \n"; $elementzahl = count($tag); echo "Die Woche hat $elementzahl Tage.\n"; ?>

      Du findest das Beispiel zum Vergleich unter dem Namen count.php.

      Die Funktion count() zählt die Elemente eines Arrays.

      Keine Bange, die Funktion count() zählt korrekt. Du musst dir also keine Sorgen machen, dass der Index-Wert 0 irgendeinen Einfluss hat. Wenn die Fußballmannschaft ein Array darstellen würde, bekäme der elfte Spieler zwar den Index-Wert 10. Trotzdem würde beim Zählen mit count() natürlich korrekt die 11 ermittelt.

      Assoziativ: Monatsnamen als Array Das mit den Arrays ist eine ganz feine Sache. Gewiss. Doch nicht immer sind diese Index-Nummern der Weisheit letzter Schluss. Nehmen wir als Beispiel ein paar europäische Städte. Diese sollen in einem Array namens $hauptstadt festgehalten werden. Nach der »klassischen« Index-Variante sieht das folgendermaßen aus: $hauptstadt[0] $hauptstadt[1] $hauptstadt[2] $hauptstadt[3]

      = = = =

      "Berlin"; "Wien"; "Warschau"; "Paris";

      Doch unter $hauptstadt[1] kannst du dir sicher nicht viel vorstellen. Du musst dir halt merken, dass sich dahinter Wien verbirgt. Je mehr Hauptstädte das Array enthält, desto komplizierter wird die ganze Geschichte.

      129

      Kapitel

      4

      Spaß mit Datum und Uhrzeit Logisch, denn unter nackten Zahlen kann sich ein Normalsterblicher – von ein paar Mathematik-Genies abgesehen – wenig vorstellen. Anders ausgedrückt: Mit bloßen Zahlen kann man wenig verbinden, wenig assoziieren. Viel praktischer ist es, wenn man diese Index-Nummern einfach durch eigene Werte ersetzt. Durch Werte, mit denen man etwas assoziieren kann. Was liegt bei Hauptstädten näher, als die im Web gebräuchliche Länderkennung zu verwenden? In unserer »assoziativen Variante« sieht das Array folgendermaßen aus: $hauptstadt["DE"] $hauptstadt["AT"] $hauptstadt["PL"] $hauptstadt["FR"]

      = = = =

      "Berlin"; "Wien"; "Warschau"; "Paris";

      In assoziativen Arrays wird als key statt der Index-Nummer ein ganz eigenes Schema erzeugt. Dieses darfst du dir (fast) frei ausdenken. Es kann sich bei diesen »Ersatz-Schlüsseln« um Strings aber auch um Zahlen handeln. Der key in assoziativen Arrays wird – von Ausnahmen abgesehen – innerhalb von Gänsefüßchen notiert.

      Einen einzelnen Index-Wert ausgeben Du möchtest einen einzelnen Index-Wert ausgeben? Kein Problem! Das Prinzip ist genau das gleiche wie bei den »klassischen Arrays« mit Zahlen als Index-Wert. Als zusätzlichen Test kannst du gleich noch die Elemente im Array durchzählen. Auch hier arbeitet count() wie gewohnt. Hier zeige ich dir den wichtigsten Teil meiner PHP-Datei hauptstadt.php.

      \n"; echo "Elemente im Array: " . count($hauptstadt); ?>



      130

      … und wieder die Kurzform

      Bei assoziativen Arrays kannst du dir den Schlüssel frei ausdenken.

      Die Wirkungsweise ist klar? In der ersten echo-Zeile ist eigentlich nur die Ausgabe von $hauptstadt["PL"] interessant. Damit daraus aber eine ganze Wortgruppe wird, verknüpfe ich den String Polen: mit $hauptstadt["PL"]. Am Schluss sorgt ein Zeilenumbruch
      dafür, dass die nächste Zeile auch auf einer neuen Zeile steht. Und das Zeichen \n kümmert sich darum, dass auch im Quelltext ein Zeilenumbruch erfolgt. In der nächsten Zeile zähle ich die Elemente des Arrays durch.

      … und wieder die Kurzform Übrigens gibt es auch bei den assoziativen Arrays eine Lang- und eine Kurzform. Auch bei dieser Kurzform arbeitet man mit runden Klammern. Davor notierst du wieder das Schlüsselwort array. Zusätzlich kommt jedoch das Zeichen »Daraus folgt« zum Einsatz. Das sieht so aus: =>. Zum Vergleich zeige ich dir hier die Kurzform des obigen Beispiels:

      "Berlin", "AT" => "Wien", "PL" => "Warschau", "FR" => "Paris"); echo "Polen: " . $hauptstadt["PL"] . "
      \n"; echo "Elemente im Array: " . count($hauptstadt); ?>



      Die lange »Array-Zeile« liest sich wie folgt: Key DE daraus folgt Berlin, Key AT daraus folgt Wien usw. usf. Vergleich mit der Datei hauptkurz.php.

      131

      Kapitel

      4

      Spaß mit Datum und Uhrzeit

      Den Monat ausgeben Zurück zu unserem Datums-Beispiel. Wir wollen diesmal den aktuellen Monat komplett auf Deutsch ausgeben. Damit es übersichtlich bleibt, setze ich ein assoziatives Array in der Langform ein: Als Schlüssel verwende ich die ausgeschriebenen englischen Monatsnamen. Warum? Weil die Funktion date("F") schließlich die Monatsnamen ausgeschrieben ermittelt. Dann brauche ich diesen englischen Monatsnamen nur noch in der Variablen $monatsname zu speichern. Diesen nutze ich als Key. Und schon habe ich den deutschen Monatsnamen. Hier das entsprechende Skript:

      \n"; echo "Das Jahr hat " . count($monat). " Monate."; ?>



      Die Monatsnamen werden durch ein assoziatives Array übersetzt.

      132

      Vergleiche mit der Datei monatsnamen.php im Ordner kapitel04.

      Schlussbemerkung

      Schlussbemerkung Nicht schlecht, Herr Specht: Du hast dich ein gutes Stück qualifiziert auf dem Weg zum »richtigen Programmierer«: Schließlich zählen die Entscheidungsstrukturen und die Arrays zu den wichtigsten Programmiergrundlagen. Und das »Spielen« mit Datum und Uhrzeit hat hoffentlich ein wenig darüber hinweggetröstet, dass der Stoff nicht immer ganz einfach ist.

      Zusammenfassung 0 Du weißt, dass du mit der Funktion date() das Datum ermitteln kannst. Mit den richtigen »Schaltern« und mit Formatierzeichen wie Punkt oder Leerzeichen gelingt fast jede gewünschte Ausgabe. Für Tag und Monat ohne führende Null und das Jahr mit zwei Stellen schreibst du z. B. echo date("j.n.y"); 0 Auch die Uhrzeit kann mit der Funktion date() ganz einfach ermittelt werden. Wenn du die Stunden, Minuten und Sekunden anzeigen möchtest, schreibst du z. B.: echo date("H:i:s"); 0 Du hast die if-else-Entscheidungsstruktur kennengelernt. Es wird eine Bedingung auf Wahrheit geprüft. Wenn diese Bedingung wahr ist, tritt Fall A in Kraft. Sonst – also wenn die Bedingung nicht wahr ist – führt das Programm Fall B aus: if (Bedingung) { Fall A; } else { Fall B; }

      0 Du kennst die wichtigsten Vergleichsoperatoren wie das Istgleich (==), die Zeichen Größer als (>), Kleiner als (<) und Größer gleich (>=) und Kleiner gleich (<=). 0 Du kennst die logischen Operatoren Und (&&) bzw. Oder (||), mit denen du mehrere Vergleiche miteinander verknüpfen kannst. Beim logischen Und müssen alle Teilausdrücke wahr sein. Beim logischen Oder muss dagegen mindestens ein Teilausdruck wahr sein.

      133

      Kapitel

      4

      Spaß mit Datum und Uhrzeit 0 Du kennst den elseif-Zweig, mit dem mehrere Bedingungen hintereinander geprüft werden können. Der nächste elseif-Zweig wird nur ausgeführt, wenn die Prüfung im übergeordneten Zweig nicht wahr war. 0 Du hast dich mit dem Konzept der Feldvariablen vertraut gemacht, der sogenannten Arrays. Eine Feldvariable bildet ein »Feld« zusammengehöriger Elemente. Indizierte Arrays besitzen als Schlüssel einen Zähler, der normalerweise bei Null anfängt zu zählen. So wird das erste Element des Arrays $tag so definiert: $tag[0]; 0 Du weißt, dass es neben den indizierten Arrays auch die sogenannten assoziativen Arrays gibt. Dabei wird der Nummern-Schlüssel durch eine selbst wählbare Zeichenfolge ersetzt. Nimm Zeichenfolgen, mit denen du etwas assoziieren kannst. So wäre $hauptstadt["DE"] = "Berlin"; eine gute Möglichkeit, die Hauptstadt von Deutschland zu speichern. 0 Du weißt, dass es bei Arrays eine Lang- und eine Kurzform gibt. Bei der Kurzform werden die einzelnen Array-Elemente in runden Klammern zusammengefasst. Vorangestellt wird das Schlüsselwort array. Bei assoziativen Arrays musst du zusätzlich mit dem Zuweisungsoperator => (Daraus folgt) arbeiten. 0 Du kennst die Funktion count(), mit der sich die Elemente eines Arrays zählen lassen.

      Ein paar Fragen … 1. Mit welcher Funktion kannst du Datum und Uhrzeit darstellen? Nenne nur die Funktion ohne Schalter oder Formatierzeichen. 2. Was bedeutet if-else und wofür brauchst du diese Schlüsselworte? 3. Welches Zeichen verwendet man, wenn man zwei Elemente auf Gleichheit testen will? 4. Wie sieht der Vergleichsoperator aus, der auf Ungleichheit prüft? 5. Mit welcher Zahl beginnt die Zählung bei indizierten Arrays? 6. Mit welcher Funktion kannst du die Elemente eines Arrays zählen?

      134

      … und ein paar Aufgaben

      … und ein paar Aufgaben 1. Schreibe ein PHP-Dokument, welches einen Satz nach diesem Muster ausgibt: »Heute ist Tag 5 des 3. Monats in 2009«. Dabei sollen natürlich der aktuelle Tag, der aktuelle Monat und das aktuelle Jahr eingesetzt werden. Speichere das Dokument unter dem Namen heuteist.php. 2. Spaß muss sein. Erzeuge eine Seite, die den Surfer an allen Werktagen normal begrüßt. Nur am Sonntag soll der Text ausgegeben werden: »Am Sonntag ist das Internet leider geschlossen«. Nenne das Dokument sunday.php. (Tipp: Nutze die Entscheidungsstruktur für diesen Zweck.) 3. Erstelle ein Dokument, welches das Datum in folgender freundlicher Schreibweise ausgibt: »Heute ist Mittwoch, der 11. Februar 2011«. (Gemeint ist das zum Zeitpunkt des Lesens aktuelle Datum!) Im Klartext: Sowohl der Wochentag als auch der Monatsname sollen in der deutschen Schreibweise ausgegeben werden. Der Dateiname soll tagmonat.php heißen.

      135

      5 Seiten mit Passwort schützen Webseiten so sicher wie die Bank von England? Solange es Hacker gibt, wird das wohl immer ein Traum bleiben. Doch etwas Sicherheit ist möglich: Erzeuge einen Passwortschutz, der zumindest von »Normalsterblichen« schwer zu knacken sein wird. Sorge dafür, dass bestimmte Informationen nur nach Eingabe eines Passwortes angezeigt werden. Schließlich stehen die Passwörter selber im PHP-Code, werden also dem Betrachter nicht angezeigt. Beste Gelegenheit, gleich ein paar weitere wichtige PHP-Techniken zu trainieren. Deshalb lernst du in diesem Kapitel: $ wie du Daten aus einem Formular mit post bzw. get verschickst $ wie du Daten aus Formularfeldern ausliest und verarbeitest $ wie du Bedingungen nicht nur mit if-else, sondern auch mit der sogenannten switch-Anweisung überprüfen kannst $ wie du Variablen auf Vorhandensein testest und Fehler vermeidest $ wie du externe Dateien mit include einbindest

      137

      Kapitel

      5

      Seiten mit Passwort schützen

      Formular für das Passwort Auf los geht’s los! Erstelle eine Datei mit einem Passwortschutz. Wer das Passwort kennt, sieht die geheimen Inhalte. Wer nicht, hat einfach Pech gehabt. Doch wie fragen wir das Passwort ab? Ganz einfach, mit einem Formular! Für das nächste Kapitel empfehle ich gute HTML-Formularkenntnisse. Falls du hier noch Lücken hast, schlage einfach noch einmal im 1. Kapitel nach. Immerhin haben wir dort schon eine erste Formularseite erstellt.

      Schreibe ein Formular Ich zeige dir Schritt für Schritt, wie das Beispiel aufgebaut wird. Mache einfach mit. Das Beispiel nennst du passwort.php. Hier siehst du die erste Version dieser Datei, ich präsentiere dir diesmal das komplette Dokument. Kennen Sie das Passwort? <meta http-equiv="content-type" content= "text/html; charset=utf-8">

      Wie lautet das Passwort?



      Zum Überprüfen: Du findest mein Beispiel in einem Unterordner namens version1.

      138

      Senden mit Methode: post oder get?

      Die Seite erzeugt ein Formular mit einem Eingabefeld. Mehr nicht!

      Zur Erinnerung: Das Formular wird durch
      eingeleitet und mit
      geschlossen. Das Formular selber besteht aus folgenden Zeilen:


      Schau dir die zweite Formularzeile an, denn hier entsteht das Texteingabefeld. Dafür sorgt die Anweisung . Ganz wichtig ist für unsere Zwecke der Name des Feldes. Dafür habe ich mir die Bezeichnung pass ausgedacht. (So kurz wie möglich!) Die Zuweisung erfolgt durch das Attribut-Werte-Paar name="pass". Das Formular selber wird durch Klick auf den Submit-Button abgeschickt. Damit hier die Aufschrift Senden prangt, verwende ich das Attribut-WertePaar value="Senden". Tja, und wenn du nun auf den Button SENDEN klickst? Dann passiert erst einmal überhaupt nichts! Oder passiert doch etwas?

      Senden mit Methode: post oder get? Das, was mit einem Formular geschieht, wird direkt im einleitenden
      -Tag festgelegt. Schau dir dieses Tag und seine Attribute etwas genauer an:

      139

      Kapitel

      5

      Seiten mit Passwort schützen

      Das Attribut action Das Attribut action kümmert sich um die »Formular-Aktion«. Action ist also dafür verantwortlich, was mit dem Formularinhalt passiert. Und was passiert damit? In unserem Beispiel besteht die Aktion lediglich aus dem Dateinamen passwort.php. Im Klartext: Die Formulardatei verschickt den Inhalt an sich selbst! Nanu, ist das denn richtig? Ja, genau das ist beabsichtigt! Beachte bitte, welchen Dateinamen du deiner Datei verpasst hast. Falls du von meinem Vorschlag abgewichen bist, musst du den Namen eintragen, den du für deine Datei gewählt hast! Im Zweifelsfall lässt du das Gänsefüßchenpaar einfach leer. Dann wird die aktuelle Datei aufgerufen: und du bist alle Sorgen los!

      Das Attribut method Das zweite wichtige Attribut ist das Attriut method. Es handelt sich dabei praktisch um die Versende-Methode. Es gibt zwei Werte, die du verwenden kannst. Das sind zum einen der Wert get und zum anderen der Wert post. Was ist der Unterschied? Mache den Test! Probiere doch einmal den Wert get aus. Ersetze post durch get und rufe das Formular über den Webserver auf. Tippe einen Wert in das Formularfeld und klicke auf SENDEN. Der Wert wird einfach nach einem Fragezeichen an die Adresse (an die URL) angehängt. Dort steht pass= und dahinter das, was du in das Texteingabefeld getippt hast.

      Völlig ungeignet: method="get" hängt

      die Werte an die URL.

      Für unsere Passwortabfrage ist das völlig ungeeignet. Es sei denn du möchtest, dass das Passwort für alle sichtbar übertragen wird. 140

      Ausgabe des Passworts Ich empfehle generell die Verwendung von post. Denn nur bei der Verwendung des Wertes post wird der Formularinhalt im Hintergrund weitergeleitet. Und tatsächlich verwendet man in der Praxis bei Formularen in der Regel den Wert post. Der Wert get dagegen kommt seltener vor. In Ausnahmefällen ist method="get" doch interessant. Denn nur so ist es möglich, dass der Benutzer auch einen Bookmark (Lesezeichen) auf eine Seite setzen kann. Die Formulardaten werden dabei mit im Lesezeichen gesichert, schließlich gehören sie dann zur URL dazu.

      Ausgabe des Passworts Ich fasse zusammen: Wir fangen das Passwort in unserem Formular auf. Der Formularinhalt (also das Passwort) wird im Hintergrund an das Dokument passwort.php geschickt. Nach Klick auf SENDEN ruft sich die Seite praktisch erneut auf. Das alles ist inzwischen sicher klar. Jetzt steht das Passwort zur Verfügung. Doch wie kommst du an das Passwort heran?

      Formularwerte als assoziatives Array Im vorigen Kapitel hatte ich dich mit den sogenannten assoziativen Arrays gequält. Erinnerst du dich? Die Mühe war nicht umsonst, denn jetzt trägt dieses Wissen Früchte. Auch Formulare werden von PHP als assoziatives Array verwaltet. Hoppla, du hast vergessen, was Arrays sind? Arrays sind Wertelisten, die aus einem Schlüssel-Werte-Paar (key-value) bestehen. Bei den einfachen indizierten Arrays ist der Schlüssel ein bei 0 beginnender Index-Wert. Bei den assoziativen Arrays dagegen lässt sich nicht nur der Wert, sondern auch der Schlüssel (key) frei bestimmen. Bei den von PHP zurückgegebenen Formularen entspricht der Name des Formularfelds dem Schlüssel (key). Der Wert (value) ist dagegen das, was der Benutzer in das Feld eingetippt hat. Das Array selber jedoch heißt $_POST, zumindest gilt das dann, wenn im -Tag das Attribut-Werte-Paar method="post" verwendet wurde. Beachte: Wenn du method="get" verwenden würdest, würde das Array $_GET heißen. Wir bleiben in unseren Beispielen jedoch stets bei method="post". 141

      Kapitel

      5

      Seiten mit Passwort schützen

      Ein Versuch: Das Passwort ausgeben Was weißt du inzwischen? Das von einem Formular zurückgegebene Array heißt $_POST. Das Formularfeld selber heißt im Beispiel pass. Ergo: Der im Formularfeld pass eingetragene Wert muss sich mit $_POST["pass"] ermitteln lassen. »Beweise, mein lieber Watson, wir brauchen Beweise!« »Natürlich, Holmes.« Also mache einen Versuch. In unserer zweiten Version der passwort.php gebe ich das Passwort einfach im Klartext aus! Und zwar mit der allseits beliebten Sprachanweisung echo. Ergänze einfach den PHP-Bereich unterhalb des Formulars. Notiere also unter dem Tag
      und über dem abschließenden noch Folgendes. " . $_POST["pass"] . "

      \n"; ?>

      Die

      -Tags dienen einfach nur dazu, einen Block zu bilden. Du hättest sie auch weglassen können. Wenn du sie verwendest, musst du in diesem Fall wieder mit dem Verkettungsoperator Punkt (.) arbeiten.

      Tatsache! Nach Klick auf Senden wird das Passwort angezeigt.

      Damit ist der Beweis erbracht: Der Zugriff auf den in das Formularfeld pass eingegebenen Wert funktioniert! Zum Vergleich: Diese zweite Version des Dokuments findest du im Unterordner version2.

      142

      Du ärgerst dich, dass du assoziative Array-Variablen auf umständliche Art und Weise mit dem String verketten musst? Gewöhnliche Variablen dagegen nicht? Dann verrate ich dir einen Geheimtrick: Du musst den key bei assoziativen Variablen nicht unbedingt in Gänsefüßchen schreiben. Statt $_POST["pass"] kannst du unter bestimmten Bedingungen auch mit $_POST[pass] auf das Passwort zugreifen. Und zwar immer dann, wenn diese Variable selber zu einem Abschnitt gehört, der in Gänsefüßchen eingekleidet wurde.

      Testen mit if-else

      Dann kannst du das Passwort also statt auf diese Weise echo "

      " . $_POST["pass"] . "

      \n";

      auch folgendermaßen ohne Verkettung ausgeben: echo "

      $_POST[pass]

      \n";

      Das ist aber nur deshalb gestattet, weil die gesamte echo-Anweisung innerhalb von Gänsefüßchen notiert wurde. Außerhalb von Gänsefüßchen solltest du diese Schreibweise nicht verwenden!

      Testen mit if-else Frisch ans Werk, nun kommt die Passwortabfrage. Wer das Passwort kennt, gelangt an die Inhalte heran. Wer nicht, wird über seine Unkenntnis informiert. Als Musterpasswort schlage ich die Zeichenfolge a?iX379 vor. Die Version 3 der Passwort-Abfrage arbeitet mit if-else. Damit sind wir zwar noch nicht am Ziel aller Wünsche angelangt, aber immerhin schon ein Stück weiter. Ich zeige dir diesmal den gesamten Teil zwischen :

      Wie lautet das Passwort?

      Geschützter Bereich

      Hier stehen die geheimen Inhalte ...

      Leider kennen Sie das Passwort nicht!



      143

      Kapitel

      5

      Seiten mit Passwort schützen Die für uns interessante Zeile steckt in: if ($_POST["pass"] == "a?iX379") {

      Hier wird getestet, ob der aus dem Feld pass ausgelesene Inhalt mit der Zeichenfolge a?iX379 übereinstimmt. Nur dann zeigt das Skript den Bereich mit den geschützten Inhalten an. Ich arbeite dabei mit einer if-else-Entscheidungsstruktur. Im if-Bereich teste ich auf Übereinstimmung. Wenn dieser Ausdruck wahr ist, wird der »geschützte Bereich« angezeigt. Falls nicht, greift der else-Zweig. Es erscheint der Satz »Leider kennen Sie das Passwort nicht«! Ist dir etwas aufgefallen? In diesem Beispiel habe ich PHP- und HTMLAbschnitte miteinander vermischt. Die HTML-Abschnitte stehen zwar außerhalb der PHP-Bereiche. Zumindest scheinbar. Trotzdem befinden sie sich innerhalb eines »PHP-Klammer-Blockes« ({ }): Dafür arbeite ich einfach mit mehreren PHP-Abschnitten, die die HTML-Bereiche jeweils »umklammern«. Je nach Bedarf schalte ich den PHP-Bereich dafür ab und wieder ein. Wie du siehst, kannst du HTML-Abschnitte also ganz problemlos in PHP einbinden. Hauptsache, du markierst korrekt, wo ein PHPAbschnitt beginnt und wo er wieder aufhört. Hauptsache, du vergisst nicht eine der hier notwendigen geschweiften Klammern!

      Schönheitsfehler? Variablentest mit isset()! Fällt dir an der dritten Version des Beispiels etwas auf? Richtig, es funktioniert! Herzlichen Glückwunsch. Nur wer das Passwort kennt, wird an die geschützten Inhalte herangelassen. Doch der Satz »Leider kennen Sie das Passwort nicht« wird auch dann eingeblendet, wenn die Seite zum allerersten Mal aufgerufen wird. Soviel Häme ist ungesund. Du musst dem Besucher ja nicht gleich am Anfang auf die Nase binden, dass du ihr oder ihm die Passwortkenntnis nicht zutraust.

      144

      Schönheitsfehler? Variablentest mit isset()!

      Gleich beim Aufrufen der Seite wird dem Besucher Unkenntnis unterstellt.

      Und tatsächlich befindet sich an dieser Stelle ein Schönheitsfehler. Der Satz sollte erst dann eingeblendet werden, nachdem der Formularinhalt abgeschickt wurde. Und nicht gleich am Anfang! Wie schaffst du das?

      Prüfen, ob die Variable überhaupt vorhanden ist Du prüfst einfach, ob die Variable überhaupt definiert und damit vorhanden ist. Denn wenn das Formular noch nicht abgeschickt wurde, kann eine Variable namens $_POST["pass"] noch nicht existieren! Oder? Das Array $_POST wird schließlich erst nach dem Abschicken des Formularinhalts erzeugt. Nutze die Funktion isset(). Die Funktion isset() prüft, ob eine Variable überhaupt gesetzt ist. Erst dann gibt sie den Wert wahr (true) zurück. Bei Nichtvorhandensein wird als Testergebnis jedoch false zurückgegeben. Die Syntax dieser Funktion sieht folgendermaßen aus: isset($Variable). Du übergibst die zu testende Variable einfach in runden Klammern. Baue das Skript um, verbessere es: Aus dem else-Zweig machst du einfach ein elseif! Und hier testest du nun, ob die Passwort-Variable gesetzt ist. Verändere also folgende Zeile: else {

      in elseif (isset($_POST["pass"])) {

      und schon hast du das Problem (vorerst) gelöst. 145

      Kapitel

      5

      Seiten mit Passwort schützen Die Wirkungsweise ist noch nicht ganz klar? Die Zeile liest sich wie folgt: Prüfe, ob die Variable $_POST["pass"] »gesetzt« ist. Wenn ja, gibt die Funktion isset() den Wert true zurück. Und if bzw. elseif testet schließlich auf Wahrheit. In diesem Fall (also nur bei gesetzter Variable) wird der Text »Leider kennen Sie das Passwort nicht« ausgegeben. Da die Variable beim ersten Aufruf der Seite jedoch noch nicht gesetzt ist, passiert gar nichts. Falls du vergleichen willst, schaust du dir das Beispiel im Ordner version4 an! Aufgepasst mit den vielen Klammern in der elseif-Zeile! Das Vergessen solch einer Klammer führt unweigerlich zu einer Fehlermeldung. Wo kommen die ganzen Klammern her? Die Bedingung für elseif wird in runden Klammern getestet. Die notierst du zuerst. Dann setzt du dort den isset()-Test hinein, der schließlich auch ein paar runde Klammern benötigt. Zum Schluss platzierst du innerhalb dieser runden Klammern die Variable, in unserem Fall $_POST["pass"]. Nach einem Leerzeichen folgt dann noch die geschweifte Klammer, die schließlich unseren Block einleitet. Mit dieser »vierten Version« der Passwortabfrage hast du ein wichtiges »Etappenziel« erreicht. Und da das Passwort im PHP-Bereich steht, wird es für Außenstehende auch nicht angezeigt.

      Das Skript noch etwas sicherer machen In diesem Skript steckt ein kleines Problem. Es handelt sich um einen unsichtbaren Hinweis (Notice), den ich für dich hier sichtbar gemacht habe:

      Das Skript produziert intern einen (normalerweise unsichtbaren) Hinweis.

      Der Hinweis bezieht sich auf Zeile 15 und besagt, dass der Index pass nicht definiert wäre. Schau dir Zeile 15 noch einmal genau an: 146

      if ($_POST["pass"] == "a?iX379") {

      Mehr Möglichkeiten mit switch Und tatsächlich steht dort $_POST mit dem Index pass. Fakt ist: Der Hinweis erscheint nur beim allerersten Aufruf der Seite. Wenn der Nutzer also noch keinen Formularinhalt eingetragen und abgeschickt hat. Das ist logisch: Wenn noch kein Formularinhalt abgeschickt wurde, kann es auch keine Variable $_POST mit dem Index pass geben. Derartige Notices (Hinweise) sind zwar keine Fehler, sie gelten aber als schlechter Programmierstil und lassen sich vermeiden. Undefinierte Indizes oder undefinierte Variablen geben Hackern gewisse Chancen, in das Skript einzudringen und Variablenwerte zu manipulieren. (Auch wenn die Chancen in diesem Fall sicher recht klein sind.) Die Lösung ist in diesem Fall ganz einfach. Füge auch in das einleitende if von Zeile 15 die eben besprochene isset()-Variablenprüfung ein – und zwar zusätzlich als erster von zwei Teilausdrücken. Verknüpfe beide Teilausdrücke mit dem &&-Operator. if (isset($_POST["pass"]) && $_POST["pass"] == "a?iX379") {

      Nun

      wird

      auch

      hier

      zuerst

      das

      Vorhandensein

      der

      Variablen

      $_POST["pass"] überprüft. Erst bei einem Erfolg findet der zweite Test statt. Vergleiche mit dem Beispiel aus dem Ordner version5.

      Wie du diese normalerweise unsichtbaren Hinweise einblendest, verrate ich dir übrigens im Nachfolgeband »PHP und MySQL Praxisbuch für Kids«.

      Mehr Möglichkeiten mit switch Ich bin nie zufrieden! Ein einziges lumpiges Passwort abfragen? Das kann doch jeder! Als nächste Stufe schwebt mir eine Seite vor, die mehrere Passwörter entgegennimmt. Je nach Passwort soll der Betrachter andere Informationen angezeigt bekommen. Das ist sozusagen die »Hohe Schule der Passwortkunst«. Folgende Passwörter sollen möglich sein: 0 a?iX379 0 a?iX380 0 a?iX381 »Richtig«, denkst du dir vielleicht: Da arbeite ich mit if und mehreren elseif-Bereichen. Stimmt. Gute Idee. Der Ansatz ist vom Prinzip her völlig korrekt! Doch gerade für solche Fälle gibt es eine Alternative zur ständigen »Elseifferei«. Schau dir die switch-Fallunterscheidung an.

      147

      Kapitel

      5

      Seiten mit Passwort schützen

      Die switch-Fallunterscheidung Du möchtest auf verschiedene Eingaben unterschiedlich reagieren? Dann bietet sich die switch-Fallunterscheidung an. Hier schlägst du gleich mehrere Fliegen mit einer Klappe. Die Syntax lautet: switch(Variable) { case Wert1: Anweisung; break; case Wert2: Anweisung; break; case Wert3: Anweisung; break; ... default: Anweisung; }

      Sieht kompliziert aus? Es ist einfacher, als du vielleicht denkst: Die switch-Fallunterscheidung untersucht, ob eine Variable mit den aufgelisteten Werten übereinstimmt. Deshalb schreibst du in der ersten Zeile switch(Variable) {

      Dabei ist das Wort Variable der Platzhalter für die zu prüfende Variable. (Für unsere Zwecke setzen wir an dieser Stelle nachher natürlich wieder $_POST["pass"] ein.) Beachte die öffnende geschweifte Klammer ({) am Schluss der Zeile, da switch() wieder einen Block benötigt. Die Übereinstimmung selber wird nun mit dem Schlüsselwort case getestet. Hinter dem Leerzeichen notierst du den Wert, mit dem die Variable evtl. übereinstimmen könnte. case Wert1: Wert1 ist hier natürlich der Platzhalter für die entsprechende Zahl bzw. Zeichenfolge. In unserem Fall würdest du als ersten Wert notieren a?iX379.

      148

      Beachte, dass am Ende der case-Zeile ein Doppelpunkt gesetzt werden muss. Gibt es eine Übereinstimmung? Dann wird die betreffende Anweisung nach dem Doppelpunkt ausgeführt. Die Programmabarbeitung muss

      Mehr Möglichkeiten mit switch durch das Schlüsselwort break beendet werden. Das Wort break steht hier für Abbruch. Falls es keine Übereinstimmung gibt, wird in der nächsten case-Zeile weitergeprüft. Sollte in keiner der case-Zeilen eine Übereinstimmung erzielt worden sein, wird die unter default: stehende Anweisung ausgeführt. Soweit die Theorie. Nun zur Praxis!

      Wir »switchen« los: Das praktische Beispiel Das praktische Beispiel nenne ich zur Unterscheidung switch.php. Achte also auf diesen neuen Dateinamen. Und hier die genaue Schrittfolge zur Erstellung des Quelltexts.

      >

      Zuerst übernimmst du das Formular aus dem allerersten PasswortBeispiel. Der einzige Unterschied: Beachte den bei action einzutragenden Wert. Da das neue Projekt unter dem Namen switch.php gesichert wird, musst du hier auch switch.php notieren!

      >

      Hier drucke ich ganz schnell zur Veranschaulichung noch einmal den gesamten HTML-Quellcode ab, der vorerst zwischen stehen muss. Die Überschrift kannst du natürlich frei wählen:

      Drei Passworte abfragen



      >

      Ich zeige dir nun die Vorgehensweise, mit der ich meine Skripte erstelle. Und zwar beginne ich dabei stets »außen« und arbeite mich »nach innen« vor. Also, mach mit: Unter dem Formular fügst du zuerst einen PHP-Bereich ein. Dazwischen lässt du genug Platz zum Ergänzen der noch folgenden Codezeilen.

      >

      Nun notierst du innerhalb des PHP-Bereichs zuerst eine ifAnweisung, mit der du auf das Vorhandensein der Variable $_POST["pass"] testest. Nun sieht der gesamte PHP-Bereich folgendermaßen aus:

      149

      Kapitel

      5

      Seiten mit Passwort schützen

      Was habe ich hier gemacht? Ich spanne die if-Abfrage praktisch um das gesamte Skript herum. Und zwar als eine Art Klammer. Im Klartext: Die in diesem untergeordneten Block enthaltenen Zeilen sollen nur dann ausgeführt werden, wenn die Variable gesetzt ist. Das schützt uns zum einen vor unsichtbaren Hinweisen. Zum anderen macht unsere noch folgende switch-Fallunterscheidung tatsächlich nur bei gesetzter Variable Sinn! Diese »alles umspannenden if-Abfragen« sind übrigens eine häufige Programmiertechnik. In den meisten Fällen wird dabei wie hier auf den else-Zweig verzichtet, da dieser nicht benötigt wird.

      >

      Das Prinzip ist klar? Gut! Innerhalb des if-Blocks notiere ich nun die switch()-Fallunterscheidung.

      >

      So sieht der gesamte PHP-Bereich aus. Die von mir hervorgehobenen ersten zwei und letzten zwei Zeilen sind die, die du eben aufgeschrieben hast. Der Rest ist neu hinzugekommen, er erzeugt die switch()Fallunterscheidung.

      Passwort-Bereich 1

      "; break; case "a?iX380": echo "

      Passwort-Bereich 2

      "; break; case "a?iX381": echo "

      Passwort-Bereich 3

      "; break; default: echo "

      Leider kennen Sie das Passwort nicht!

      "; } } ?>

      150

      Inhalt mit include einbinden Zur Information: Aus Gründen der Übersichtlichkeit habe ich hier auf das Einbinden von HTML-Bereichen verzichtet. Eine Zeile wie echo "

      Passwort-Bereich 3

      ";

      steht als Platzhalter für den entsprechenden Passwortbereich.

      Drei Passwörter stehen zur Auswahl.

      Und, schon ausprobiert? Sehr gut! Wie du siehst, kannst du auch mit switch() eine Passwortabfrage erzeugen.

      Inhalt mit include einbinden Apropos Platzhalter für den entsprechenden Passwortbereich. Wäre es nicht schöner, die betreffende Seite extern ablegen zu können? Damit du die »geheimen Infos« viel einfacher bearbeiten kannst? Wie gut, dass es include() gibt! Mit der Funktion include() kannst du externe Dateien einbinden und auswerten. Notiere in runden Klammern einfach den Dateinamen und evtl. den Pfad zur jeweiligen Datei, und zwar von Gänsefüßchen umhüllt. Wichtig zu wissen: Durch den Einsatz von include() wird die PHPNotation automatisch abgeschaltet. Die einzubindende Datei wird als normale HTML- bzw. Textdatei betrachtet. Um die Datei info1.html einzubinden, schreibst du z. B. include("info1.html").

      >

      Erstelle nun eine Datei für jeden Passwort-Bereich. Als Endung entscheidest du dich für die Endung .html. Die erste Datei nennst du im Beispiel info1.html.

      Bereich für Passwort 1

      Hier stehen die Infos für die Besitzer des 1. Passworts.



      151

      Kapitel

      5

      Seiten mit Passwort schützen

      >

      Erzeuge nach diesem Muster die zwei weiteren externen Dateien namens info2.html und info3.html. Achte darauf, dass du diese Dateien im Beispiel in den gleichen Ordner legst, in dem die switch.php liegt.

      Und nun baust du die switch.php um. Der derart umgestaltete switch()-Block sieht folgendermaßen aus: switch($_POST["pass"]) { case "a?iX379": include("info1.html"); break; case "a?iX380": include("info2.html"); break; case "a?iX381": include("info3.html"); break; default: echo "

      Leider kennen Sie das Passwort nicht!

      "; }

      Probiere es aus, es funktioniert. (Das Vergleichs-Beispiel auf CD heißt hier switch2.php.) Der Vorteil liegt auf der Hand: Es ist für dich nun viel einfacher, den Inhalt der Passwort-Bereiche zu bearbeiten und anzupassen. Merkst du etwas? Du kennst jetzt zwar die switch()-Fallunterscheidung an einem praktischen Beispiel. Doch mit dem Thema Sicherheit hat die bisherige Vorgehensweise nicht das geringste zu. Der Besucher braucht nur (durch Raten) den direkten Link zur Datei info1.html, info2.html bzw. info3.html zu kennen. Schon gelangt sie oder er an deine ach so geheimen Daten heran! Mehr Tipps zur Sicherheit folgen deshalb im nächsten Abschnitt.

      Mehr Sicherheit: Endungs- und Ordnertricks Zurück zum Thema Sicherheit. So flexibel und angenehm die »includeMethode« zu sein scheint. Hier zeigen sich offenbar die Grenzen. Trotzdem 152

      Mehr Sicherheit: Endungs- und Ordnertricks habe ich ein paar Ideen, wie du mehr Sicherheit erreichen kannst. Schau dir einfach meine Ideen an und mache dir deine eigenen Gedanken: 0 Verwende Dateinamen, die sich nicht so leicht raten lassen. Wie wäre es mit d_75uzRxei.html? 0 Verwende eine andere Dateiendung als .html. Der Funktion include() ist die Endung egal. Du kannst deine Dateien auch .txt, .inc oder sogar .exe nennen. 0 Es geht noch wilder: Verwende z. B. die Endung .gif, .zip oder .mid. Bei all diesen Endungen zeigen die meisten Browser die Datei nicht im Klartext an, da sie keine HTML-Datei erwarten. Gif-Grafiken werden als Bild erkannt. Dateien mit .zip am Ende will der Browser herunterladen, da er hier ein sogenanntes gepacktes ZIP-Archiv vermutet. Noch pfiffiger ist vielleicht die Endung .mid. Die meisten Browser bestehen darauf, eine derartige Datei abzuspielen, da sie an der Endung eine MidiKlangdatei zu erkennen glauben. 0 Nutze einen (oder mehrere) Unterordner für deine Dateien. Wie wäre es mit content007? Dass der Besucher zum einen den richtigen Ordnernamen für den Unterordner errät und zum anderen den korrekten Dateinamen, ist schon mehr als unwahrscheinlich.

      Verstecke die Dateien im Unterordner und verpasse ihnen eine falsche Dateiendung.

      Ich habe mich im ersten Beispiel für eine Kombination aus der letzten und der vorletzten Idee entschieden. Der Funktion include() ist die Dateiendung der einzubindenden Datei schließlich herzlich egal. Also benenne ich meine Textdateien einfach um.

      153

      Kapitel

      5

      Seiten mit Passwort schützen Vergleiche mit meiner Beispieldatei include.php. Die einzelnen Textdateien habe ich mit der Endung .mid versehen und in einem Unterordner namens content007 abgelegt. Tipp: Das Umbenennen einer Datei gelingt im Windows-Explorer. Rechtsklicke auf die Datei, wähle den Befehl UMBENENNEN. Lege die neue Endung fest. Schon wieder wirst du nur mit einem Teil der Wahrheit abgespeist. Ich fürchte, dass an dieser Stelle wohl wieder etwas handfestes HundeKnow-how gefragt ist! Es gibt eine weit sicherere Lösung, als dir der Buchautor glauben machen möchte. Zugegeben, nicht bei allen Dienstleistern klappt es. Jedoch bei vielen kostenpflichtigen Anbietern wie z. B. bei www.all-inkl.com. Wie lautet der Trick? Lege die zu schützenden Dateien zuerst in einem separaten Unterordner ab, wie hier schon gezeigt. Diesen Unterordner schützt du nun mit dem Konfigurationstool deines Dienstleisters! (Dahinter verbirgt sich eine als htaccess bezeichnete Technik.) Ein Beispiel? Gut! Ich habe für dich einen Ordner namens safe eingerichtet. Dort liegt eine derartige .htaccess-Datei. Sie schützt diesen Ordner vor dem Zugriff von außen. Im safe-Ordner kannst du also ohne Reue HTML-Dateien wie info1.html, info2.html oder info3.html ablegen – sie sind von außen nicht sichtbar. Vergleiche mit meiner Lösung include2.php. Probiere aus, ob es auch bei deinem Hoster funktioniert. Und noch einen Trick habe ich herausgefunden. Du kannst die zu schützenden Dateien auch in einen anderen sicheren Ordner legen. Ich meine einen Ordner, der beim Dienstleister »von Hause aus« geschützt ist. So ist bei www.all-inkl.com der Ordner cgi-bin von außen nicht erreichbar – und das ganz ohne schützende .htaccess-Datei. Er ist für Skripte vorbehalten. Wenn du jedoch hier Dateien ablegst und diese per include() einbindest, werden die Dateien auch aus diesem Ordner herausgeholt.

      Schlussbemerkung In diesem Kapitel hast du nicht nur viel zum Thema Passwortschutz gelernt. Du hast bei dieser Gelegenheit auch erfahren, wie Formulare abgeschickt und ausgewertet werden. Mit der switch()-Fallunterscheidung kennst du eine weitere wichtige Methode, Eingaben auf Übereinstimmung zu überprüfen. Außerdem weißt du nun, wie du externe Dateien per include() einbinden kannst. 154

      Zusammenfassung

      Zusammenfassung 0 Du weißt, wie Formulare ausgewertet werden. Notiere im
      -Tag das Attribut action. Gib als Wert den Namen bzw. Pfad der PHP-Datei an, die die Formulardaten entgegennehmen soll. (Wenn du das Gänsefüßchenpaar leer lässt, wird automatisch wieder die aktuelle Datei aufgerufen.) Das Attribut method dagegen steuert die Versendemethode (get bzw. post). Schreibe method="post", wenn die Daten im Hintergrund übermittelt werden sollen. 0 Der Formularinhalt wird als assoziatives Array zurückgegeben. Bei Auswahl von method="get" heißt dieses $_GET, bei method="post" dagegen $_POST. Den Wert eines Formularfeldes kannst du im letzten Fall über $_POST["Feldname"] auslesen. 0 In Ausnahmefällen darfst du den key bei assoziativen Arrays auch ohne Gänsefüßchen notieren, schreibe z. B. $_POST[Feldname]. Durch diese Komfortschreibweise ersparst du dir das Verketten des übrigen Strings mit den Array-Variablen. 0 Die Funktion isset() testet, ob eine Variable überhaupt vorhanden ist. Sie gibt wahr oder falsch zurück. Du möchtest prüfen, ob ein Passwortfeld namens pass existiert? Das erreichst du mit isset($_POST["pass"]). 0 Die switch()-Fallunterscheidung untersucht, ob eine Variable mit den aufgelisteten Werten übereinstimmt. Je nach Übereinstimmung kannst du ganz unterschiedliche Codezeilen ausführen lassen. Damit ist switch() eine Alternative zu if und elseif. Mit switch() kannst du jedoch nur auf Übereinstimmung testen. Die Prüfung, ob ein Wert z. B. größer, kleiner oder ungleich ist, ist if bzw. elseif vorbehalten. 0 Binde externe Dateien mit der Funktion include() in deine PHPAbschnitte ein. Die einzubindende Datei wird dabei unabhängig von der Endung als normale HTML- bzw. Textdatei betrachtet. Möchtest du hier PHP-Code einbinden, musst du das in der externen Datei erstens durch die Endung .php und zweitens durch die PHP-Tags kenntlich machen.

      155

      Kapitel

      5

      Seiten mit Passwort schützen

      Ein paar Fragen … 1. Bei welcher Versendemethode werden Formulardaten im Hintergrund an das entsprechende Skript geschickt? 2. Angenommen, du verschickst den Formularinhalt mit method="get". Wie greifst du im PHP-Skript auf den Inhalt eines Feldes namens pass zurück? 3. Wie heißt die Funktion, mit der du die Existenz einer Variablen prüfen kannst? 4. Angenommen, du legst eine Datei namens inhalt.txt in den Unterordner daten. Der Pfad zu dieser Datei lautet also daten/inhalt.txt. Du möchtest diese Datei über include() vom Wurzelordner aus einbinden. Wie sieht die komplette Funktion aus?

      … und ein paar Aufgaben 1. Schreibe ein PHP-Dokument namens vorname.php. Erstelle hier ein Formular mit Texteingabefeld, in welches der Benutzer seinen Vornamen eingeben kann. Nenne das Texteingabefeld vorname. Nach Klick auf SENDEN soll unter dem Formular ein persönlicher Begrüßungssatz wie »Hallo Petra!« stehen. 2. Gib den Inhalt des Formularfelds ($_POST["vorname"]) in einer Syntax wieder, die auf die Verknüpfung mit dem umgebenden String verzichtet. 3. Falls noch nicht getan: Sorge dafür, dass die Begrüßung nur dann erfolgt, wenn das Formular zum einen abgeschickt wurde (Ist die Variable gesetzt?) und zum anderen aber auch, wenn das Feld nicht leer ist. Verknüpfe also zwei Bedingungen miteinander. Tipp: Ein Leerstring wird durch ein Paar Gänsefüßchen symbolisiert. 4. Wie gut sind deine generellen Formularkenntnisse? Ändere das Passwortbeispiel aus dem ersten Teil des Kapitels (Datei passwort.php) wie folgt ab: Das Formularfeld soll das Passwort bei der Eingabe nicht mehr im Klartext anzeigen. Stattdessen sollen je nach Browsertyp Sternchen bzw. Kreise erscheinen.

      156

      6 Etwas Mathe: Taschen(geld)rechner Kennst du das auch? Da bekommt man nun regelmäßig eine gewisse Summe pro Monat. Und dann ist am Ende des Geldes noch so viel Monat übrig. Wo verschwinden sie hin, die sauer verdienten Piepen? Was passiert mit deinem Taschengeld? Ich glaube, hinter diesem Phänomen steckt eines der letzten großen Rätsel der Menschheit. Versuchen wir gemeinsam, zumindest etwas Licht in das Dunkel zu bringen. In diesem Kapitel zeige ich dir aus aktuellem Anlass, wie du $ mit den Grundrechenarten umgehst $ einen Einnahme-Ausgaben-Vergleich erstellst $ das Ergebnis absolut und in Prozent darstellst $ Zahlen rundest und mit Nachkommastellen füllst $ ein Diagramm zur Auswertung zeichnest $ einen einfachen Taschenrechner programmierst $ die Berechnung mit Hilfe einer Funktion erleichterst Mit anderen Worten: In diesem Kapitel dreht sich alles rund um die Mathematik. Ganz unabhängig davon, welche Einstellung du zu diesem Schulfach hast bzw. hattest.

      157

      Kapitel

      6

      Etwas Mathe: Taschen(geld)rechner

      Nicht ohne Grund: Grundrechenarten Eine Programmiersprache wäre keine Programmiersprache, wenn man damit nicht rechnen könnte. Und genau wie in der Schule geht es auch in PHP mit den Grundrechenarten los. Wir wollen uns ja nicht gleich am Anfang überanstrengen!

      Plus, Minus, Mal, Geteilt Die vier Grundrechenarten lauten Plus, Minus, Mal und Geteilt. Die entsprechenden Rechenoperatoren sehen in PHP so aus: +, -, * und / (Schrägstrich). Außerdem gibt es vom Plus- bzw. Minuszeichen jeweils noch ein »Doppelmoppel-Exemplar« namens ++ bzw. --. Mit dem »Doppelplus« wird nicht etwa doppelt addiert. Es handelt sich vielmehr um den Operator zum Inkrementieren. Inkremen… wie bitte? Mit Inkrementieren ist lediglich das Hinzuzählen von 1 gemeint. Rechentechnisch steckt also die Anweisung $i = $i + 1 dahinter. Zur Variablen $i (oder $kaugummi oder wie auch immer) wird also der Wert 1 hinzugezählt. Und warum schreibt man dann nicht einfach $i = $i + 1, sondern $i++? Weil Programmierer faule Gesellen sind und kürzen, wo es nur geht. Zugegeben, so ein $i++ sieht auf den ersten Blick recht ungewohnt aus. Nach einer gewissen Eingewöhnungszeit geht’s aber dann recht fix! Ähnlich verhält es sich mit dem Gegenstück --. Damit wird dekrementiert, also um 1 vermindert. Für die Berechnung $i = $i - 1 schreibt man also $i--. Merke dir diese Anweisungen!

      Grundrechenarten im Überblick Und nun zeige ich dir die vier Grundrechenarten nebst Inkrement- und Dekrement-Operator fein säuberlich aufgelistet in einer Tabelle. Ich habe gleich ein Anwendungsbeispiel hinzugeschrieben. Operator + * / ++ --

      158

      Bedeutung Addition Subtraktion Multiplikation Division addiert 1 hinzu zieht 1 ab

      Beispiel $a = 8 + $c $c = $b – 2 10 * 4 $x / $y $i++ (ist die Abkürzung für $i = $i + 1) $i-- (steht für $i = $i - 1)

      Rechenpraxis: Zwei mal Drei macht Vier …

      Rechenpraxis: Zwei mal Drei macht Vier … … und Drei macht Neune. Zumindest behauptet das Pippi Langstrumpf. Ich fürchte, dass ich während meiner Schulzeit zu ähnlichen Ergebnissen gelangt war. Egal ob kleines Einmaleins oder große Berechnungen: Mit PHP lässt sich das alles endlich wunderbar nachprüfen. Ran an die Praxis, jetzt wird gerechnet. Wir begnügen uns dabei mit der Multiplikation. Notiere das Grundgerüst für eine HTML-Datei. Ich zeige dir nun den kompletten Teil zwischen den Tags .

      Zwei mal Drei



      Das Skript ist einfach: Die zu multiplizierenden Werte halte ich in den Variablen $a und $b fest. Das Ergebnis speichere ich in der Variablen $c und gebe das Ganze durch eine simple echo-Anweisung aus. Der PHP-Teil wird außerdem vom Tag-Paar

      eingefasst, damit das Ergebnis innerhalb eines Absatzes ausgegeben wird. Du weißt schon, jeglicher Text sollte innerhalb eines Block-Elements notiert werden. Und das Ergebnis selbst?

      »Plutimikation« frei nach Pippi Langstrumpf. PHP rechnet genauer!

      Zugegeben, Autor und Pippi gehören nicht gerade zu den Leuchten in Mathematik. Aber zum Glück gibt es ja die Rechenfunktionen von PHP! Übrigens, falls du das Beispiel suchst: Ich habe es unter dem Namen pippi.php auf der CD abgespeichert. 159

      Kapitel

      6

      Etwas Mathe: Taschen(geld)rechner

      Einnahmen minus Ausgaben: Taschengeldrechner Wie wär’s zur Abwechslung mit einer Subtraktion? Schließlich werden im Leben wohl mehr Dinge »abgezogen« als hinzugefügt. Beim Taschengeld zum Beispiel.

      Formular erzeugen Erstelle doch einmal ein Formular mit zwei Feldern. Das eine Feld nimmt den Einnahme-Wert entgegen und wird mit a benannt. Das zweite Feld ist für die Ausgaben gedacht, es bekommt den Namen b verpasst. Dein Skript berechnet Einnahmen minus Ausgaben und präsentiert dir das meist ernüchternde Ergebnis. Das Dokument heißt übrigens rechner.php, denn schließlich musst du auch den Dateinamen wissen. Diesen brauchst du für das Attribut action im Formular, denn das Formular schickt den Inhalt an sich selber. Der Quelltext ist simpel. Wenn du beim vorigen Kapitel gut mitgekommen bist, verstehst du die Wirkungsweise auf Anhieb.

      Einnahme-Ausgabe-Rechnung

      Einnahme:
      Ausgabe:

      Das Ergebnis lautet $c

      \n"; ?>

      Der PHP-Teil besteht lediglich aus zwei Zeilen, die sich sofort erschließen. Mit $_POST['a'] ermittelst du den Wert aus Feld a, mit $_POST['b'] dagegen die Zahl aus Feld b. Die Differenz wird berechnet, in der Variablen $c gespeichert und in der zweiten PHP-Zeile ausgegeben.

      160

      Einnahmen minus Ausgaben: Taschengeldrechner

      Du möchtest Bruchzahlen notieren, z. B. 12,5? Dann beachte, dass Dezimalbrüche in PHP (und in anderen Programmiersprachen) nicht mit dem Komma getrennt werden. Im angelsächsischen Raum wird dafür der Punkt verwendet, denn die Amis oder Engländer kennen unsere Bedeutung für das Komma nicht: Schreibe Kommazahlen also stets mit Punkt statt Komma! Für 12,5 musst du also notieren: 12.5!

      Dezimalbruch auf Angelsächsisch: Trenne mit Punkt statt mit Komma!

      Ist es dir schon aufgefallen? In diesem Kapitel verwendet der Autor die Schreibweise $_POST['a'] und nicht $_POST["a"]. Warum die einfachen statt der doppelten Gänsefüßchen? Gibt es da einen Unterschied? Nein, den gibt es nicht. Es ist in unserem Fall völlig egal, ob du die einfachen oder die doppelten Gänsefüßchen verwendest. Das Thema spielt erst dann eine Rolle, wenn du Gänsefüßchen ineinander verschachtelst. Denn gleichrangige Gänsefüßchenpaare dürfen nicht ineinander verschachtelt werden. Nimm die Schreibweise, die dir am besten behagt. In der Praxis wirst du mal diese, mal jene Schreibweise vorfinden und der Autor dieses Buches will dich wahrscheinlich nur an diese Praxis gewöhnen.

      Kein Ergebnis anzeigen beim ersten Aufruf So simpel können wir das Skript nicht stehen lassen. Denn selbst beim ersten Aufruf der Seite erscheint nun der Text Das Ergebnis lautet 0. Wozu haben wir im vorigen Kapitel lang und breit die if-Abfrage besprochen? Prüfe, ob die beiden Variablen gesetzt sind. Beim ersten Aufruf der Seite wird das noch nicht der Fall sein. Der Inhalt der Formularfelder wird schließlich erst dann verschickt, wenn du auf die Schaltfläche BERECHNEN klickst. Verbinde diese Abfrage durch den &&-Operator (AND). Erst wenn beide Bedingungen wahr sind, soll das Ergebnis eingeblendet werden. 161

      Kapitel

      6

      Etwas Mathe: Taschen(geld)rechner Hier siehst du den PHP-Teil mit dieser zusätzlichen if-Klammer: Das Ergebnis lautet $c

      \n"; } ?>

      Besser testen: Die Funktion empty() Zeit, dass ich mich mal wieder melde, dein Hund Buffi! Offenbar teilt dir der Autor nur die »halbe Wahrheit« mit und speist dich mit der Funktion isset() ab. Was passiert, wenn du nichts in die Felder einträgst und trotzdem auf die Schaltfläche BERECHNEN klickst? Das Skript berechnet das Ergebnis 0. Warum? Leer gelassene Felder werden als Leerstring interpretiert, was in diesem Fall gleichbedeutend ist mit der Ziffer Null. Nimm statt isset() doch einfach die Funktion empty()! Mit empty() erreichst du fast das Gegenteil von isset(). Zur Wiederholung: Die Funktion isset() prüft, ob eine Variable gesetzt ist und gibt nur dann true zurück. Sonst liefert isset() jedoch den Wert false. Das ist bekannt. Mit der neuen Funktion empty() dagegen kannst du herausfinden, ob eine Variable nicht gesetzt ist, ob sie leer ist oder ob sie dem Wert 0 entspricht. In allen diesen drei Fällen liefert die Funktion true zurück, sonst ist der Wert von empty() false. Du schlägst also gleich drei Fliegen mit einer Klappe! Weil empty() ebenfalls einen Wahrheitswert zurückgibt, eignet sich die Funktion genau wie isset() so wunderbar für den Einsatz in ifStrukturen. Der Test lautet dann wie folgt: empty($Variable). Einen Haken gibt es noch an der Geschichte. Mit isset() ermittelst du, ob eine Variable gesetzt ist, nur dann gibt die Funktion true zurück. Mit empty() hingegen erhältst du true, wenn die Variable eben nicht gesetzt (oder leer oder 0) ist. Hmm. Eigentlich wollten wir es ja umgedreht haben. Doch hier greift ein neuer Trick! Stelle der Funktion ein Ausrufezeichen voran! Mit diesem Ausrufezeichen verkehrst du die Funktion in ihr Gegenteil, dieses Ausrufezeichen ist eine Art »Umkehroperator«. Schreibe also !empty($Variable). 162

      Einnahmen minus Ausgaben: Taschengeldrechner

      Und so sieht das Beispiel aus, wenn du statt isset() mit empty() arbeitest: Das Ergebnis lautet $c

      \n"; } ?>

      Bei leer gelassenem Feld erfolgt keine Berechnung.

      Zum Vergleich: Die derart verbesserte Version findest du unter dem Namen rechner_hund.php auf der CD. Probiere sie aus!

      Noch besser testen: Funktion is_numeric() Der Hund Buffi aus der Randspalte wird in letzter Zeit ein wenig vorlaut! Die Funktion empty() ist keine schlechte Idee, das gebe ich zu. Und die Überlegungen aus seinem Tipp sind schon sehr wichtig. Trotzdem sollten wir an dieser Stelle weiterdenken. Denn !empty() unterdrückt auch die Eingabe einer 0 in eines dieser Formularfelder. Zugegeben, in den meisten Fällen macht die Eingabe von Nullen nicht viel Sinn. Aber wenn du außer der Reihe doch mal eine 0 brauchst? Wer den Trick kennt, tippt einfach 0.0 oder 0. in das Formularfeld ein. Das geht. Besser wäre es, wenn du gleich die Funktion is_numeric() verwenden würdest. Sie prüft, ob ein Wert eine Zahl ist. Nur dann gibt sie true zurück, ansonsten false! Das ist doch viel eleganter, findest du nicht? Und so sieht das Beispiel aus, wenn du statt !empty() mit is_numeric() arbeitest. (Dabei prüfe ich zuerst aus Sicherheitsgründen mit isset(), ob die Variable überhaupt existiert. Erst dann teste ich, ob sie einem Zahlwert entspricht. So vermeide ich Fehlermeldungen.)

      163

      Kapitel

      6

      Etwas Mathe: Taschen(geld)rechner

      Das Ergebnis lautet $c

      \n"; } ?>

      Ein weiterer Vorteil: Fehleingaben wie Buchstaben oder Leerzeichen werden auf diese Weise von vornherein ignoriert. Das Beispiel findest du unter dem Namen rechner_autor.php auf der CD zum Buch!

      $_SERVER['PHP_SELF']: Daten an sich selbst schicken Wirf doch einmal einen kritischen Kontrollblick auf das Formular. Auf die erste Zeile deines Formulars. Die Aktion interessiert uns. Bisher haben wir hier den Dateinamen notiert:


      oder auch:

      Eigentlich ist das eine zuverlässige und sichere Lösung. Doch wenn du den Namen der eigentlichen Datei änderst? Und wenn du dann vergisst, auch den Wert hinter action zu ändern? Dann klappt die Formularauswertung natürlich erst einmal nicht und die Fehlersuche beginnt. Da gibt es eine beliebte, allerdings nicht sonderlich sichere Lösung! Es gibt eine sogenannte Servervariable, die Namen und Pfad der Datei zurückgibt. Diese Variable steht im Array $_SERVER zur Verfügung. Der entsprechende key (Schlüsselwert) für diesen Fall heißt 'PHP_SELF'. Notiere also $_SERVER['PHP_SELF']; und schon hast du den schönsten Selbstverweis. Denn diese Variable enthält im aktuellen Fall den Namen rechner.php oder rechner_hund.php (mit Pfad), je nachdem, wie dein PHP-Dokument heißt. 164

      Wie viel bleibt übrig? Prozentrechnung! Mit anderen Worten: Du kannst dein Formular auch so einleiten:

      Vergiss jedoch keinesfalls die Anweisung echo. Erst damit sorgst du dafür, dass der in der Variablen $_SERVER['PHP_SELF'] steckende String ausgegeben und hinter action geschrieben wird. Diese Variante wird von Sicherheitsexperten leider als kritisch eingestuft, da auch der Inhalt von Servervariablen wie $_SERVER['PHP_SELF'] durch Hacker manipuliert werden kann. Im Buch verwende ich sie deshalb nicht. Wenn du dir wirklich die Arbeit erleichtern willst, lässt du das Gänsefüßchenpaar hinter action einfach leer. Das Versenden klappt trotzdem. Denn dadurch bleibt die aktuelle Datei automatisch der Empfänger der Formulardaten. Den Trick hatte ich dir ja weiter vorne schon verraten.

      Wie viel bleibt übrig? Prozentrechnung! Lust auf Prozentrechnung? Richtig, die »Sache mit den Torten«. Soviel zumindest ist bei mir vom Matheunterricht noch übrig geblieben. Und auch in PHP kannst du natürlich nach Herzenslust »Stücke aus der Torte herausschneiden«. Nimm einfach das vorhandene Dokument, passe es an und speichere es unter dem Namen prozent.php. Vergiss nicht, den Wert hinter action anzupassen, im Beispiel muss dieser jetzt natürlich prozent.php lauten. Du kannst auch als Wert hinter action eintragen, auch wenn es nicht die sicherste Lösung ist. Oder du lässt das Gänsefüßchenpaar einfach leer – das funktioniert auch!

      Der Quelltext im Überblick Im Beispiel möchtest du ermitteln, wie viel Prozent vom Taschengeld noch übrig geblieben sind. Du gibst Grundwert und Prozentwert ein und ermittelst den Prozentsatz. Die Einnahme entspricht dabei stets 100%, doch die Ausgabe, also der Prozentsatz?

      165

      Kapitel

      6

      Etwas Mathe: Taschen(geld)rechner

      Mathematisch lässt sich das mit einem Dreisatz lösen. Du kannst auch Verhältnisgleichung dazu sagen. Die Einnahme ist bekannt, diese setzt du zu 100% (Wert 100) ins Verhältnis. Auch die Ausgabe kennst du, doch es fehlt die Angabe für Prozent. Du berechnest also Ausgabe * 100, geteilt durch Einnahme. Hier präsentiere ich dir nun den Quelltext im Überblick. Das Ergebnis lautet $c.

      \n"; echo "

      Ausgegeben wurden also $d Prozent.

      \n"; } ?>

      Teste das Skript ruhig einmal aus. Nimm für den Anfang einfache Werte. Du kannst als Einnahme 100 und als Ausgabe z. B. 20 notieren. Das Skript sollte nun auch für Prozent eine 20 ermitteln.

      Die Funktion round() zum Runden Mache einmal ein Experiment mit krummen Werten! Gib bei der Einnahme eine 12 ein. Ausgegeben hast du dagegen 5 Euro 50 Cent: Für die Ausgabe notierst du also 5.5 (mit Punkt statt Komma, nicht vergessen!) und klickst auf BERECHNEN. Bei krummen Werten erfolgt die Ausgabe langer Nachkommastellen.

      166

      Huch, so eine lange Prozentzahl? So genau wolltest du es vielleicht gar nicht wissen? Du wünschst die Prozentangabe lieber mit zwei oder ganz und gar ohne Nachkommastellen?

      Wie viel bleibt übrig? Prozentrechnung! Nutze die Funktion round(). Die Syntax lautet: round(Wert, Nachkommastellen)

      Für den Platzhalter Nachkommastellen notierst du einfach den gewünschten Wert, z. B. 2 oder 0. Im Beispiel werde ich den Prozentsatz mit zwei Nachkommastellen ausgeben. Dazu füge ich eine zusätzliche Zeile ein: echo "

      Das Ergebnis lautet $c.

      \n"; $d = round($d, 2); echo "

      Ausgegeben wurden also $d Prozent.

      \n";

      Die Zahl in der Variablen $d wird lediglich gerundet und erneut in $d gespeichert. Das Ergebnis kann sich sehen lassen:

      Gerundet sieht der Prozentsatz doch viel schöner aus!

      Du findest das Skript unter dem Namen round.php auf der CD!

      Zahlen formatieren mit sprintf() So ganz zufrieden bin ich bisher jedoch immer noch nicht. Die Prozentzahl haben wir wunderbar gerundet. Doch was ist mit dem Dezimalbruch für die Währung? Diese Zahl erscheint mal ohne Dezimalstellen, mal mit einer (wie im Beispiel) oder in manchen Fällen mit zweien. Gerade für die Ausgabe der Währung wäre eine einheitliche Schreibweise schön! Die Zahl sollte stets mit zwei Nachkommastellen angezeigt werden! Kein Problem, diesen Wunsch erfüllt uns die Funktion sprintf(). Diese Funktion formatiert einen String (oder eine Zahl) und gibt diese formatiert zurück. Die Grundsyntax lautet: sprintf("Formatieranweisung", Argument2)

      Das zweite Argument ist klar, da setzen wir die Variable $c ein. Doch wie sieht das erste Argument aus, welche Formatieranweisung sollen wir nehmen? 167

      Kapitel

      6

      Etwas Mathe: Taschen(geld)rechner

      Die von mir empfohlene Formatieranweisung heißt %01.2f. Bitte frage mich nicht, was sich genau hinter dieser Zeichenfolge verbirgt, sondern merke sie dir einfach. Die von dir zu verwendende Funktion lautet im Beispiel demnach sprintf("%01.2f", $Variable). Diese Formatieranweisung sorgt dafür, dass der Wert der Variablen stets mit zwei Nachkommastellen ausgegeben wird. Probiere es aus. Das derart erweiterte Skript sieht folgendermaßen aus. Auf der CD findest du es unter dem Namen sprintf.php: Das Ergebnis lautet $c.

      \n"; $d = round($d, 2); echo "

      Ausgegeben wurden also $d Prozent.

      \n"; } ?>

      Der Wert wird nun stets mit zwei Nachkommastellen angezeigt.

      Im gewissen Sinne besteht eine Verwandtschaft zu round(): Zuviel Nachkommastellen werden gerundet. Im Gegensatz zu round() füllt sprintf() die fehlenden Nachkommastellen jedoch mit Nullen auf.

      168

      Schnell noch ein Supertipp von mir! Wie wäre es mit der Ausgabe der Währung? Auch das kannst du mit der Funktion sprintf() erledigen! Schreibe einfach sprintf("%01.2f Euro", $c) und schon erscheint hinter dem Wert der Text Euro.

      Traurige Säulen: Ergebnis als Diagramm

      Die Formatier-Funktion eignet sich sogar zur Ausgabe der Zeichenfolge Euro.

      Vergleiche mit dem Quelltext der Datei sprintf_euro.php von der CD! Du gibst einen Ausgabewert ein, der höher liegt als der Einnahmewert? Oder sogar eine negative Zahl? Dann entspricht der ermittelte Prozentwert möglicherweise nicht deinen Erwartungen! Um ganz professionell vorzugehen, könntest du diese Fehleingaben durch if-Abfragen abfangen. Und so wird es in der Praxis auch tatsächlich gemacht. (Mehr zu dieser Technik erfährst du im Kapitel 8.) Im Beispiel verzichten wir jedoch aus Gründen der Vereinfachung darauf!

      Traurige Säulen: Ergebnis als Diagramm Hast du Lust, mit den Zahlen etwas zu spielen? Erstelle zur Abwechslung doch einmal ein Säulendiagramm. Bei dieser Gelegenheit rundest du den Prozentwert so, dass keine Nachkommastellen übrig bleiben.

      Einfach aber wirkungsvoll: Ein Säulendiagramm zur Visualisierung der Daten.

      Zuerst zeige ich dir den kompletten Quelltext im Überblick. Danach folgt die kurze Erklärung. Aber eigentlich ist da gar nicht viel zu erklären. 169

      Kapitel

      6

      Etwas Mathe: Taschen(geld)rechner Das Ergebnis lautet $c.

      \n"; $d = round($d, 0); echo "

      Ausgegeben wurden also $d Prozent.

      \n"; echo "

      Vergleichsdiagramm:

      \n"; echo ""; echo ""; echo "
       Einnahme
      \n"; echo ""; echo ""; echo "
       Ausgabe
      \n"; } ?>

      Der Trick besteht einfach darin, mit Tabellen zu arbeiten. Du benötigst so viele Tabellen wie Säulen, im Beispiel also zwei. Jede Tabelle besteht nur aus einer einzigen Zeile und zwei Zellen. Die Zelle der ersten Tabelle ist 100 Pixel breit (width='100') und besitzt die Hintergrundfarbe grün (bgcolor='green'). Das habe ich so vorgegeben. Die Breite der zweiten Tabellezeile wird dagegen durch den Prozentwert gesteuert. Und dieser liegt dank unserer Rundung auf Ganzzahlen genau zwischen 0 und 100. Zumindest solange wie du positive Zahlen einträgst, die nicht über dem Eingabewert liegen. Wozu habe ich das Zeichen   in der Tabellenzelle notiert? Das mache ich deshalb, weil die Zelle nicht leer gelassen werden darf. Erst mit diesem geschützten Leerzeichen sorge ich dafür, dass die Zelle nicht als leer betrachtet wird und formstabil bleibt. Das Beispiel findest du in der Datei diagramm.php auf der Buch-CD.

      Plus, Minus, Mal, Geteilt? Select!

      170

      Als nächstes Beispiel schlage ich einen simplen Taschenrechner vor. Dazu erweiterst du einfach das Subtraktions-Beispiel. Du kannst eines der ersten Beispiele verwenden, die Prozentrechnung und das Säulendiagramm interessieren hierbei nicht.

      Plus, Minus, Mal, Geteilt? Select! Bist du bereit? Subtrahieren ist out, Wahlfreiheit ist in: Per Auswahlfeld wählst du die gewünschte Rechenoperation, egal ob Addition, Subtraktion, Multiplikation oder Division.

      Ein simpler Taschenrechner mit PHP. Die Auswahl erfolgt per SELECTAuswahlfeld.

      Das Prinzip ist eigentlich gar nicht so schwer. Im Formular ergänzt du das Auswahlfeld (<select>). Und im PHP-Teil liest du dieses Feld aus.

      Der Quelltext im Überblick Zuerst zeige ich dir den Quelltext im Überblick. Danach besprechen wir das Wichtigste! Die Datei selber heißt im Beispiel select1.php.

      Taschenrechner

      Zahl 1:
      Rechenoperation: <select name="rz">
      Zahl 2:


      171

      Kapitel

      Etwas Mathe: Taschen(geld)rechner

      6

      case "-": $c = $_POST['a'] - $_POST['b']; break; case "*": $c = $_POST['a'] * $_POST['b']; break; case "/": $c = $_POST['a'] / $_POST['b']; break; } echo "

      Das Ergebnis lautet $c

      \n"; } ?>

      So liest du ein SELECT-Feld aus Das Herzstück des Skriptes ist das neue Feld SELECT wie Auswählen. Dieses Feld wird von <select> eingehüllt. Die einzelnen Tags bilden die verschiedenen Optionen. Also die Auswahlmöglichkeiten, die in der Liste herunterklappen. In diesem Fall handelt es sich um die vier Grundrechenoperatoren.

      Das Auswahlfeld Fertig ist das wunderbare Auswahlfeld, unsere praktische Klappliste. <select name="rz">

      Außerdem gebe ich dem Feld im einleitenden Tag <select> noch einen Namen mit auf dem Weg. Ich nenne das Feld rz (wie Rechenzeichen). Je nach Auswahl schickt das Feld den entsprechenden Value zurück, also entweder den String +, -, * oder /. So einfach ist das. Auch nicht weiter kompliziert ist die Auswertung im PHP-Teil! Hier arbeite ich mit der aus dem vorigen Kapitel bekannten switch-Anweisung. Erin172

      So liest du ein SELECT-Feld aus nerst du dich? Eine Variable wird auf das Vorhandensein eines Wertes geprüft, hier die Variable $_POST['rz']: switch($_POST['rz']) {

      Bei Übereinstimmung mit einem bestimmten Wert wird die jeweilige Rechenoperation ausgeführt, z. B. die Addition. case "+": $c = $_POST['a'] + $_POST['b'];

      Die Ausführung wird dann durch das Schlüsselwort break abgebrochen. break;

      So funktioniert es auch bei den anderen drei Fällen, zumindest sinngemäß. In diesem Fall kannst du auf den default-Zweig verzichten, da die Variable $_POST['rz'] sowieso nur einen der vier Werte annehmen kann. Zum Vergleichen: Du findest das Beispiel auch in der Datei select1.php.

      Werte in Formularfeldern speichern So schön unser Rechner bisher funktioniert: Eine Sache ist recht ärgerlich. Nach Klick auf BERECHNEN wird zwar das Ergebnis angezeigt. Doch die Werte sind längst aus den Eingabefeldern verschwunden. Kein Problem, speichere die Werte einfach dauerhaft in den Formularfeldern. Wie? Mit einem kleinen Trick. Baue die beiden Zahlen-Eingabefelder im Formular einfach um. Schreibe statt

      Zahl 1:


      einfach folgende aufgebohrte Zeile:

      Zahl 1:


      Ändere auch die zweite input-Zeile von Zahl 2:



      in

      173

      Kapitel

      6

      Etwas Mathe: Taschen(geld)rechner

      Zahl 2:



      Der Trick ist schnell erklärt: Du notierst einfach zusätzlich das Attribut value in den beiden -Formularfeldern. Damit lässt sich ein Wert schon vorher in das Formular eintragen. Den Wert schreibst du jedoch nicht fest, sondern dynamisch in das Feld, und zwar über einen kurzen PHPAbschnitt. Notiere also die Anweisung . Prüfe innerhalb des PHP-Bereichs zuerst, ob $_POST['a'] bzw. $_POST['b'] existieren. Dann gibst du die Werte aus mit echo $_POST['a'] bzw. echo $_POST['b']. Du findest das Skript unter dem Namen select2.php auf der CD zum Buch.

      Rechner de luxe: Wir schreiben eine Funktion An dieser Stelle folgt nun die große Herausforderung von Kapitel 6. Sozusagen der Höhepunkt. Bist du bereit? Stelle deinen Gehirnkasten auf Empfang, denn du schreibst eine eigene Funktion! Eine Funktion für das Rechenskript! Zugegeben, an der Funktionalität des kleinen Taschenrechner-Programms wird sich dabei nichts ändern. Zumindest nicht nach außen. Aber du bist nach dieser Aktion um einige wichtige Kenntnisse reicher. Und das sollte doch die Mühe allemal wert sein, oder?

      Was ist eine Funktion? Eine Funktion ist eigentlich nichts weiter, als eine Sammlung von Programmzeilen. Es ist ein Programmabschnitt, der etwas für dich tut. Ein Programmbereich mit einem speziellen Namen. Man kann eine Funktion aufrufen, übergibt ihr ein paar Argumente und bekommt das verarbeitete Ergebnis zurück. Klingt zu kompliziert? 174

      Rechner de luxe: Wir schreiben eine Funktion Denke einfach an die vordefinierten Funktionen. Es gibt hunderte davon in PHP. Einige kennst du schon, andere bringe ich dir im Verlauf des Buches noch bei. Die Funktion isset($variable) z. B. prüft eine Variable auf Existenz. Sie gibt je nach Sachstand den Wahrheitswert true oder false zurück. Die übergebene Variable (der Prüfling) wird hierbei auch als Argument bezeichnet. Eine Funktion kann auch mehrere Argumente besitzen. Erinnerst du dich an die Funktion sprintf(), die wir eben besprochen haben? Nimm die Zeile: $c = sprintf("%01.2f", $c);

      Die Funktion besitzt gleich zwei Argumente, die durch ein Komma getrennt werden. Das erste Argument steckt in der Formatieranweisung. Das zweite Argument ist der Wert, der formatiert wird. Im Beispiel gibt die Funktion den formatierten Wert zurück, der hier erneut in der Variablen $c gespeichert wird. Halten wir fest: Eine Funktion besitzt ein paar runde Klammern, die sich ohne Leerzeichen nahtlos an den Funktionsnamen anschließen. Innerhalb der runden Klammern werden die sogenannten Argumente übergeben. Mehrere Argumente trennt man durch ein Komma voneinander. Eine Funktion gibt in der Regel etwas zurück, das kann ein String, eine Zahl oder ein Wahrheitswert sein. Keine Bange: Ob du nach einem Komma hinter einem Argument ein Leerzeichen lässt oder nicht, bleibt dir überlassen. Ein Leerzeichen erhöht die Übersicht, muss aber nicht unbedingt sein. In der Praxis findest du stets beide Varianten vor.

      Funktionen selber schreiben Ich hatte vorhin behauptet, dass eine Funktion eine Sammlung von Programmzeilen ist. Eine Art Programm-Modul also, was auf Abruf zur Verfügung steht. Wo stecken denn diese Programmzeilen? Bei den vordefinierten Funktionen ist die Antwort ganz einfach: Sie sind in PHP fest eingebaut, du bekommst sie nicht zu Gesicht. Vordefinierte Funktionen arbeiten wie ein schwarzer Kasten, in den man etwas hineintut und etwas anderes zurückbekommt. Ganz anders sieht die Sache aus, wenn du eine Funktion selber schreibst. Dann kannst du bestimmen, was in der Funktion passiert, denn du »baust den Funktions-Kasten selber zusammen«. Doch warum solltest du das überhaupt tun?

      175

      Kapitel

      6

      Etwas Mathe: Taschen(geld)rechner 0 Funktionen sind ideal, wenn du eine bestimmte Funktionalität in PHP vermisst, aber häufig benötigst. 0 Funktionen sind dann sinnvoll, wenn du eine dieser Aktionen immer wieder durchführen willst. Im Klartext: Funktionen sind etwas für Faule, die sich ihre Codezeilen gerne aufbewahren. Und natürlich etwas für Pfiffige, die damit in manchen Fällen viel Schreibarbeit sparen.

      Grundsyntax einer Funktion Wenden wir uns von der Theorie nun der Praxis zu: Die Grundsyntax einer Funktion sieht folgendermaßen aus, beachte das einleitende Schlüsselwort function vor dem Funktionsnamen: function Funktionsname(Argument[, Argument]) { Codezeile(n); return $variablenwert; }

      Zusammengehalten wird der Funktions-Block wieder durch geschweifte Klammern – diesmal bekommt die einleitende Klammer eine eigene Zeile! Wie schon bei Variablennamen gilt auch bei Funktionsnamen: Groß- und Kleinschreibung werden unterschieden. Leerzeichen, Umlaute und die meisten Sonderzeichen sind tabu. Beginne einen Funktionsnamen nie mit einer Zahl. Der Unterstrich (_) jedoch ist erlaubt. Nehmen wir einmal an, du benötigst eine Funktion, die bei einem Produktpreis aus dem Nettowert den Bruttowert berechnet. So eine Funktion gibt es nicht in PHP. Der Nettowert ist der Preis des Produktes ohne die sogenannte Mehrwertsteuer. (Hinter der Mehrwertsteuer verbirgt sich eine Abgabe, die in Deutschland auf fast jedes Produkt aufgeschlagen wird und die du damit automatisch mit bezahlst.) Diese Mehrwertsteuer beträgt 19%. Die Berechnung selber ist simpel: Du brauchst nur den Nettowert mit 1.19 zu multiplizieren. Das ist schon alles. Ich nenne die Funktion nettoinbrutto(), weil sie den Nettowert in einen Bruttowert umwandelt. Erstelle eine neue PHP-Seite und mache mit! Die Funktion besitzt nur ein einziges Argument: 176

      Der Rechner im Einsatz function nettoinbrutto($wert) { $wert = $wert * 1.19; return $wert; }

      Die Funktion nimmt das Argument entgegen, multipliziert es mit 1.19 und gibt diesen Wert zurück. Innerhalb der Funktion wird dafür die Variable $wert verwendet. Variablen, die du in der Funktion deklarierst, haben normalerweise auch nur innerhalb dieser Funktion Gültigkeit. Die Variable $wert ist im übrigen Skript nicht sichtbar. Auch umgedreht gilt diese Regel. Die Funktion kann nur auf die Werte zurückgreifen, die du ihr als Argument übergibst. Überprüfe, ob die Funktion »funktioniert«. Ergänze unterhalb der Funktion noch folgende Zeilen: $zahl = 100; $zahl = nettoinbrutto($zahl); echo $zahl;

      Herauskommen muss 119. (Die Mehrwertsteuer beträgt in diesem Fall also 19, da 19% von 100 19 sind.) Und, klappt es? Statt dieser drei Zeilen kannst du auch schreiben: echo nettoinbrutto(100);

      Das Beispiel findest du in der Datei mwst.php.

      Der Rechner im Einsatz Soweit zu den Vorbemerkungen. Zurück zu unserem Rechner, zur Datei select1.php oder vielmehr der verbesserten Variante select2.php. Speichere das Dokument ruhig unter einem anderen Namen, ich schlage nun function.php vor. Nach diesen Vorübungen können wir uns endlich an die große Funktion wagen. Es geht um die Funktion zum Berechnen! Unsere Funktion selber nenne ich berechne() und übergebe ihr gleich drei Argumente. Es sind die erste Zahl, die zweite Zahl und der entsprechende Rechenoperator.

      177

      Kapitel

      6

      Etwas Mathe: Taschen(geld)rechner Und nun zeige ich dir, wie ich den PHP-Teil aufgebaut habe. Dank der neuen Funktion konnte ich hier erst einmal radikal ausmisten: Das Ergebnis lautet $c

      \n"; } ?>

      Übrig geblieben sind neben der if-Abfrage und der echo-Zeile für das Ergebnis nur noch zwei weitere Zeilen. Das nennt man klar und übersichtlich, findest du nicht? Das Berechnen wird von der neuen Funktion übernommen. Die ganzen langen switch-Zeilen und all das »Programmgestrüpp« verschwindet damit in der »Funktionskiste«. Doch ehe wir uns die »Kiste« anschauen, betrachten wir den Funktionsaufruf. Der Funktionsaufruf erfolgt in der Zeile: $c = berechne($_POST['a'], $_POST['b'], $_POST['rz']);

      Die Funktion nimmt die drei Argumente entgegen, berechnet das Ergebnis und gibt dieses zurück. Das Skript speichert das Ergebnis in der Variablen $c und gibt den Inhalt mit echo() aus. Doch was ist mit der Funktion selber? Wo steckt die? Hier verwendet der Autor die »Modulbauweise«. Die Codezeilen für die Funktion selber hat er in einer separaten externen Datei abgelegt. Die Datei wird dabei oberhalb des Funktionsaufrufes eingebunden. Das sollte man tun, damit die Funktion noch vor dem Aufruf eingelesen werden kann. So steht sie praktisch schon »auf Abruf bereit«. Für das Einbinden dieser externen Datei dient die im vorigen Kapitel besprochene include()-Anweisung. include("function_modul.inc.php");

      Diese externe Datei heißt function_modul.inc.php und liegt im Beispiel im gleichen Ordner. Warum diese Doppelendung, warum nicht einfach function.txt? Die Endung .php ist ideal, weil dadurch der Code nicht sichtbar ist. Denn PHP-Dateien werden vom Webserver nicht im Klartext angezeigt. Die davor platzierte Endung .inc steht für include, einfügen. So weißt du also, dass es eine externe Include-Datei ist, die du an dieser Stelle einfügst. 178

      Der Rechner im Einsatz

      Quellcode der Datei function_modul.inc.php Nun zur Funktionskiste selber. Schau dir dafür den Quellcode der externen Datei mit dem gewichtigen Namen function_modul.inc.php an. (Den Namen function_modul habe ich so gewählt, dass er möglichst selbsterklärend ist.) Gibt es da Besonderheiten? Da die Datei als PHP-Datei deklariert wurde, muss sie zum einen auch von eingehüllt werden. Nur so kann der Quellcode nicht von jedermann eingesehen werden, wenn die Seite zufällig direkt aufgerufen wird. Außerdem habe ich am Anfang ein paar Kommentarzeilen eingefügt, damit ich später noch verstehe, was die Funktion überhaupt macht.

      Programmtechnisch jedoch bietet die Funktion nichts Neues. Es ist genau die gleiche switch-Anweisung, die ich schon für die erste Version dieses Rechners verwendet habe. Nur für die Variablen habe ich mir neue Namen ausgedacht, aber diese existieren sowieso nur innerhalb der Funktion. 179

      Kapitel

      6

      Etwas Mathe: Taschen(geld)rechner Wichtig sind weiterhin die geschweiften Klammern, die den Funktionsblock bilden. Außerdem muss das Ergebnis der Funktion mit return $ergebnis zurückgegeben werden. Denn unsere Funktion braucht schließlich einen Rückgabewert. Blickst du da auf Anhieb durch? Herzlichen Glückwunsch! Dann hast du schon ein wichtiges Stück fortgeschrittener PHP-Programmierung verstanden. Wenn nicht, ist es auch nicht so schlimm. Du kannst fast alle Programme auch ohne Funktion schreiben. Im Fortgeschrittenen-Band »PHP und MySQL Praxisbuch für Kids« gehe ich näher auf Funktionen ein und mache dich auch mit den Details zur Klammersetzung vertraut.

      Schlussbemerkung In diesem Kapitel haben wir uns mit Mathematik beschäftigt. War es schwer? Ich hoffe nicht, zumindest nicht am Anfang. Du kennst die Grundlagen für das Rechnen mit PHP und hast dich sogar an die Prozentrechnung gewagt. Du kannst Diagramme zeichnen und Auswahlfelder erstellen. Das Beste: Du hast in das Thema PHP für Fortgeschrittene hereingeschnuppert und weißt sogar schon, wie man eigene Funktionen zusammenbaut. Für das sechste Kapitel ist das schon nicht schlecht, oder?

      Zusammenfassung 0 Du kennst die vier Grundrechenarten und die entsprechenden Operatoren +, -, * und /. 0 Du kennst die Operatoren zum Inkrementieren (um 1 erhöhen) und Dekrementieren (um 1 erniedrigen), sie lauten ++ und --. 0 Du kennst die Funktion empty(). Damit kannst du testen, ob eine Variable nicht gesetzt ist, ob sie leer ist oder ob sie dem Wert 0 entspricht. 0 Du kennst die Funktion is_numeric(). Sie testet, ob eine Variable eine Zahl ist und gibt dann true zurück.

      180

      0 Du kennst die Server-Variable $_SERVER['PHP_SELF'], die den Pfad und Dateinamen der aktuellen Datei ausgibt. Du weißt jedoch, dass sie ein Sicherheitsrisiko darstellt und sparsam eingesetzt werden sollte.

      Ein paar Fragen … 0 Du hast dich mit Prozentrechnung beschäftigt und weißt, wie du mit unsichtbaren Tabellen ein Säulendiagramm zeichnen kannst. 0 Du kennst die Funktionen round() und sprintf() zum Runden bzw. Formatieren von Zahlen. 0 Du kennst das Konzept der Funktionen, der »Speicherkästen« für eine Abfolge von Befehlen. Neben den vielen in PHP eingebauten Funktionen weißt du nun auch, wie man eigene Funktionen schreibt.

      Ein paar Fragen … 1. Wie sieht der Rechenoperator aus für Geteilt durch? 2. Mit welcher Funktion kannst du Zahlen so formatieren, dass stets eine bestimmte, aber von dir frei wählbare Zahl von Nachkommastellen angezeigt wird? 3. Welche Doppelendung vergibt man gerne an ausgelagerte IncludeDateien und warum? 4. Wie schreibt man Eineinhalb als Dezimalbruch in PHP? Warum verwendet man das von dir gewählte Trennzeichen?

      … und ein paar Aufgaben 1. Der Taschenrechner (Datei function.php) hat noch einen Haken. Wähle doch einmal die Division und trage ins Feld 2 eine 0 ein! Eine Fehlermeldung ist die Folge. Klar, denn eine Division durch 0 ist nicht definiert! Deine Aufgabe: Sorge dafür, dass die Rechnung zumindest dann nicht durchgeführt wird, wenn der Nutzer in Feld 2 eine 0 eingibt. Speichere das Dokument unter dem Namen taschenrechner.php. 2. Verändere das Diagramm-Skript (diagramm.php) so, dass die Säulen doppelt so lang sind wie in der bisherigen Variante. 3. Sorge außerdem dafür, dass der Inhalt der Formularfelder für die Eingabe der Zahlen nach dem Abschicken nicht gelöscht wird. 4. Berechne die Versandkosten für ein Produkt. Nutze dafür eine Seite, die du versand.php nennst. Das zu bestellende Produkt soll 20 Euro kosten. Erzeuge auf dieser Bestellseite also ein Formularfeld, in das der Nutzer die Produktanzahl eintragen kann. Liegt der Bestellwert unter 100 Euro, sollen die Versandkosten 10 Euro betragen. Liegt der Wert jedoch höher, fallen die Versandkosten auf 5 Euro. Gib den entsprechen-

      181

      Kapitel

      6

      Etwas Mathe: Taschen(geld)rechner den Gesamtpreis in Abhängigkeit von der eingetragenen Bestellmenge aus. (Wie du die Seite optisch aufbaust, bleibt dir überlassen.) 5. Öffne das Dokument mwst.php. Notiere hier eine zweite Funktion, die diesmal den Nettowert aus dem Bruttowert berechnet. Dazu erkundige dich, wie hoch die Mehrwertsteuer zur Zeit in Deutschland ist. Beachte, dass der Bruttowert bei 19 Prozent mit 119% angesetzt werden muss, wobei der Nettowert dann 100% beträgt. Bekommst du das hin mit dem Dreisatz?

      182

      7 Schleifen: Die »Gratulationsmaschine« Wenn mich einer fragt: »Was ist das Wichtigste beim Programmieren?« Dann antworte ich ohne zu zögern: Die Schleife. Denn erst mit Schleifen sorgst du dafür, dass Befehle immer und immer wiederholt werden können. Wie meistens gibt es auch diesmal einen Haken an der Geschichte. Schleifen gehören zu den nicht ganz einfach zu durchschauenden Elementen. Aus diesem Grund nähern wir uns dem Thema sanft und vorsichtig. Beispiele, Abbildungen und Diagramme sollen dir das Verständnis erleichtern. Du lernst in diesem Kapitel, wie du $ eine while-Schleife erstellst $ die do-while-Schleife nutzt $ eine for-Schleife erzeugst $ mit foreach alle Elemente eines Arrays durchläufst Und wenn du nach dem Lesen feststellst: »Schleifen, Mann: Das ist doch cool und easy!« – dann hat das Kapitel seinen Zweck erfüllt.

      183

      Kapitel

      7

      Schleifen: Die »Gratulationsmaschine«

      Die while-Schleife Wir fangen ganz gemütlich mit der while-Schleife an, werfen einen Blick auf do-while und landen dann bei for und foreach. Doch halt, was sind Schleifen überhaupt? Schleifen dienen dazu, eine Anweisung in Abhängigkeit von einer oder mehreren Bedingungen wiederholt ausführen zu können. Alles unklar? Kein Problem, das ging mir am Anfang auch so! Das Schlüsselwort lautet Wiederholung. Repetitio est mater studiorum, sagte mein alter Lateinlehrer immer. Frei übersetzt heißt das: Wiederholung ist die Mutter der Porzellankiste. (Zugegeben, das ist etwas zu frei übersetzt, aber auch Latein hat nie zu meinen Stärken gezählt.) Zurück zu den Schleifen. Ein Beispiel muss her! Was wiederholt sich in deinem Leben? Der Tag deiner Geburt! Wie alt bist du? 6, 14 oder gar 42 wie der Schreiber dieser Zeilen? Programmiere doch einmal eine Schleife, die den Satz wiederholt: Happy Birthday! Und zwar so oft, wie es deinem Alter entspricht.

      Der Quelltext für die Schleife Zuerst zeige ich dir den gesamten Quelltext zwischen den Tags . Du kannst das Dokument abschreiben und unter dem Namen while.php speichern.

      Die while-Schleife

      Wie alt bist du?

      \n"; $i++; }

      184

      Die while-Schleife echo "Schleife wurde verlassen.\n"; } ?>



      Probiere es aus. Funktioniert das mit der Wiederholung?

      Du gibst eine 6 ein? Dann schreibt das Skript sechsmal Happy Birthday!

      Einiges kommt dir sicher schon bekannt vor. Du erzeugst ein Formular zur Eingabe des Alters. Nach Absenden wird der Inhalt des Feldes anzahl abgeschickt und an den PHP-Teil übergeben. Dort kommt wieder unser bewährter Test zum Einsatz, der prüft, ob die Variable existiert und nicht etwa leer ist bzw. 0 entspricht. So weit, so bekannt. Doch was passiert innerhalb der Schleife, die eigentlich nur aus folgenden Zeilen besteht? while ($i <= $_POST['anzahl']) { echo "Happy Birthday!
      \n"; $i++;

      Hier wird die Wiederholung festgelegt, und zwar in Abhängigkeit von der eingegebenen Zahl! Was da genau abgeht, klären wir gleich.

      Die Grundsyntax der while-Schleife Schaue dir zuerst die Grundsyntax der while-Schleife an. while (Bedingung) { Befehlszeilen immer wieder ausführen, solange Bedingung wahr ist; } Fortsetzung, wenn Bedingung falsch;

      185

      Kapitel

      7

      Schleifen: Die »Gratulationsmaschine« Was fällt dir auf? Richtig: Auch hier dient wieder ein geschweiftes Klammernpaar zum Zusammenhalten des Schleifenblocks. Die erste Zeile bildet den Schleifenkopf. Hier wird die Bedingung geprüft. Zumindest die Struktur ist nicht neu, die kennst du ja schon von den if-Abfragen. (Wenn nicht, blättere ganz fix zwei Kapitel zurück!) Doch im Gegensatz zu if werden die Anweisungen innerhalb des Blocks stets wiederholt. Und zwar so lange, bis die Bedingung endlich einmal falsch geworden ist. Daraus folgt 0 Schleifen brauchen eine sinnvolle Bedingung, die sich auf Wahrheit prüfen lässt. 0 Du musst darauf achten, dass die Bedingung irgendwann wieder falsch wird. Bist du ein optischer Typ? Dann kannst du versuchen, dir die Wirkungsweise von while anhand dieses Diagramms zu veranschaulichen:

      Nur wenn die Bedingung wahr ist, werden die Befehle der Schleife ausgeführt.

      Beachte, dass die Befehle innerhalb der Schleife stets wiederholt werden. Das ist schließlich der Sinn der Sache. Sie werden so lange wiederholt, bis die Bedingung falsch ist.

      Das Beispiel in der Diskussion Und nun zu unserer Beispiel-Schleife. Schau dir zuerst die Zeilen an, die im weiteren Sinne zu unserer »Geburtstags-Schleife« zählen. Auch wenn sie nicht innerhalb des Schleifen-Blocks notiert wurden: 186

      Die while-Schleife $i = 1; while ($i <= $_POST['anzahl']) { echo "Happy Birthday!
      \n"; $i++; } echo "Schleife wurde verlassen.\n";

      Zuerst erzeuge ich eine Zählvariable $i, die ich gleich mit 1 initialisiere. Solch eine Variable benötigst du in der Regel. Schließlich musst du dafür sorgen, dass die Bedingung irgendwann wieder falsch wird. Zählvariablen werden gerne mit $i bezeichnet. Diese Benennung ist aber keinesfalls Pflicht. Du kannst deine Variable auch $zaehler, $kaugummi oder $fliegenschiss nennen. In der ersten eigentlichen Schleifenzeile wird nun die Bedingung überprüft. Der Test erfolgt also in dem eben erwähnten Schleifenkopf: while ($i <= $_POST['anzahl']) {

      Was wird hier geprüft? Es wird geprüft, ob $i kleiner gleich $_POST['anzahl'] ist, also kleiner gleich dem Wert, den du in das Formularfeld eingegeben hast. Nehmen wir einmal an, du hast eine 6 eingegeben! Die 1 ist kleiner gleich 6. Also wird der Code innerhalb der Schleife ausgeführt. Der Satz Happy Birthday wird nebst Zeilenumbruch in das Dokument geschrieben. echo "Happy Birthday!
      \n";

      Als nächstes wird die Zählvariable um 1 erhöht. Dafür kommt der im vorigen Kapitel besprochene Inkrementierungs-Operator ++ zum Einsatz: $i++; bedeutet so viel wie $i = $i + 1. In der Variablen $i ist nun der Wert 2 gespeichert. Der Schleifenblock ist zwar zu Ende, doch die Schleife prüft die Bedingung erneut auf Wahrheit: Das ganze Spielchen geht also von vorne los: Ist $i (nunmehr 2) immer noch kleiner gleich 6? Jawohl, das ist der Fall. Die Bedingung ist immer noch wahr und die Schleife kann wiederholt werden. Also wird der Satz Happy Birthday ein zweites Mal ausgegeben usw. usf. Erst nach dem 6. Durchlauf (ich wiederhole: danach!) gibt die Prüfung der Bedingung in unserem Falle falsch zurück. Warum? Das ist klar: Nach dem 187

      Kapitel

      7

      Schleifen: Die »Gratulationsmaschine« 6. Durchlauf hat $i den Wert 7 angenommen. Und der Vergleich 7 ist kleiner gleich 6 liefert nicht mehr wahr, sondern falsch. Damit wird die Schleife verlassen, ein siebter Durchlauf findet nicht statt. Jetzt wird der Satz unterhalb der Schleife angezeigt: echo "Schleife wurde verlassen.\n";

      Ganz wichtig: Achte unbedingt darauf, dass die Bedingung im Schleifenkopf irgendwann einmal falsch (false) zurückgibt. Denn sonst erzeugst du eine der berüchtigten Endlosschleifen. Die Endlosschleife läuft Amok, sie wird immer wieder und wieder ausgeführt, bis dein Rechner oder der Webserver im schlimmsten Fall nicht mehr reagiert!

      Gib auch die Zählvariable aus! Du hast das Prinzip verstanden? Sehr gut! Dann hast du in wenigen Stunden das geschafft, wofür der Autor dieses Buches Monate gebraucht hat! Zum Festigen schlage ich vor: Erweitere das eben erstellte »Geburtstagsskript« ein wenig. Gib zusätzlich die Zählvariable mit aus. Wandle den Satz Happy Birthday! einfach um in Happy Birthday, 1. Jahr! bzw. Happy Birthday, 2. Jahr! usw. usf.

      So verstehst du noch besser, was mit dem Zähler geschieht.

      Hast du die Lösung selbsttätig gefunden? Es ist ganz einfach! Ändere lediglich die echo-Zeile innerhalb der Schleife wie folgt: echo "Happy Birthday, $i. Jahr!
      \n";

      Du findest das Beispiel auch unter dem Namen whilecount.php im Ordner kapitel07 auf der CD zum Buch. 188

      Prüfung zu Fuß: do while

      Prüfung zu Fuß: do while Der Vollständigkeit halber erwähne ich noch die do-while-Schleife. Der Unterschied: Bei der while-Schleife wird die Bedingung im Schleifenkopf getestet, bei der do-while-Schleife dagegen im Schleifenfuß. Die Syntax sieht folgendermaßen aus: do { Befehlszeilen immer wieder ausführen, solange Bedingung wahr ist; } while (Bedingung); Fortsetzung, wenn Bedingung falsch;

      Im Klartext: Da die Bedingung erst im Schleifenfuß getestet wird, wird die Schleife mindestens einmal durchlaufen. Auch wenn die Bedingung von vornherein falsch ist. Das entsprechende Diagramm sieht folgendermaßen aus:

      Die Schleife wird mindestens einmal ausgeführt.

      Wenn du die vorige Datei auf do-while umbaust, kommt folgendes heraus, ich zeige dir zumindest den PHP-Bereich:

      189

      Kapitel

      7

      Schleifen: Die »Gratulationsmaschine«

      \n"; $i++; } while ($i <= $_POST['anzahl']); echo "Schleife wurde verlassen.\n"; } ?>

      Prüfe, ob meine Aussage stimmt. Gib einmal einen negativen Wert in das Feld ein. Die Schleife wird zumindest einmal durchlaufen! (Mit der 0 klappt es in unserem Fall allerdings nicht. Die 0 wird schließlich schon von unserer if-Abfrage mit empty() herausgefiltert!) Du findest das Beispiel in der Datei dowhile.php. Hilfe! Du hattest schon Probleme mit der while-Schleife und magst die do-while-Konstruktion überhaupt nicht? Ich mag sie auch nicht. Und ich habe sie in meiner ganzen Praxis wohl nur ein einziges Mal benötigt. Bleibe bei der while-Schleife. Mache dich jedoch unbedingt mit der nächsten Schleifengattung vertraut, lerne den Schleifentyp for.

      Der Bestseller: for Kommen wir nun zum Höhepunkt unserer »Schleifendiskussion«. Die beliebteste und wohl am häufigsten eingesetzte Schleife ist die for-Schleife. Diese Schleife wird gemeinhin als Zählschleife bezeichnet. Leider ist sie nicht ganz so einfach zu verstehen. Aber wir nehmen uns Zeit!

      Die Syntax von for am Beispiel erklärt Hier zeige ich dir zuerst die Grundsyntax der for-Schleife:

      190

      for (Zählvariable; Bedingung; Zählmuster) { Befehlszeilen immer wieder ausführen, solange Bedingung wahr ist; }

      Der Bestseller: for Zählvariable, Prüfung der Bedingung und das Festlegen des Zählmusters erfolgen gebündelt im Schleifenkopf. Diese Elemente werden in runden Klammern zusammengefasst und durch Semikolons voneinander abgegrenzt. Schau dir diesen besonderen Schleifenkopf etwas genauer an. Dazu wähle ich zur Verdeutlichung eine etwas ausführlichere Schreibweise: for (Zählvariable initialisieren; Bedingung abfragen; Zählmuster festlegen) { Befehlszeilen immer wieder ausführen, solange Bedingung wahr; }

      Soweit die Theorie. Jetzt zur Praxis. Nimm dir doch noch einmal das while-Beispiel vom Anfang des Kapitels vor! Hier fix der Quelltext, damit du nicht erst zurückblättern musst: $i = 1; while ($i <= $_POST['anzahl']) { echo "Happy Birthday, $i. Jahr!
      \n"; $i++; } echo "Schleife wurde verlassen.\n";

      Dieses while-Beispiel bauen wir jetzt zu einer for-Schleife aus. Zählvariable initialisieren Im while-Beispiel gibt es einen Zähler ($i), den ich mit 1 initialisiert habe. Dort wird also die Zählvariable initialisiert. Dafür sorgt die Zeile $i = 1;

      Diese Anweisung hatte ich oberhalb der Schleife notiert. Sie gehört zwar nicht direkt zum Schleifenblock dazu, ist aber wichtig. Bedingung abfragen Die Bedingung selber wird im Schleifenkopf geprüft, sie lautet $i <= $_POST['anzahl']

      Zählmuster festlegen Außerdem habe ich ein Zählmuster festgelegt. Der Zähler wurde innerhalb der Schleife inkrementiert, also um 1 erhöht. Diese Anweisung sieht so aus: $i++;

      191

      Kapitel

      7

      Schleifen: Die »Gratulationsmaschine« Soweit also das schon bekannte while-Beispiel. Alles das wird in der forSchleife nun im Schleifenkopf zusammengefasst, also an einer zentralen Stelle. Daraus ergibt sich im Beispiel folgende kompakte Notation. for ($i = 1; $i < = $_POST['anzahl']; $i++) { echo "Happy Birthday, $i. Jahr!
      \n"; }

      Zugegeben, bei einer while-Schleife sind alle diese Elemente etwas verstreut, aber das Prinzip ist das gleiche. In den meisten Fällen ist es egal, ob du while oder for verwendest. Ich empfehle die for-Konstruktion, weil sie so schön »aufgeräumt« ist. Es gibt jedoch einige seltene Fälle, wo du vor allem mit while glücklich wirst. Beispiele dafür findest du im Datenbankteil, wenn MySQL-Tabellen abgefragt werden.

      Die for-Schleife ist der komfortabelste Schleifentyp.

      Du findest das Beispiel in der Datei for.php auf der CD zum Buch.

      Und die Geburtstagskerzen?

      192

      Feierst du gerne Geburtstag? Mit Party, Torte und Kerzen? Kerzen – das ist genau das Stichwort. Ich möchte in diesem Kapitel noch mehr »Geburtstagsstimmung« verbreiten und ein paar »Kerzen anzünden«. Und zwar für jedes Jahr eine. Wir stellen die Kerzen schön ordentlich nebeneinander.

      Und die Geburtstagskerzen? Egal, ob dich das Beispiel vom Hocker reißt oder nicht. Du lernst, wie du mit einer Schleife eine Grafik mehrfach einfügen kannst und gleichzeitig die Zellen einer Tabelle dynamisch erzeugst.

      Wie alt bist da? Dank einer Tabelle stellt das Skript für jedes Jahr eine Kerze auf.

      Tabelle dynamisch erzeugen Nimm das vorhandene for-Schleifen-Beispiel aus der Datei for.php. Auch hier benötigen wir das Formularfeld für die Eingabe des Alters. Ich speichere die Datei unter einem anderen Namen, im Beispiel unter dem Namen kerzen1.php. Für das Beispiel habe ich eine kleine Abbildung vorbereitet, die 12 Pixel breit und 50 Pixel hoch ist. Sie heißt candle.gif. Du findest sie auf der CD zum Buch, und zwar im Ordner beispiele/kapitel07. Du kannst aber auch jede andere Grafik verwenden, solange diese nicht zu breit ist Und hier zeige ich dir nun den gesamten Teil zwischen den Tags :

      Elektronische Geburtstagskerzen

      Wie alt bist du?
      \n"; for ($i = 1; $i <= $_POST['anzahl']; $i++) { echo "Kerze\n"; } echo "\n"; } ?>

      193

      Kapitel

      7

      Schleifen: Die »Gratulationsmaschine« Das Prinzip ist nicht schwer zu verstehen. Das Grundgerüst der Tabelle entsteht erst einmal außerhalb der Schleife. Diese Zeile leitet die Tabelle ein: echo "\n";

      und diese Zeile schließt die Tabelle: echo "
      \n";

      Die Schleife selber macht nun nichts weiter, als die einzelnen Zellen zu erzeugen. In Abhängigkeit vom eingegebenen Alter wird folgende Passage mehr oder weniger oft wiederholt: echo "Kerze\n";

      Fertig ist die »Kerzenlinie«. So einfach kannst du mit einer Schleife also auch dynamische Inhalte erstellen! Das Beispiel eignet sich übrigens ganz fabelhaft zum Erstellen eines attraktiven Säulendiagramms. Du willst die Verkaufszahlen eines Produktes darstellen, z. B. deiner selbst gekochten Kaugummis? Dann kannst du die Säule einfach aus kleinen Abbildungen deiner Produkte zusammensetzen! Hatte es einen tieferen Sinn, dass ich ausgerechnet eine Tabelle schreibe? Hätte ich das Skript nicht verkürzen und den ganzen -\n"; if ($i >= 108) { break; } }

      Ich habe die Variable $i (siehe Pfeil) nur deshalb mit eingefügt, damit du die Zählung überprüfen kannst! Entferne sie einfach, wenn sie dich stört.

      Und noch eine Schleife: foreach Zum Schluss stelle ich dir noch eine wirklich tolle Schleifenkonstruktion vor. Ich präsentiere dir hier an dieser Stelle ganz exklusiv die … foreachSchleife!

      195

      Kapitel

      7

      Schleifen: Die »Gratulationsmaschine«

      Schleife für Wertelisten Die foreach-Schleife durchläuft ein Array und gibt die dort gespeicherten Werte zurück. Auf diese Art und Weise kannst du nacheinander alle Werte eines Arrays ermitteln. Zur Erinnerung: Ein Array ist eine Werteliste, bei der mehrere Werte in einer Variablen gespeichert werden. Zum Ermitteln des einzelnen Wertes dient der jeweilige key, der Schlüssel. Es gibt Arrays mit einem numerischen key. Hier werden die einzelnen Werte mit 0 beginnend hochgezählt. Weiterhin gibt es die assoziativen Arrays mit einer Zeichenfolge als key. Der key trägt hier meist eine Bedeutung und ist daher im Gegensatz zur Nummer meist viel interessanter. Probiere es zuerst bei einem »herkömmlichen« Array, bei dem dich der numerische key nicht so dringend interessiert. Wenn du auf die Ausgabe des keys verzichtest, sieht die Syntax von foreach so aus: foreach ($Arrayname as $value) { echo "$value
      \n"; }

      Das Wort $Arrayname steht hierbei nur als Platzhalter für den Namen der Werteliste. Die echo-Zeile dient lediglich als Vorschlag. Du kannst die Ausgabe natürlich noch besser verpacken. Wichtig ist jedoch die Zeichenfolge $value, welche den Wert ausgibt.

      Wochentage: Nur den value ausgeben Zu theoretisch? Ein Beispiel muss her! Erinnerst du dich noch an das Wochentage-Beispiel von Kapitel 4? Mal sehen ob es dir gelingt, alle Werte aus dem Array $tag fein säuberlich auszugeben.

      196

      Wochentage ausgeben mit foreach


      Und noch eine Schleife: foreach foreach ($tag as $value) { echo "$value
      \n"; } ?>



      Bei dieser ersten Variante wird der Wert (value) ausgegeben, nicht der key, der sogenannte Schlüssel. Wie schon erwähnt, der key ist im ersten Fall nicht so umwerfend wichtig, entspricht er doch der Index-Nummer.

      Alle Werte aus dem Array werden ausgegeben!

      Du findest das Beispiel unter dem Namen foreach1.php auf der CD zum Buch. Die Zeichenfolge foreach kann mit für jedes übersetzt werden. Die Schleife gilt also für jedes Element im Array, sie liest alle Elemente aus.

      Hauptstädte: key und value gemeinsam ausgeben Viel interessanter wird die Geschichte bei assoziativen Arrays. Also bei der Array-Gattung, bei der auch der key eine Bedeutung trägt und nicht nur eine langweilige Nummer ist. Dann lohnt es sich auch, den key zu ermitteln. Die Grundsyntax von foreach wird dafür etwas erweitert: foreach ($Arrayname as $key => $value) { echo "$key = $value
      \n"; }

      Auch hier dient die echo-Zeile lediglich als Ausgabe-Vorschlag. 197

      Kapitel

      Schleifen: Die »Gratulationsmaschine«

      7

      Bei dieser Variante wird sowohl der key als auch der value ausgegeben.

      Probiere auch diese Variante am Beispiel aus.

      Hauptstädte: key und value ermitteln

      $value) { echo "$key = $value
      \n"; } ?>



      Fabelhaft! Das Array liefert dir alle Schlüssel-Werte-Paare aus dem Array. Vergleiche mit der Datei foreach2.php von der CD zum Buch. Übrigens bist du nicht auf die Bezeichnungen $key und $value festgelegt – das ist nur ein Vorschlag. Du kannst auch $schluessel und $wert oder etwas anderes einsetzen. Vergleiche mit der Datei foreach3.php, wo ich diese individuelle Variante verwendet habe. Natürlich kannst du die Ausgabe bei echo stets an deinen Geschmack anpassen. Kleide die Variablen $key und $value und $schluessel und $wert beispielsweise in Sätze ein. Gib die Daten in Tabellenzellen aus usw. usf. Besonders wichtig ist diese Technik bei der Auswertung von Formularen, denn Formulare sind ein assoziatives Array, welches aus Attribut-Werte-Paaren (key-value-Paaren) besteht. Das Array selber heißt $_POST. Der Wert (key) ist der Name des Formularfeldes. Genau dieses Wissen brauchst du im nächsten Kapitel! 198

      Schlussbemerkung

      Schlussbemerkung In diesem Kapitel hast du die Schleifen kennengelernt, die praktischen »Wiederholmodule« einer Programmiersprache. Egal ob while, for oder foreach: Vielleicht hast du ja die Erfahrung gemacht, dass Schleifen gar nicht so kompliziert sind, wie der Autor behauptet hatte? Wie auch immer, mit diesem Kapitel ist der Grundlagenteil des Buches abgeschlossen. Fortgeschrittene Programmieraufgaben sowie kleine als auch größere Projekte warten auf dich!

      Zusammenfassung 0 Du kennst das Konzept von Schleifen. Hier werden Befehlszeilen in Abhängigkeit von einer oder mehreren Bedingungen wiederholt. 0 Die while-Schleife wird ausgeführt, solange die Bedingung wahr ist. Die Prüfung findet im Schleifenkopf statt. 0 Bei der do-while-Schleife findet die Prüfung erst im Schleifenfuß statt. Deshalb wird die Schleife auch dann einmal durchlaufen, wenn die Bedingung von Anfang an falsch ist. 0 Du weißt, dass du bei Schleifen immer eine Abbruchbedingung vorsehen musst, damit es nicht zu einer Endlosschleife kommt. 0 Du kennst die for-Schleife (Zählschleife). Hier erfolgen Initialisierung der Zählvariable, Test der Bedingung und Festlegen des Zählmusters direkt im Schleifenkopf. 0 Du kennst das Schlüsselwort break, welches zum Abbruch einer Schleife führt. 0 Du kennst die foreach-Schleife, die ein Array durchläuft und auf Wunsch key und value zurückgibt.

      Ein paar Fragen … 1. Bei welchem Schleifentyp erfolgt der Test der Bedingung im Schleifenfuß? 2. Mit welchem Schlüsselwort erreichst du, dass eine Schleife abgebrochen wird?

      199

      Kapitel

      7

      Schleifen: Die »Gratulationsmaschine« 3. Wie heißt der Schleifentyp, mit dem man ein Array durchlaufen und key und value zurückgeben kann? 4. Was bedeutet $i++ und wie nennt man diese Operation?

      … und ein paar Aufgaben 1. Erstelle eine for-Schleife, die alle ungeraden Zahlen zwischen 2 und 16 nebeneinander ausgibt. Nenne die Datei ungerade1.php.

      So soll es aussehen: Die ungeraden Zahlen stehen nebeneinander.

      2. Versuche, das Gleiche mit einer while-Schleife zu erreichen. Nenne die Datei ungerade2.php. 3. Erstelle ein Dokument namens anzeigen.php. Hier sollen per Formular folgende Besucherdaten erfragt werden: Vorname, Name, Str, PLZ, Ort und Email. Nutze diese Bezeichnungen für die Bennennung der Formularfelder. Nach Klick auf ABSENDEN sollen alle Benutzerdaten auf der gleichen Seite noch einmal eingeblendet werden. Verwende dafür eine foreach-Schleife. Tipp: Denke daran, dass das Array eines mit method="post" erzeugten Formulars $_POST heißt!

      200

      8 Fürs Feedback: Formmailer selbst gestrickt Feedback! Danach sehnen sich wohl die meisten Betreiber einer Webseite. Du lernst in diesem Kapitel, wie du $ die Funktion mail() zum Versenden von E-Mails einsetzt $ der Botschaft einen Datums- und Zeitstempel aufdrückst $ ein Feedback-Formular programmierst $ die Daten vor dem Absenden überprüfst (validierst) $ einen Universal-Formmailer erstellst, der praktisch jedes Formular versendet Im gesamten Kapitel müssen wir die Zeichensatzkodierung der HTMLDatei ausnahmsweise auf ISO-8859-1 ändern! UTF-8 bereitet Probleme, Umlaute und Sonderzeichen kommen beim Empfänger möglicherweise verstümmelt an! Ersetze utf-8 stets durch iso-8859-1 Wähle dann in PSPad FORMAT|ANSI. Außerdem gilt: Die Skripte dieses Kapitels funktionieren nur richtig, wenn du sie online testest! Zumindest der Sende-Teil wird nur auf dem Webserver deines Dienstleisters funktionieren! Dein lokaler Computer kann mit der Funktion mail() in der Regel nicht umgehen und produziert eine Fehlermeldung!

      201

      Kapitel

      8

      Fürs Feedback: Formmailer selbst gestrickt

      Die Funktion mail() Sicher kennst du die klassische Feedback-Lösung – den E-Mail-Link. Erstelle einen mailto-Verweis, auf den man klicken und dir eine Mail schreiben kann. Die Syntax ist dir sicher vertraut: Schreibe mir!

      Genauso vertraut sind dir sicher auch die großen Nachteile dieser Methode. Damit es funktioniert, muss der Benutzer ein korrekt installiertes Mailprogramm verwenden. Das ist aber nicht immer der Fall, vor allem nicht in Internetcafés! Ein weiterer Nachteil wiegt viel schwerer: Die »internationale Spam-Mafia« ergaunert solche Adressen und müllt dich in Folge mit unsinnigen Werbemails zu. Ich rate deshalb inzwischen von der mailto-Variante ab. (Eine E-Mail-Adresse solltest du auf deiner Webseite möglichst nur noch als »verschlüsselten Text« mit Leerzeichen, fehlenden Zeichen bzw. Füllzeichen oder sogar als »Text-Grafik« ablegen!)

      Lösung mit PHP Wir lernen etwas Besseres: nutze PHP! Denn so kannst du Daten per E-Mail verschicken, ohne dass deine E-Mail-Adresse im Klartext übermittelt wird. Dabei wird ein Mailprogramm verwendet, welches dein Dienstleister für dich bereithält. 0 Beachte allerdings, dass alle Skripte dieses Kapitels nur dann vollständig funktionieren, wenn du sie online testest! Zumindest der Sende-Teil wird nur auf dem Webserver deines Dienstleisters funktionieren. Dein lokaler Computer kann mit der Funktion mail() in der Regel nicht umgehen und produziert eine Fehlermeldung! Zuerst zeige ich dir, wie simpel das Versenden einer E-Mail in PHP eigentlich ist. Dafür benötigst du lediglich die Funktion mail(). Diese Funktion verschickt – nomen est omen – eine E-Mail an die angegebene Adresse. Diese Funktion besitzt folgende Grundsyntax: mail("Empfängeradresse", "Betrefftext", "Botschaft", "From: Absenderadresse")

      202

      Du kannst alle Argumente direkt in die Funktion eintragen oder aber durch Variablen darstellen. Wichtig: Diese Werte müssen dem Datentyp String

      Die Funktion mail() entsprechen. Setze sie also im Zweifelsfalle in Gänsefüßchen! Oder achte darauf, dass die entsprechende Variable für das jeweilige Argument dem Datentyp String entspricht.

      Bei Aufruf der Seite: E-Mail! Wie wäre es mit dem ersten Beispiel? Das nun folgende PHP-Dokument verschickt immer dann eine E-Mail, wenn der Surfer die entsprechende Seite aufruft. Weil es so simpel ist, zeige ich dir den gesamten Quelltext. Du findest das Dokument unter dem Namen infomail.php auf der CD zum Buch. Info-Mail verschicken <meta http-equiv="content-type" content="text/html; charset=iso-8859-1">

      Diese Seite verschickt eine Info-Mail



      Achtung! Ersetze »utf-8« durch »iso-8859-1«! Wähle in PSPad außerdem FORMAT|ANSI!

      Schaue dir die Funktion mail() etwas genauer an. Als erstes Argument gibst du natürlich statt [email protected] deine eigene E-Mail-Adresse an. Der Wert der Variablen $Email wiederum ist nur ein Platzhalter. Schließlich kannst du bei diesem Skript die E-Mail-Adresse des Surfers nicht ermitteln. Trotzdem verlangt die Funktion irgendeine Absenderadresse. In der Variablen $mailbody speicherst du den Text, welchen die E-Mail an dich schickt. Es ist der »Body« der E-Mail, wenn du so willst. Lade die Seite auf den Server und probiere es aus. Bei jedem Hit bekommst du nun eine E-Mail geschickt mit dem Text Soeben hat jemand deine Seite angeklickt.

      203

      Kapitel

      8

      Fürs Feedback: Formmailer selbst gestrickt

      Hilfe, bei dir funktioniert das Skript nicht, es gibt nur Fehlermeldungen? Bitte vergiss nicht, dass alle Beispiele dieses Kapitels nur dann funktionieren, wenn du die Datei vorher auf den Server lädst. Dein Dienstleister sollte außerdem das serverseitige Mailen unterstützen. Auf deinem lokalen System funktioniert mail() in aller Regel nicht und gibt daher einen Fehler zurück!

      mail() läuft nicht auf

      dem lokalen System, es gibt eine Fehlermeldung!

      E-Mail mit Datums- und Zeitstempel Eine simple E-Mail pro Besuch reicht dir nicht? Du wünschst mehr Informationen? Kein Problem! Ermittle zum Beispiel Datum und Uhrzeit des Besuches. Dazu erzeugst du zusätzlich einen Datums- und Zeitstempel. So weißt du auch ganz exakt, wann der Besucher bei dir vorbeigeschaut hat. Erinnerst du dich? Zum Ausgeben von Datum und Uhrzeit verwendest du die Funktion date() mit den entsprechenden Argumenten. Du möchtest das Datum nach dem Motto ausgeben Tag (1-31), Monat (1-12) und Jahreszahl (vierstellig)? Dann verwendest du die folgende Syntax: echo date("j.n.Y"). Einen Zeitstempel mit Stunden (24 h-Format), Minuten und Sekunden erzeugst du dagegen mit echo date("H:i:s").

      Der Quelltext im Überblick Das nun folgende Beispiel verschickt die E-Mail mit Datums- und Zeitstempel. Ich zeige dir den PHP-Teil der Datei mailstempel.php:

      204


      Das Feedback-Formular $mailbody = "Am $datum um $zeit Uhr hat jemand deine Seite angeklickt!"; mail("[email protected]", "Ein Besucher", $mailbody, "From: $Email"); ?>

      Probiere es aus: Lade das Dokument auf den Server und rufe es auf. Schaue dann in deinen Posteingang.

      Warum nicht: E-Mail mit Datums- und Zeitstempel.

      Hat es funktioniert? Wunderbar. Das war nur eine Übung. Zeit für ein etwas fortgeschritteneres Beispiel!

      Das Feedback-Formular Jetzt kommt der erste Höhepunkt dieses Kapitels. Du erstellst ein Feedback-Formular. Der Besucher kann seine E-Mail-Adresse und einen Kommentartext eingeben. Auf Knopfdruck wird der Inhalt an dich abgeschickt.

      Erzeuge ein Formular zur Entgegennahme von Feedback.

      TEXTAREA: Ideal für Kommentare Ich zeige dir zuerst den kompletten HTML-Quelltext des PHP-Dokuments mitsamt Formular. Den PHP-Teil fügen wir hinterher gemeinsam ein. Nenne das Dokument feedback.php und ergänze es Schritt für Schritt. So erzeugen wir ein sicheres Formular, das auch für das Web geeignet ist!

      205

      Kapitel

      8

      Fürs Feedback: Formmailer selbst gestrickt

      Feedback-Formular <meta http-equiv="content-type" content="text/html; »iso-8859-1« statt »utf-8« charset=iso-8859-1">

      Feedbackformular

      E-Mail-Adresse:
      Kommentar:



      Hier kommt der PHP-Teil hin

      Dieses Dokument enthält neben zwei INPUT-Feldern eine Besonderheit. Beachte das große »Kommentarfeld«. Dieses Feld wird vom Tag-Paar umschlossen. Es ist wie geschaffen für große Texteingabebereiche. Apropos Größe: Mit dem Attribut cols (Spalten) legst du die Breite des Feldes in Zeichen fest. Ich habe mich für 50 Zeichen entschieden. rows (Zeilen) steuert dagegen die Zeilenzahl, im Beispiel 5. Denkst du an iso-8859-1 statt utf-8? Hast du die Kodierung der Datei auch von UTF-8 auf ANSI geändert (PSPad: FORMAT|ANSI)?

      Der PHP-Teil Nun baust du den Formmailer zusammen. Schließlich fehlt der PHP-Teil zum Versenden! Füge folgende Zeilen ein, und zwar zwischen dem abschaltenden -Tag und dem Tag :

      206



      Professionell mailen: Fehler unterdrücken Das genügt. Zuerst prüfst du mit if, ob das Feld Email zurückgeschickt wurde und nicht leer geblieben ist. Dann schickst du den Formularinhalt mit mail() auf die Reise. Da die einzelnen Argumente von mail() Strings sein müssen, wird z. B. die Zeichenfolge From: $_POST[Email] in Gänsefüßchen eingekleidet. Deshalb darfst du den key des Array-Eintrags aus $_POST ausnahmsweise nicht in Gänsefüßchen schreiben! Schreibe also $_POST[Email] statt $_POST['Email']. Diese gänsefüßchenfreie Schreibweise ist immer dann notwendig (und zulässig), wenn die Array-Variable selber innerhalb eines Gänsefüßchen-Paars steht. Ansonsten solltest du den key je nach Geschmack stets mit einfachen bzw. doppelten Gänsefüßchen umkleiden, wie ich es z. B. bei $_POST['botschaft'] getan habe. Meine Version findest du unter dem Namen feedback1.php auf der CD zum Buch – es ist der erste Stand. Lade das Skript doch einmal auf den Server und probiere es aus. Klappt die Formularauswertung?

      Professionell mailen: Fehler unterdrücken Das Skript besitzt bisher etliche Schönheitsfehler! Den ersten Schönheitsfehler merkst du, wenn du das Beispiel offline ausprobierst, also auf deinem heimischen Rechner. Da das Mailen hier nicht funktioniert, hagelt es eine kryptische Fehlermeldung. Solch eine Fehlermeldung kann aber auch auftreten, wenn der Mailer deines Dienstleisters gerade überlastet ist.

      Zeichen @ zur Fehlerunterdrückung Vielen Funktionen kannst du das Zeichen @ voranstellen. Dadurch werden Fehler unterdrückt. Notiere statt mail() einfach @mail(). Stelle der mail()-Funktion im Beispiel nun das @-Zeichen voran. Probiere das Skript offline aus. Wunderbar, die Fehlermeldung ist weg. Aber der Nutzer wiegt sich in dem Glauben, sein Kommentar wäre abgeschickt worden. Offenbar war diese eine Maßnahme doch noch nicht der Weisheit letzter Schluss. Und tatsächlich gibt es einen weiteren Trick.

      207

      Kapitel

      8

      Fürs Feedback: Formmailer selbst gestrickt

      Rückgabewert der Funktion mail() testen Viele Funktionen geben einen Wahrheitswert zurück. Bei Erfolg ist es der Wert true, bei Misserfolg der Wert false. So auch bei unserem Star des Kapitels, der Funktion mail(). Die Funktion mail() gibt bei erfolgreichem Versand den Wert true zurück. Wenn der Versand fehlschlägt, wird der Wahrheitswert false zurückgegeben. Diese Eigenschaft solltest du nutzen, um Fehler abzufangen! Zeige dem Besucher eine Bestätigung an, wenn der Versand geglückt ist. Informiere im Gegenzug auch über einen Misserfolg! Der derart erweiterte PHP-Teil sieht so aus: Danke! Die Botschaft wurde weitergeleitet!

      \n"; } else { echo "

      Leider gab es einen Sendefehler!

      \n"; } } ?>

      Die kryptische Fehlermeldung wird unterdrückt und durch eine sinnvolle ersetzt.

      Wie du siehst, werden hier zwei if-Abfragen ineinander geschachtelt. Die innere if-Abfrage testet, ob mail() erfolgreich war. Wenn ja, sieht der Nutzer die Meldung Danke! Die Botschaft wurde weitergeleitet. Bei Misserfolg greift der else-Zweig und informiert über den Sendefehler. Diese Version des Feedback-Formulars findest du in der Datei feedback2.php. 208

      Professionell mailen: Fehler unterdrücken

      Mehr Variablen für eine klarere Struktur! Ich fürchte, dass uns an dieser Stelle der Hund Buffi noch etwas zu sagen hat. Er scheint mit der bisherigen Fassung des Skripts noch nicht zufrieden zu sein. Der Autor versucht, das Skript kurz zu fassen. Das scheint das Problem vieler sogenannter »genialer Programmierer« zu sein: Sie kürzen wo es geht, und zwar auf Kosten der Klarheit. Ich schlage dir vor, das Skript auf mehr Zeilen aufzuteilen. Füge für E-Mail-Adresse und den Kommentar zusätzliche Variablen ein. Das erzeugt zwar etwas längeren Code, schafft aber eine klarere Struktur! Ich zeige dir meine Version des PHP-Teils, damit du siehst, was ich meine. Danke! Die Botschaft wurde weitergeleitet!

      \n"; } else { echo "

      Leider gab es einen Sendefehler!

      \n"; } } ?>

      Hinzugekommen sind die Variablen $mailbody und $Email. In diesen speichere ich zuerst den Inhalt aus den zwei Formularfeldern ab. Dann brauche ich innerhalb der Funktion mail() nicht mehr mit den »Monstern« $_POST['Email'] und $_POST['botschaft'] zu arbeiten. Außerdem kannst du den Inhalt der Formularfelder einfacher bearbeiten und ergänzen. Beispielsweise, wenn du weitere Daten in der Variable $mailbody sichern möchtest, und nicht nur den Inhalt des Kommentarfeldes namens botschaft. Diese Version findest du in der Datei feedback3.php. 209

      Kapitel

      8

      Fürs Feedback: Formmailer selbst gestrickt

      Formular um ein Name-Feld erweitern Einverstanden, der Hund hat Recht. Mehr Klarheit kann nicht schaden. Ich habe seinen Tipp beherzigt und mein Skript um die beiden Variablen erweitert. Damit bin ich tatsächlich viel flexibler. So kann ich nun das Formular problemlos z. B. um ein Name-Feld erweitern!

      Füge ein Feld für den Namen ein!

      Das ist ganz einfach. Mach mit! Ergänze im Formularbereich folgende Zeile: Name:


      Gehe nun in den PHP-Bereich. Ersetze diese eine Zeile: $mailbody = $_POST['botschaft'];

      durch folgende zwei Zeilen: $mailbody = $_POST['Name'] . " schrieb\n\n"; $mailbody .= $_POST['botschaft'];

      Die Zeichen \n\n sind sicher klar. Sie sorgen für zwei zusätzliche Zeilenumbrüche im Text der E-Mail. So bleibt in der Mail zwischen Name und dem Kommentartext eine Leerzeile. Doch was bedeutet das Zeichen .=?

      Kurzform für das Verketten Es handelt sich um eine Kurzform für das Verketten. Diese Zeile entspricht eigentlich folgender Zeile $mailbody = $mailbody . $_POST['botschaft'];

      210

      Backslashes entfernen mit stripslashes() Mit diesem raffinierten »Verkürzungsoperator« ersparen sich die schreibfaulen Programmierer das doppelte Schreiben einer Variablen: $mailbody .= $_POST['botschaft'];

      Wenn man sich an diesen praktischen Operator einmal gewöhnt hat, möchte man ihn bald nicht mehr missen! (Allerdings dauert es eine Weile, ehe man sich daran gewöhnt hat.) Die bisherige Fassung findest du in der Datei feedback4.php.

      Backslashes entfernen mit stripslashes() Das Skript besitzt trotzdem noch einen Schönheitsfehler. Dieser ist jedoch nicht gleich offensichtlich: Gib zur Probe einmal einen Kommentartext ein, der einfache oder doppelte Gänsefüßchen enthält. Schließlich soll es vorkommen, dass der Besucher derartige Zeichen einsetzt. Auch bei einem Namen kann z. B. das einfache Gänsefüßchen vorkommen. Denke an den schönen irischen Namen O’Hara.

      Gänsefüßchen werden manchmal automatisch durch einen Backslash maskiert.

      Wie du der abgebildeten Mail entnehmen kannst, werden diese Zeichen automatisch maskiert – zumindest bei einigen Webhostern. Sie werden »escaped«, es wird ein Backslash vorangestellt. Aus dem Eingabetext Ich wünsche dir "viel Glück"!

      wird in der E-Mail z. B.: Ich wünsche dir \"viel Glück\"!

      Ist das bei dir auch der Fall? Wenn nicht, hast du Glück mit deinem Hoster! Falls doch – kein Problem dank der Funktion stripslashes().

      211

      Kapitel

      8

      Fürs Feedback: Formmailer selbst gestrickt

      Die Funktion stripslashes(($Variable) entfernt alle Backslashs aus einem String und gibt den bereinigten String zurück. Ich ergänze unterhalb dieser Zeilen: $mailbody = $_POST['Name'] . "schrieb\n\n"; $mailbody .= $_POST['botschaft'];

      einfach folgende Zeile: $mailbody = stripslashes($mailbody);

      Und schon wird in $mailbody der »bereinigte String« gespeichert und kann an die mail()-Funktion übergeben werden. Probiere es aus! Die Backslash-Zeichen sind weg! Ich zeige es dir in der Datei feedback5.php. Das eben gezeigte Problem hat etwas mit einer PHP-Einstellung namens magic_quotes_gpc zu tun. Früher stand dieser »magische Schalter« bei den meisten Dienstleistern auf »On«, die Backslashes wurden also stets automatisch hinzugefügt. Inzwischen wird dieser »Schalter« meist auf »Off« geschaltet, auch XAMPP macht das so. Nicht ohne Grund, denn die »magic quotes« sind ein Auslaufmodell! Zum Glück! Mehr zu den Vorund Nachteilen der »magic quotes« verrate ich dir auf Seite 351.

      Prüfen! Sind alle Felder ausgefüllt? Wünschst du dir ein Feedback-Formular mit allen Schikanen? Prüfe, ob alle Felder ausgefüllt sind. Gib bei jedem einzelnen Feld eine gezielte Fehlermeldung aus nach dem Motto Die E-Mail-Adresse fehlt. Ich zeige es dir wieder Schritt für Schritt:

      >

      Ergänze den SUBMIT-Button im Formularfeld. Notiere im Tag zusätzlich das Attribut-Werte-Paar name="submit". Damit verpasst du auch diesem Knopf einen Namen, den du im PHP-Teil auswerten kannst. Ich habe die Ergänzung fett hervorgehoben

      > 212

      Schaue nun in den PHP-Teil. Bisher findest du dort innerhalb von folgende Codezeilen:

      Prüfen! Sind alle Felder ausgefüllt? if (!empty($_POST['Email'])) { $mailbody = $_POST['Name'] . "schrieb\n\n"; ... usw. ...; echo "

      Leider gab es einen Sendefehler!

      \n"; } }

      >

      Entferne die erste und die letzte Zeile (siehe Pfeil). Diese auf das E-Mail-Feld bezogene if-Abfrage brauchst du für die nächste Version nicht mehr. Sie wird ersetzt durch eine if-Abfrage, die sich auf den SUBMIT-Button bezieht. Schließlich soll die Namensgebung name="submit" nicht umsonst gewesen sein.

      >

      Erweitere nun den Bereich innerhalb von wie folgt. Für die eben um zwei Zeilen »gestutzten« Mailer-Zeilen habe ich Auslassungszeichen ... notiert: if (isset($_POST['submit'])) { $fehler = false; $fehlertext = ""; if (empty($_POST['Name'])) { $fehler = true; $fehlertext .= "Der Name fehlt!
      \n"; } if (empty($_POST['Email'])) { $fehler = true; $fehlertext .= "Die E-Mail-Adresse fehlt!
      \n"; } if (empty($_POST['botschaft'])) { $fehler = true; $fehlertext .= "Das Kommentar-Feld muss ausgefüllt werden!
      \n"; } if ($fehler) { echo "

      $fehlertext

      "; } else { ... hier steht der Mailbereich ... } }

      213

      Kapitel

      8

      Fürs Feedback: Formmailer selbst gestrickt Probiere das Skript aus, indem du mal das eine, mal das andere Feld frei lässt.

      Der Nutzer wird gezielt auf fehlende Felder hingewiesen!

      Der Quelltext im Überblick Ich fürchte, dass hier einiger Erklärungsbedarf besteht. Gut, fangen wir außen an. Der gesamte PHP-Teil wird nun von folgender if-Abfrage umspannt: if (isset($_POST['submit'])) { ... }

      Hier prüft das Skript, ob das Formular überhaupt abgeschickt wurde. Nur dann ist die Variable $_POST['submit'] gesetzt. Zur Erinnerung: Diese Variable entsteht, da der SUBMIT-Button einen Namen bekommen hat. Doch was passiert in diesen zwei Zeilen? $fehler = false; $fehlertext = "";

      Hier werden zwei Variablen deklariert und gleich initialisiert, also mit Werten gefüttert. Die erste Variable namens $fehler ist eine sogenannte Flag-Variable. Es ist tatsächlich ein »kleines Fähnchen« (Flag wie Flagge), welches im Erfolgsfalle – also wenn ein Fehler auftaucht – gehisst wird. Doch zuerst hisse ich noch gar nichts. Ich gehe davon aus, dass dem Benutzer kein Ausfüll-Fehler unterlaufen ist und initialisiere die Variable deshalb mit dem Wahrheitswert false. 214

      Prüfen! Sind alle Felder ausgefüllt? Die zweite Variable $fehlertext wird einfach mit einem Leerstring gefüttert. Später soll in dieser Variablen der Fehlertext gespeichert werden. Dieser wird je nach Anzahl der falsch oder gar nicht ausgefüllten Felder kürzer oder länger. Nun erfolgt der erste Test: if (empty($_POST['Name'])) { $fehler = true; $fehlertext .= "Der Name fehlt!
      \n"; }

      Hier prüft das Skript, ob das Feld Name leer gelassen wurde. Wenn ja, ist das ein Fehler. Die Flag-Variable $fehler wird deshalb auf true geschaltet. Es ist wahr, dass ein Fehler vorgekommen ist, unser Fähnlein »flattert im Wind«. Außerdem wird die Variable $fehlertext mit einem Fehlertext nebst Zeilenumbruch gespeist. Wie du siehst, verwende ich hier wieder die Kurzform für das Verketten. Diese Zeile entspricht eigentlich folgender Zeile: $fehlertext = $fehlertext . "Der Name fehlt!
      \n";

      Jetzt wird auch klar, warum ich die Variable $fehlertext am Anfang schon mit einem Leerstring initialisiert hatte. Es muss schon etwas da sein, wenn ich eine Variable mit sich selbst verketten möchte. Die nächsten beiden if-Blöcke prüfen nun, ob das E-Mail-Feld oder das Feld für den Kommentar nicht etwa leer geblieben sind. Falls das so ist, wird auch hier wieder die »Fehlerflagge gehisst« und ein »Fehlertext« notiert. if (empty($_POST['Email'])) { $fehler = true; $fehlertext .= "Die E-Mail-Adresse fehlt!
      \n"; } if (empty($_POST['botschaft'])) { $fehler = true; $fehlertext .= "Das Kommentar-Feld muss ausgefüllt werden!
      \n"; }

      Und spätestens an dieser Stelle macht die Verkettung Sinn. Bei mehreren fehlenden Feldern werden alle Fehlermeldungen in dieser einen Variable gespeichert. Das ist gerade bei mehreren Feldern wirklich sehr praktisch! 215

      Kapitel

      8

      Fürs Feedback: Formmailer selbst gestrickt (Ich habe absichtlich nur drei Felder verwendet, um das Skript nicht zu sehr zu verkomplizieren. In der Praxis können noch viel mehr Felder vorkommen, die der Nutzer ausfüllen muss!)

      Fehlertext ausgeben Nun folgt eine weitere if-Abfrage. Hier wird der Status unserer FlagVariablen getestet. Wurde die Flagge gehisst? Gab es einen Fehler? Dann ist der Wert von $fehler true. Dann wird die Variable $fehlertext ausgegeben und der Nutzer sieht, welche Felder sie oder er vergessen hatte: if ($fehler) { echo "

      $fehlertext

      "; }

      Sollte alles okay gewesen sein, kann die Mail dagegen endlich auf die Reise gehen: else { ... hier steht der Mailbereich ... }

      Ich hoffe, dass du durch diesen Wust von verschachtelten if-Abfragen durchgestiegen bist. Immerhin hast du damit ein gutes Stück »PraxisKnow-how« mitbekommen. Vergleiche mit der Datei feedback6.php von der CD zum Buch.

      Inhalt in die Formularfelder schreiben Die Sache mit den fehlenden Feldern ist ja ganz gut und schön. Und trotzdem ist das Skript bisher doch die reinste Veralberung! Dein Besucher hat mühsam seinen Namen notiert und einen meterlangen Kommentar eingetragen, vor lauter Aufregung jedoch die E-Mail-Adresse vergessen? Das kommt vor! Dann wird sie oder er darauf hingewiesen, dass die E-MailAdresse fehlt. Wie zum Hohn werden beim nächsten Aufruf der Seite Name und Kommentarfeld gelöscht. Das prickelt! Warum speicherst du die Daten nicht in den Feldern, wie schon zwei Kapitel zuvor gezeigt? 216

      Inhalt in die Formularfelder schreiben

      Das Feld Name sichern Du willst die Eingabe aus dem Feld Name sichern? Dann musst du lediglich den value dynamisch in das Feld schreiben. Ergänze also das Feld:

      um das Attribut value – und zwar vor der schließenden spitzen Klammer. Schreibe dort, nach einem Leerzeichen, Folgendes: value=""

      Bevor du den Inhalt der Variablen mit echo ausgibst, solltest du stets mit isset($_POST['...']) testen, ob das Formular abgesendet wurde! Nur wenn das jeweilige Formularfeld existiert, kannst du den Wert dieser Variablen auch in das Formularfeld schreiben. Sonst erzeugt PHP den schon erwähnten (normalerweise unsichtbaren) Fehlerhinweis. Die Funktion stripslashes() benötigst du, damit Gänsefüßchen demaskiert werden. Doch das genügt noch nicht! Wie meistens gibt es auch diesmal noch einen Haken an der Sache. Probiere es aus und gib einen Namen mit doppeltem Gänsefüßchen ein. Schreibe zum Beispiel: Hans "Ottokar" Meier. Was stellst du fest? Der Name wird bis zum Gänsefüßchen ausgelesen, dann ist Feierabend.

      Der Blick in den Quelltext zeigt das Problem.

      217

      Kapitel

      8

      Fürs Feedback: Formmailer selbst gestrickt Das Problem: Hier wurden gleichrangige Gänsefüßchen ineinander verschachtelt, und das geht nicht. Denn das nächste Gänsefüßchen ist für HTML das Zeichen, mit dem Auslesen des values wieder aufzuhören. Doch du kannst dem Nutzer schließlich nicht verbieten, doppelte Gänsefüßchen zu schreiben. Ich habe zwei Ansätze für dieses Problem.

      Funktion strtr() Zum einen kannst du die Funktion strtr() verwenden. Die Funktion strtr() tauscht bestimmte Zeichen aus. Die Syntax lautet strtr(String, "Zeichen", "Ersatzzeichen");

      Der String ist das Element, das durchsucht werden soll. Das kann auch der Rückgabewert einer Funktion sein, wie im Beispiel gleich zu sehen sein wird. Bei Zeichen gibst du das auszutauschende Zeichen an. Bei Ersatzzeichen notierst du dagegen das Austauschzeichen. Im Beispiel würdest du statt stripslashes($_POST['Name']);

      einfach schreiben: strtr(stripslashes($_POST['Name']), "\"", "'");

      Dabei wickle ich einfach zwei Funktionen umeinander. Ersetzt wird das Zeichen " durch das '. Beachte, dass du dem Zeichen " einen MaskierBackslash voranstellen musst. Denn auch hier gilt: Gleichrangige Gänsefüßchen dürfen nicht ineinander verschachtelt werden.

      Die Funktion strtr() ersetzt ein Zeichen durch ein anderes.

      Die Wirkungsweise dieses Funktionsdoppels ist klar? Zuerst wird der String von seinen Backslashes befreit. Vom derart befreiten String werden nun alle doppelten in einfache Gänsefüßchen umgewandelt. Trotzdem ist strtr() in diesem Fall nicht meine Wahl. Ich entscheide mich lieber für die nächste Funktion!

      218

      Inhalt in die Formularfelder schreiben

      Funktion htmlspecialchars() Besprechen wir nun eine im Zusammenhang mit Formulardesign ungeheuer wichtige Funktion, die Funktion htmlspecialchars(). Sie ist wirklich »sehr special«, denn sie dient zum »Entschärfen« aller in HTML mit besonderer Bedeutung ausgestatteten Zeichen! Auch das doppelte und einfache Gänsefüßchen werden dabei berücksichtigt. Die Syntax lautet: htmlspecialchars($variable)

      Was macht htmlspecialchars() nun? Diese Funktion wandelt die vier hier aufgezählten Zeichen in ihre HTML-Entitäten um: Zeichen

      wird zu

      < > & "

      < > & "

      (steht für) lower than greater than Ampersand quotation mark

      Hier wird das doppelte Gänsefüßchen also nicht durch ein anderes Zeichen ersetzt, sondern in sein HTML-Pendant " umgewandelt. Dadurch bleibt es auch optisch erhalten. Das Name-Feld wird also folgendermaßen erweitert: value=""

      Die Funktion htmlspecialchars()

      wandelt das Gänsefüßchen in " um.

      Die gleiche Behandlung solltest du auch dem E-Mail-Feld gönnen: value=""

      219

      Kapitel

      8

      Fürs Feedback: Formmailer selbst gestrickt

      Der Kommentarbereich Beim Kommentarbereich kannst du ausnahmsweise nicht mit dem Attribut value arbeiten. Für den Bereich ist ein besonderer Trick nötig. Ergänze das Feld

      wie folgt:

      Der Trick besteht darin, den Inhalt direkt zwischen den Tags zu notieren. Das ist die Besonderheit bei ! Auch hier darfst du nicht vergessen, die Backslashs mit der entsprechenden Funktion zu entfernen. Das Maskieren der Sonderzeichen ist zwar nicht unbedingt erforderlich, da es zumindest hier keine »Gänsefüßchenkonflikte« geben wird. Ich habe es aus Sicherheitsgründen jedoch trotzdem gemacht! Merke dir die wichtige Funktion htmlspecialchars() unbedingt schon einmal vor! Du wirst sie für das eigene Gästebuch aus Kapitel 12 noch benötigen! Hier ist es besonders wichtig, alle Zeichen zu maskieren, mit denen man HTML-Tags zusammensetzen kann. Die »Skript-Kids« schummeln dir sonst eigene HTML- oder JavaScript-Bereiche in dein Tagebuch und verändern damit das Aussehen deiner Seite! Vergiss jedoch nicht, auch hier vorher mit einer if-Abfrage zu prüfen, ob die Variable $_POST['botschaft'] existiert. Denn wenn das Formular noch gar nicht abgesendet wurde, muss auch kein Inhalt in das Formularfeld eingetragen werden. Ohne if-Abfrage würde das Skript zwar auch funktionieren, würde jedoch sofort alle Fehlermeldungen wie Der Name fehlt, Die E-Mail-Adresse fehlt usw. anzeigen. Doch das wäre Unsinn! Fehlermeldungen dürfen erst nach Absenden des Formularinhalts erscheinen. Den bisherigen Sachstand findest du in der Datei feedback7.php. 220

      Erweiterter Fehlertest: Mindestlänge und E-Mail-Check

      Erweiterter Fehlertest: Mindestlänge und E-Mail-Check Damit ist das Skript aber noch keinesfalls perfekt. Bisher prüfen wir, ob die Felder nicht leer gelassen wurden. Doch wenn der Benutzer nur ein Platzhalter-Zeichen eingegeben hat? Einen Buchstaben oder eine Zahl? »SpaßAusfüller« sind gar nicht so selten! Vor allem das Feld mit der AbsenderMailadresse ist gefährdet. Ohne gründliche Prüfung der Eingabe könnten Hacker dein Formular zum Versenden von Spammails missbrauchen! In diesem Kapitel zeige ich dir deshalb weitere wichtige Fehlerbehandlungs-Techniken. Schreibe eine bestimmte Mindestlänge vor. Prüfe vor allem, ob die E-Mail-Adresse den gültigen Regeln entspricht!

      Mindestlänge erzwingen mit strlen() Zuerst unternimmst du etwas gegen zu kurze Namen. Mit weniger als drei Zeichen solltest du dich keinesfalls zufrieden geben! Nutze die talentierte Funktion strlen() für diesen Zweck. Die Funktion gibt die Länge eines Strings zurück. (Dahinter verbirgt sich die Abkürzung für string length.)

      >

      Suche den Bereich if (empty($_POST['Name'])) { $fehler = true; $fehlertext .= "Der Name fehlt!
      \n"; }

      >

      Notiere darunter und über if (empty($_POST['Email'])) { bitte Folgendes: elseif (strlen($_POST['Name']) < 3) { $fehler = true; $fehlertext .= "Der Name ist zu kurz!
      \n"; }

      Durch die Angabe elseif sicherst du, dass der zweite Test erst dann ausgeführt wird, wenn der erste nicht erfolgreich war. Wenn das Feld schon von Anfang an leer ist, macht eine Prüfung auf Länge auch keinen Sinn. 221

      Kapitel

      8

      Fürs Feedback: Formmailer selbst gestrickt Und wie wird nun auf Länge geprüft? Ganz einfach: Mit einem Vergleich stellst du fest, ob deine Wunschlänge unterschritten wurde. Wenn ja, setzt du die »$fehler-Flagge« auf true und fügst einen sinnvollen Fehlertext hinzu. Das gleiche kannst du für das Kommentarfeld (botschaft) erledigen. Ergänze zum Beispiel folgenden elseif-Zweig: elseif (strlen($_POST['botschaft']) < 3) { $fehler = true; $fehlertext .= "Der Kommentar ist zu kurz!
      \n"; }

      Welche Zahlen du für die Länge einsetzt, bleibt natürlich dir überlassen.

      E-Mail-Check mit regulärem Ausdruck Hast du Lust, auch den E-Mail-Check zu verbessern? Soviel schon vorweg: Prüfen, ob eine E-Mail-Adresse wirklich existiert, kannst du nicht. Du kannst dich aber davor schützen, dass dir der Ausfüllende unsinnige Zeichenfolgen als »E-Mail-Adresse« verkauft. Schließlich folgt der Aufbau solch einer Adresse ganz bestimmten Regeln. Solch ein Test gelingt dir mit den sogenannten regulären Ausdrücken, kurz RegExp. Mit diesen entsprechend vorbereiteten »Suchmustern« kannst du Strings auf das Vorhandensein bestimmter Zeichenfolgen prüfen. 0 Ist das Zeichen »@« vorhanden? 0 Ist die sogenannte Toplevel-Domain (eine Endung wie .de, .org oder .museum) nicht kürzer als zwei und nicht länger als sechs Zeichen? 0 Wurde ein Punkt notiert? 0 Besitzt die Adresse etwa verbotene Zeichen wie Leerzeichen, Umlaute oder Sonderzeichen? Betrachte diese mysteriösen regulären Ausdrücke einfach als eine Art universale Musterschablone. Also eine Schablone, die du dir für jeden Zweck zurechtbiegen kannst. Du testest auf das Vorhandensein oder Nichtvorhandensein bestimmter Zeichen- und Zeichenfolgen. Unsere »Musterschablone« für die E-Mail-Adresse sieht folgendermaßen aus, notiere bitte eine lange Zeile ohne Umbruch: $muster = "/^[a-zA-Z0-9-_.]+@[a-zA-Z0-9-_.]+\. [a-zA-Z]{2,6}$/";

      222

      Erweiterter Fehlertest: Mindestlänge und E-Mail-Check In dieser Zeile wird der reguläre Ausdruck definiert und in der Variablen $muster abgelegt. Nimm einfach hin, dass dieser Ausdruck die Schablone für eine E-Mail-Adresse darstellt und lass dich von dieser Zeichenwüste für den Anfang nicht allzu sehr beeindrucken.

      Testen auf Übereinstimmung mit preg_match() Und wie testest du nun auf Übereinstimmung? Verwende die Funktion preg_match()! Die Syntax sieht so aus: preg_match(Suchmuster, Zeichenkette)

      Das Suchmuster ist unser eben festgelegter regulärer Ausdruck. Also die Musterschablone für die E-Mail-Adresse. Die Zeichenkette ist der Prüfling, im Beispiel die zu testende E-Mail-Adresse. Wenn es keine Übereinstimmung mit dem Suchmuster gibt, wird eine 0 zurückgegeben, ansonsten liefert die Funktion mindestens 1. Das können wir uns in der if-Abfrage zunutze machen. Hier zeige ich dir die gesamte umgebaute if-elseif-Struktur für den Test der E-Mail-Adresse. Beachte, dass du die Variable $muster am Anfang dieser Passage initialisieren musst, damit der if-elseif-Ablauf nicht gestört wird. Es ist eine lange Zeile ohne Umbruch! Den alten Teil habe ich hervorgehoben. $muster = "/^[a-zA-Z0-9-_.]+@[a-zA-Z0-9-_.]+\. [a-zA-Z]{2,6}$/"; if (empty($_POST['Email'])) { $fehler = true; $fehlertext .= "Die E-Mail-Adresse fehlt!
      \n"; } elseif (preg_match($muster, $_POST['Email']) == 0) { $fehler = true; $fehlertext .= "Die E-Mail-Adresse ist ungültig!
      \n"; }

      Probiere deinen Fehlertest bisher ruhig einmal aus. Gib absichtlich ein paar falsche E-Mail-Adressen ein, z. B. mit Umlauten, Leerzeichen, fehlendem Zeichen @ usw. usf. Mit diesem regulären Ausdruck verhindern wir übrigens auch den Missbrauch unseres Mailformulars zu Spamzwecken. Angreifer schaffen es nun nicht mehr, die mail()-Funktion auszutricksen!

      223

      Kapitel

      Fürs Feedback: Formmailer selbst gestrickt

      8

      Das ist keine gültige E-Mail-Adresse. Es fehlt der Klammeraffe!

      Mit diesem Test bist du »professionellem Formdesign« ein ganzes Stück näher gerückt. Das Beispiel findest du in der Datei feedback8.php.

      RegExp: Der Aufbau des Such-Musters Zurück zum Such-Ausdruck aus der Variablen $muster. Interessiert dich, was dahinter steckt? Der gesamte Ausdruck wird zuerst einmal eingehüllt von zwei gleichen frei wählbaren Zeichen, hier ein Slash: / /. Das Dach ^ signalisiert den Beginn der Zeichenfolge, ein Dollar-Zeichen $ das Ende. Die Zeichenfolge a-zA-Z0-9-_. steht als Platzhalter für ein beliebiges alphanumerisches Zeichen, also für a-z, A-Z, 0-9, außerdem für den Bindestrich –, den Unterstrich _ und den Punkt .. Dadurch kann man Umlaute, Leer- und andere Sonderzeichen von vornherein ausschließen! Warum Unterstrich und Bindestrich? Diese Zeichen sind deshalb wichtig, da sie ebenfalls in E-Mail-Adressen vorkommen können. Auch der Punkt ist geläufig, deshalb musst du dieses Zeichen ebenfalls berücksichtigen. Das ganze fasst du in eckige Klammern ein und versiehst es mit einem Plus-Zeichen: [a-zA-Z0-9-_.]+ Das Plus-Zeichen verdeutlicht, dass dieses entsprechende Zeichen mindestens einmal vorkommen muss und beliebig oft vorkommen kann. Auch eine beliebige Kombination aller dieser Zeichen ist also erlaubt. Leerzeichen, Umlaute oder Sonderzeichen sind jedoch ausgeschlossen.

      224

      Das Zeichen »@« habe ich nicht innerhalb von Klammern notiert. Warum? Das bedeutet, dass dieses Zeichen genau einmal vorkommen muss, und zwar an dieser Position (in der Mitte der E-Mail-Adresse)! Danach notierst du wieder den Platzhalter für ein beliebiges alphanumerisches Zeichen. Der ebenfalls nicht eingeklammerte Ausdruck \. steht für dem »Pflicht-Punkt« an dieser einen Stelle.

      Erweiterter Fehlertest: Mindestlänge und E-Mail-Check Ganz am Schluss der E-Mail-Adresse dürfen nur alphanumerische Zeichen vorkommen. Hier geht es um die Top-Level-Domains wie .de, .info oder .museum. Das wird durch folgende Zeichen symbolisiert: [a-zA-Z]{2,6}

      Mindestens zwei, höchstens jedoch sechs Zeichen sind erlaubt. Das symbolisiert die Zeichenfolge {2,6}. Uff! Schon in diesem einen Suchmuster steckt ziemlich viel Komplexität. Schon aus diesem kurzen Beispiel merkst du, wie schwierig der Umgang mit diesen regulären Ausdrücken ist. Es gibt umfangreiche Kapitel in Fachbüchern, die sich allein diesem Thema widmen. Bei Stefan Münz auf http://de.selfhtml.org findest du ebenfalls eine ziemlich umfangreiche Einführung in dieses Thema. Und es gibt sogar mehrere »Spielarten« dieser regulären Ausdrücke. Der Autor hat z. B. mit den modernen Perlkompatiblen regulären Ausdrücken gearbeitet (Perl ist eine mit PHP vergleichbare Server-Programmiersprache!). Der Name der Funktion preg_match (Perl-kompatible reguläre Ausdrücke, match wie Übereinstimmung) weist darauf hin. Falls du ältere PHP-Einführungen liest, stößt du möglicherweise auf die veraltete Funktion ereg(). Diese Funktion bietet zu wenige Möglichkeiten. Im zweiten Buch werden wir uns noch intensiver mit diesen regulären Ausdrücken beschäftigen!

      Schutz gegen Flooding? Ist das Skript damit schon perfekt? Nein! Es ist noch nicht gegen Flooding (»Fluten«) geschützt. Also dagegen, dass ein Scherzbold immer wieder und wieder auf den ABSENDEN-Button klickt und damit das erneute Versenden auslöst. Denn alle Formulardaten bleiben in den Formularfeldern erhalten. Man müsste den Inhalt der Formularfelder irgendwie löschen, damit es nicht zu einem erneuten Versand kommt. Und hier greife ich eine Idee von Falk auf, die er in meinem Forum gepostet hat. (Danke, Falk!) Mache einmal Folgendes:

      >

      Vertausche die Position von Formular (alles zwischen den Tags ) und PHP-Skript. Bisher beginnt das Formular ja direkt unterhalb der

      und endet über dem einschaltenden PHP-Tag und dem schließenden Body-Tag ein. (Ausschneiden und Einfügen

      kannst du hoffentlich?) 225

      Kapitel

      8

      Fürs Feedback: Formmailer selbst gestrickt Wenn du das Skript jetzt ausprobierst, sollte es weiterhin funktionieren. Der einzige Unterschied: Die Statusmeldungen erscheinen jetzt über und nicht mehr unter dem Formular – und das ist ja nicht das Schlechteste. (So fallen sie besser ins Auge.)

      >

      Die ersten drei Zeilen des Skripts unterhalb von sehen nun wie folgt aus. Setze doch einmal die Zeile $fehler = false; vor die if-Abfrage.

      Feedbackformular


      Dadurch wird die $fehler-Variable gleich von Anfang an mit false initialisiert. Sie ist daher gleich im gesamten Skript »sichtbar«.

      >

      Und nun – ahnst du schon was? – gehst du in den unteren QuellcodeTeil, ins Formular. Und zwar zu den drei Stellen, wo der value dynamisch in das Feld geschrieben wird. Erweitere die jeweilige if-Abfrage um && $fehler, ich zeige es dir am Beispiel des ersten Felds, des Name-Felds:

      Name:


      Das bedeutet: Der Wert soll also nur dann in das Feld geschrieben werden, wenn die entsprechende Variable existiert – also wenn das Formular abgeschickt wurde – und wenn es einen Fehler gegeben hat. Einen Fehler, der dafür sorgt, dass die Daten noch nicht abgeschickt werden konnten. Wenn sie dagegen verarbeitet wurden, ist der Wert von $fehler schlicht und ergreifend false. Die Werte werden dann nach Klick auf ABSENDEN aus den Feldern gelöscht! Die Lösung findest du in der Datei feedback9.php.

      226

      Okay, das ist schon eine gute Lösung, perfekt ist sie noch nicht. Die Gefahr von Flooding ist damit noch nicht gebannt. Die Daten befinden sich trotzdem noch im sogenannten Browsercache (Zwischenspeicher). Der Scherzkeks braucht nur auf Reload des Browsers zu drücken – schon geht die E-Mail noch einmal auf die Reise. Auch der Klick auf den ZURÜCK-Button

      Krönender Abschluss: Universal-Formmailer des Browsers ist sehr aufschlussreich. Plötzlich stehen die Daten wieder in den Formularfeldern und lassen sich erneut versenden! Für einen wirksamen Flooding-Schutz haben wir an dieser Stelle aber einfach noch nicht genug Wissen! In Kapitel 12 erstellst du die Funktion isDouble(), um Doppeleinträge bei Gästebüchern zu verhindern. Dabei erzeugt das Formular zusätzlich einen Zeitstempel. Dieser wird in einer Textdatei gespeichert und bei erneutem Versand verglichen. Beide Zeitstempel müssen voneinander abweichen, sonst handelt es sich um alte Formulardaten aus dem Browsercache. Auf diese Weise lässt sich der Doppelversand wirksam unterdrücken. Vergleiche mit meiner Lösung unter kapitel08/feedback (und lies Kapitel 12)! Diese Lösung läuft jedoch an dieser Stelle außer Konkurrenz und wird nicht mit in die Aufgaben am Ende des Kapitels einbezogen!

      Krönender Abschluss: UniversalFormmailer Wie wäre es mit einem Skript, welches alle deine Formulare verschickt? Egal wie diese aufgebaut sind? Ideal für Feedback, für Bestellungen aus einem Onlineshop, für Umfragen usw. Dieses Skript gibt es. Nutze meinen berühmten Universal-Formmailer, den ich extra für dieses Buch erweitert und nochmals entscheidend verbessert habe. Das Skript kannst du praktisch zum Auswerten aller deiner Formulare verwenden, ganz egal, wie viele und welche Felder in diesen auftreten. Einzige Bedingung: Das Formular muss auf jeden Fall ein Feld besitzen, welches Email benannt wurde! Außerdem muss jedes Formularelement einen anderen Namen erhalten, aber das versteht sich sicher von selber!

      Der Quelltext im Überblick Und hier zeige ich dir nun den kompletten Quelltext der Datei unimailer.php. Beachte meine Kommentare, die dir die Wirkungsweise des Skriptes erklären. Eine Einbauerklärung nebst kurzer Erläuterung der Besonderheiten bekommst du im Anschluss. 227

      Kapitel

      8

      228

      Fürs Feedback: Formmailer selbst gestrickt

      Formularinhalt versenden <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> $value) { /* Formular-Daten werden in $mailbody gespeichert: */ $mailbody .= "$name = $value\n"; // Kurzform Verkettung $mailbody = stripslashes($mailbody); } $muster = "/^[a-zA-Z0-9-_.]+@[a-zA-Z0-9-_.]+\.[a-zA-Z]{2,6}$/"; /* Versenden! Email-Feld im Formular vorsehen! */ // Ist das Email-Feld nicht leer und gültig? if (!empty($_POST['Email']) && preg_match($muster, $_POST['Email']) > 0) { /* Dann wird Versenden-Funktion mail() aktiv */ $absender = $_POST['Email']; if (@mail($empfaenger, $betreff, $mailbody, "From: $absender")) { /* mail() erfolgreich? Dann sieht Nutzer Folgendes */ echo "

      Herzlichen Dank!

      \n"; echo "

      Die Daten wurden weitergeleitet!

      \n"; } /* Sonst gibt es eine Fehlermeldung: */ else { echo "

      Leider konnte die Botschaft nicht verschickt werden.

      \n"; } } // äußere if-Funktion schließen

      Krönender Abschluss: Universal-Formmailer /* else-Zweig äußere if bei nicht gesetzter Email: */ else { echo "

      Die E-Mail-Adresse muss angegeben werden und gültig sein!

      \n"; echo "

      zurück zum Formular

      \n"; } ?>

      Keine Lust zum Abschreiben? Du findest das Beispiel natürlich auch auf der CD zum Buch, und zwar unter dem Namen unimailer.php. Außer Konkurrenz biete ich dir noch eine zweite Version meines Unimailers. Du findest sie unter kapitel08 im Ordner unimailer_deluxe. Dort habe ich zusätzlich eine Flooding-Sperre eingebaut. Da ich diese Sperre aber erst in Kapitel 12 erläutere, gehe ich hier nicht weiter auf diesen Zusatz ein. Du möchtest den Inhalt deiner Formulare über diesen Unimailer versenden? Nichts leichter als das. Lege die unimailer.php (und die phpkid.css) auf deinen PHP-fähigen Server. Merke dir die Adresse gut, z. B. http://www.deinserver.de/unimailer.php. Schaue nun in die Datei mit dem Formular, es kann eine normale HTML-Datei sein. Gehe in das einleitende -Tag. Achte darauf, dass hier folgendes steht: 0 action="http://www.deinserver.de/unimailer.php" 0 method="post" Das war schon alles. Du kannst gerne alle deine Formulare über diesen Unimailer versenden. Dabei macht es nichts, wenn diese Dateien auf einem ganz anderen Server liegen – zumindest gilt diese Aussage für die meisten kostenpflichtigen Dienstleister mit PHP-Unterstützung. Hauptsache, du vergisst nicht die eben genannten Angaben.

      Besonderheiten im Skript Damit du sofort durchblickst, habe ich das Skript ausführlich kommentiert. Und wenn du das Kapitel bis hierher aufmerksam studiert hast, müsstest du eigentlich alles ohne Probleme verstehen. 229

      Kapitel

      8

      Fürs Feedback: Formmailer selbst gestrickt Ich verwende eine foreach-Schleife. Diese gibt alle Schlüssel-Werte-Paare des Arrays $_POST und damit alle Felder und ihren Inhalt zurück: /* foreach liest Attribut-Werte-Paare aus: */ foreach($_POST as $name => $value) { /* Formular-Daten werden in $mailbody gespeichert: */ $mailbody .= "$name = $value\n"; // Kurzform Verkettung $mailbody = stripslashes($mailbody); }

      Außerdem findest du im Skript auch wieder die Kurzform für das Verketten. So entspricht die folgende Zeile $mailbody .= "$name = $value\n"; // Kurzform Verkettung

      praktisch dieser Anweisung: $mailbody = $mailbody . "$name = $value\n";

      Der Rest ist sicher leicht verständlich. Passe die entsprechenden Variablen deinen Wünschen an. Das Skript testet auch, ob die E-Mail-Adresse eingegeben wurde und gültig ist. Dafür kommt wieder unser regulärer Ausdruck zum Einsatz. Ist irgendetwas faul mit der E-Mail-Adresse? Dann wird der Besucher darüber aufgeklärt: echo "

      Die E-Mail-Adresse muss angegeben werden und gültig sein!

      \n";

      Ein JavaScript-Link führt mit dem Schlüsselwort history.back() wieder zurück zur vorherigen Seite: echo "

      zurück zum Formular

      \n";

      Bis auf diesen Test der E-Mail-Adresse findet keine Formularvalidierung statt, also kein Test auf Gültigkeit des restlichen Formularinhalts. Das Skript bleibt dadurch flexibel: Schließlich weißt du nicht, wie viele und welche Felder es gibt.

      230

      Schlussbemerkung

      Arbeitsteilung JavaScript und PHP Apropos Formvalidierung: In vielen Fällen macht es Sinn, deine Formulare mit JavaScript zu testen. Erst die korrekten Daten werden dann an PHP weitergegeben. Das hat Vorteile, denn die beiden Skriptsprachen können sich die Aufgaben ganz wunderbar teilen. Schließlich wurde JavaScript extra für die Formularvalidierung erschaffen! JavaScript wird vom Client ausgeführt, also von deinem Rechner. PHP läuft dagegen auf dem Server und belastet den Rechner des Anbieters! Für dich als Formularanbieter macht es deshalb Sinn, möglichst viele Programmaktionen an den Client zu delegieren. Besonders, wenn du viele »Kunden« hast und bei der Serverkapazität sparen musst. Bei einem zu großen Besucheransturm kann die Serverkapazität sonst sehr schnell in die Knie gehen. Im Endeffekt reagieren deine Seiten immer langsamer und langsamer und sind im Zweifelsfalle nicht mehr erreichbar. Deinen Rechner als Kunde belastet die eine kleine Validierung mit JavaScript jedoch kaum. Als kleines Praxisbeispiel für diese Aufgabenteilung hat dir der Buchautor ein Skript für einen Onlineshop mit auf die CD gepackt. Es handelt sich um sein Programm Shopmichel Version 2.3. Es ist ein experimentelles Bestellsystem mit Warenkorb und Bestellbestätigung. Der Käufer bekommt nach Handelsabschluss eine Bestätigungs-Mail geschickt. Das Interessante dabei: Formularauswertung und Erzeugung des Warenkorbs erfolgt ausschließlich mit HTML und JavaScript. Dein Server wird dadurch kaum belastet, denn der wird dafür praktisch nicht benötigt. Erst ganz am Schluss leitet das Skript die Bestellung an einen PHPFormmailer weiter. Schau dir ruhig den Quelltext an. Du findest auch eine ausführliche Erklärung mit Einbauanleitung.

      Schlussbemerkung In diesem Kapitel hast du dich ausgiebig mit Formularauswertung und Formularversand beschäftigt. Du kennst die wichtigsten Tricks und Kniffe, um professionell aufgebaute Feedback-Formulare zu erstellen! Außerdem hast du gelernt, dass der Zeichensatz UTF-8 auch Probleme bereiten kann. Wir mussten alle Skripte als ISO-8859-1 kodieren, damit es beim Empfänger keine verstümmelten Umlaute und Sonderzeichen gibt. (Andere Lösungen wären aber an dieser Stelle zu kompliziert gewesen!) 231

      Kapitel

      8

      Fürs Feedback: Formmailer selbst gestrickt

      Zusammenfassung 0 Du kennst die Funktion mail(), mit der du über den Webserver eine E-Mail verschicken kannst. 0 Du weißt, dass du Formmailer-Dateien als ISO-8859-1 (PSPad: ANSI) speichern solltest, damit es keine »Umlaut-Probleme« gibt. 0 Du weißt, dass du mit dem Zeichen @ vor mail() die Ausgabe von Fehlermeldungen unterdrückst. 0 Du weißt, dass die Funktion mail() je nach Erfolg true oder false zurückgibt und dass du diesen Wert abfangen und zur Fehlerausgabe nutzen kannst. 0 Du kennst die Kurzform für das Verketten einer Variablen mit sich selbst (.=). 0 Du kennst die Funktion stripslashes() zum Entfernen der Maskierungs-Backslashes und die Funktion strtr() zum Ersetzen von Zeichen. 0 Du weißt, dass du mit der Funktion htmlspecialchars() die für HTML wichtigen Zeichen in ihre Entitäten (Umschreibungen) umwandeln und damit »entschärfen« kannst. 0 Du kennst die Funktion strlen() zum Ermitteln der Länge eines Strings und damit zum Prüfen von Formulareingaben. 0 Du hast das Konzept der regulären Ausdrücke kennengelernt, der Suchmuster für bestimmte Zeichenfolgen. Du weißt, dass du mit preg_match() und dem entsprechenden Suchmuster z. B. den korrekten Aufbau der E-Mail-Adresse überprüfen kannst.

      Ein paar Fragen … 1. Mit welchem Zeichen kannst du bei vielen Funktionen die Ausgabe von Fehlermeldungen unterdrücken? 2. Welche Werte gibt die Funktion mail() zurück und wie kann man diese Tatsache ausnutzen? 3. Welche Funktion gibt die Länge eines Strings zurück?

      232

      4. Welche im Browser lauffähige Programmiersprache wurde speziell dazu entwickelt, Formulare zu validieren (zu überprüfen)?

      … und ein paar Aufgaben

      … und ein paar Aufgaben 1. Füge ein weiteres Formularfeld in das Feedback-Formular (Datei feedback.php) ein, um den Wohnort zu ermitteln. Nenne das Feld Ort. 2. Überprüfe, ob das Wohnort-Feld ausgefüllt wurde. Gib eine Mindestlänge von 3 Zeichen vor. 3. Speichere den Ort dynamisch im Formularfeld und vergiss nicht, ihn auch zum $mailbody hinzuzufügen. 4. Erweitere das Feedback-Formular, schicke dem Feedback-Schreiber automatisch eine Bestätigungsmail, in der du dich für die Angaben bedankst! 5. Schaue dir das Umfrage-Formular aus Kapitel 1 an. Baue es so um, das der Formularinhalt über den Universal-Formmailer abgeschickt werden kann. Welches Feld musst du noch einbauen, damit der UniversalFormmailer arbeiten kann? 6. Erstelle eine Formtester-Seite. Eine Seite, die dir alle Attribut-WertePaare eines Formulars untereinander anzeigt, ohne irgendein Feld vorauszusetzen oder zu testen. Nenne die Seite formtester.php.

      233

      9 Surfer wiedererkennen mit Cookies Keine Angst vorm Krümelmonster! In diesem Kapitel backen wir Kekse, zu Englisch Cookies. Du lernst in diesem Kapitel, wie du $ Informationen auf dem Rechner des Besuchers speicherst $ Cookies mit PHP setzt, verwaltest und ausliest $ Cookies mit einem Mindesthaltbarkeitsdatum versiehst $ Cookies löschst Dabei reden wir ganz ausführlich auch über die Nachteile dieser Technologie und schauen uns an, welche Browsereinstellungen für die Arbeit mit Cookies wichtig sind. Denn als Surfer musst du dir nicht alle Kekse gefallen lassen. Doch was sind Cookies überhaupt?

      235

      Kapitel

      9

      Surfer wiedererkennen mit Cookies

      Was sind Cookies? Kennst du das auch? Du surfst zu einer Website und liest: »Schön, dass Sie uns wieder besuchen!«. Und tatsächlich – es ist nicht dein erster Besuch. Noch nach Wochen »erinnert sich« ein Onlineshop an die Produkte, die du irgendwann mal zur Probe in den Warenkorb gelegt und nie gekauft hattest. Du hattest das längst vergessen, der Shop »wusste offenbar Bescheid«. Manche Websites erinnern sich sogar nach Monaten an deinen Namen. So wirst du bei eBay (www.ebay.de) selbst dann noch mit deinem Benutzernamen begrüßt, wenn du dich als Benutzer längst wieder ausgeloggt hast. Was steckt dahinter? Ist das Hexerei? Fauler Web-Zauber? Ein Protokollund Überwachungsprogramm des Bundesnachrichtendienstes? Nein! Hier handelt es sich aller Wahrscheinlichkeit nach um Cookies. Cookies sind Informationskrümel, die eine Webseite auf dem Rechner des Besuchers speichert. Eine Webseite »merkt« sich dadurch, dass du sie besucht hast. Ein Onlineshop »weiß«, welche Produkte noch in deinem Warenkorb stecken. Denn bei einem neuerlichen Besuch liest diese Webseite die Datei einfach wieder aus und reagiert darauf. Cookies werden vom Browser verwaltet, der sie empfängt.

      Sind Cookies ein Sicherheitsrisiko? Eigentlich nicht. Es kommt immer darauf an, wie der Seitenersteller diese Technologie einsetzt. (Damit bist auch du als Seitenersteller gemeint!) Doch zuerst die harten Fakten: 0 Cookies sind kleine Textdateien, die eine Webseite auf der Festplatte des Surfers ablegt. Programme oder Viren lassen sich so nicht sichern. 0 Cookies werden in Abhängigkeit vom Browser stets an einer bestimmten Stelle abgelegt. (Wo, klären wir gleich!) 0 Du kannst Cookies einsehen und bedenkenlos wieder löschen. Wie das geht, hängt vom Browser ab. 0 Du kannst deinen Browser so konfigurieren, dass er Cookies gar nicht erst annimmt. 0 Ein Cookie ist in aller Regel nicht größer als 4 KB. (Schon das sorgt dafür, dass Programme und Viren keine Chance haben!) 236

      Was sind Cookies? 0 Cookies sind normalerweise eine Privatsache zwischen der Webseite des Cookie-Produzenten, deinem Browser und dir als Surfer. In der Regel bekommt der Seitenbetreiber nicht einmal mit, dass eine Seite ein Cookie bei dir gesetzt hat. (Cookies können unter bestimmten Voraussetzungen allerdings doch zum Ausspionieren verwendet werden, dazu gleich mehr!) 0 Cookies können normalerweise nur von der Seite wieder ausgelesen werden, die sie gesetzt hat. Oder, um präziser zu sein, von Webdokumenten aus dem gleichen Ordner bzw. Webseiten aus Unterordnern. Im Normalfall nicht von einer anderen Domäne! (Wenn also www.phpkid.de/index.html ein Cookie setzt, kann dieses nur von www.phpkid.de/index.html oder www.phpkid.de/weblog/index.html, aber nicht von www.shopmichel.de ausgelesen werden! Eine Ausnahme spielen die Cookies von Drittanbietern, die du auf jeden Fall deaktivieren solltest. Auch dazu gleich mehr!) Nachdem du die technischen Daten kennst, interessiert dich sicher die Frage: Wo liegen die Biester?

      Wo speichert der Browser die Cookies? Jeder Browser verwaltet die Cookies auf unterschiedliche Art und Weise. Der Internet Explorer unter Windows XP legt die Kekse in der Regel ab unter C:\Dokumente und Einstellungen\Benutzername\Cookies. An Stelle von Benutzername setzt du natürlich den Benutzernamen ein, den du als Windows-Nutzer unter Windows XP besitzt. Bei älteren WindowsVersionen ohne Nutzerprofile liegen die Cookies häufig aber auch unter C:\Windows\Cookies. In diesem Ordner findest du lauter kurze Textdateien vor, in denen der Browser die entsprechenden Cookie-Daten lagert.

      Der Internet Explorer legt die Cookies im gleichnamigen Ordner ab.

      237

      Kapitel

      9

      Surfer wiedererkennen mit Cookies

      Du möchtest diesen Cookie-Ordner blitzschnell aufrufen, um die dort liegenden Textdateien einsehen zu können? Du arbeitest mit dem Windows-Explorer unter Windows XP oder 98? Dann probiere meinen Supertrick: Wähle einfach START|AUSFÜHREN. Tippe die Zeichenfolge cookies in das Dialogfenster ein und klicke auf OK. Schon steckst du mitten drin im Cookie-Ordner. Wie zeigst du diese Dateien übersichtlich an? Wähle am besten ANSICHT|DETAILS. Achte auf die Spalte mit dem Speicherdatum! Klicke auf den Spaltenkopf GEÄNDERT AM, bis du die neuesten Cookies zuoberst siehst. Das eigentliche Aufrufen der entsprechenden CookieTextdateien gelingt jetzt ganz einfach durch Doppelklick auf die entsprechende Textdatei. Der Inhalt der Cookies besteht oft aus kryptischen Namen, Zeichen und Nummern. Der Sinn erschließt sich oft nur dem Betreiber der Seite, der das Cookie setzt. Häufig findest du in dieser Textdatei auch die Domain, von der du den Keks erhalten hast. Das »Haltbarkeitsdatum« ist in einer langen Nummer verschlüsselt. Du möchtest eine dieser Cookie-Dateien löschen? Nichts leichter als das. Rechtsklicke auf die Datei. Befördere Sie per LÖSCHEN-Befehl in den Papierkorb! Bis auf die Verwaltungsdatei index.dat (die kannst du nicht löschen!) lassen sich alle Cookie-Dateien auf diese Weise eliminieren. Der Firefox-Browser macht das Verwalten und Löschen der Cookies besonders einfach. Wähle EXTRAS|EINSTELLUNGEN. Klicke links auf den Bereich DATENSCHUTZ und – falls vorhanden – auf das Register COOKIES. Klicke auf die Schaltfläche COOKIES ANZEIGEN. Du siehst nicht die nackte Textdatei, sondern eine übersichtliche Maske. Hier kannst du alle Cookies nacheinander einsehen. Wie du siehst, sind es nur kurze, oftmals kryptische Informationen. Du möchtest ein Cookie löschen? Klicke dazu einfach auf die Schaltfläche COOKIE ENTFERNEN. Wähle ALLE COOKIES ENTFERNEN, wenn du dich komplett von allen Cookies trennen möchtest.

      Wann werden Cookies problematisch? Eigentlich sind und waren Cookies als sinnvolle Komfortmaßnahme gedacht! Und zwar als Komfortmaßnahme für den Surfer. Inzwischen hat sich die Welt jedoch weitergedreht und das Web wurde immer kommerzieller. Solange du nur auf einer Seite »herumsurfst«, können dir die Cookies noch nichts anhaben. Sie sind zwar da, doch der Betreiber der Webseite erfährt nichts von deiner Existenz. 238

      Grundeinstellungen im Browser

      Mit Hilfe von Cookies gehen kommerzielle Anbieter auf deine Bedürfnisse ein.

      Das ändert sich spätestens dann, wenn du Daten von dir preisgibst. Du füllst ein Formular aus? Du meldest dich mit einem Benutzernamen an? Du bestellst in einem Onlineshop? Dann kann dich der Webseitenbetreiber beim nächsten Besuch dank des Cookies namentlich zuordnen. Doch damit nicht genug. Dein Verhalten auf einer Webseite wird häufig sogar ganz genau verfolgt. Viele Seitenbetreiber erstellen regelrechte Nutzerprofile. Der Onlinehändler www.amazon.de zum Beispiel »merkt« sich deine Vorlieben ganz genau. Du bist Amazon-Kunde und hattest beim vorigen Besuch Sciencefiction-Literatur betrachtet? Dann bekommst du beim nächsten Besuch mit großer Wahrscheinlichkeit Empfehlungen genau zu diesem Thema. Der Surfer wird zum »gläsernen Konsumenten«. Das geht sogar so weit, dass dir manche Seitenbetreiber speziell auf deine Interessen zielende Werbebanner einblenden. Hier ist mir der Verlag Zweitausendeins (www.zweitausendeins.com) sehr positiv aufgefallen. In einem ausführlichen Infotext erklärt der Verlag auf seiner Webseite ganz genau, wozu die Cookies benötigt werden. Man versichert dir, dass diese Textschnipsel nicht zum »Tracking« deines Nutzerverhaltens verwendet werden. Eine sehr löbliche Ausnahme.

      Grundeinstellungen im Browser Wie du merkst, stehe ich diesen kleinen Informationskrümeln durchaus kritisch gegenüber, obwohl sie an und für sich harmlos sind. Das ist auch der Grund, warum viele aufgeklärte Surfer Cookies abschalten. Schade eigentlich, denn Cookies erfüll(t)en eine wichtige Funktion. Und wir brauchen sie noch. 239

      Kapitel

      9

      Surfer wiedererkennen mit Cookies Was soll dein Browser nun mit den Keksen anfangen? Lass dir nicht alles gefallen – sortiere sie aus: die guten ins Töpfchen, die schlechten ins Kröpfchen. Richte dein Surfbrett wunschgemäß ein!

      Einstellungen beim Internet Explorer Du arbeitest mit dem Internet Explorer ab Version 6? Du möchtest entscheiden, was mit Cookies passieren soll? So gehst du vor:

      > > >

      Wähle EXTRAS|INTERNETOPTIONEN und gehe ins Register DATENSCHUTZ. Schaue in den unteren Bereich. Klicke auf die Schaltfläche ERWEITERT. Setze das Häkchen vor der Option AUTOMATISCHE COOKIEBEHANDLUNG AUFHEBEN.

      >

      Im Bereich COOKIES VON ERSTANBIETERN kannst du dich für ANNEHMEN, SPERREN oder EINGABEAUFFORDERUNG entscheiden.

      Für unsere Experimente empfehle ich dir diese Option namens EINGABEAUFFORDERUNG. Dann erscheint bei jedem Cookie erst ein Dialogfenster mit den entsprechenden Cookie-Daten. Klicke dort auf die Schaltfläche DETAILS, wenn du mehr Informationen wünschst. Auf diese Weise siehst du sofort, ob es mit dem Erstellen und Annehmen der Cookies klappt, wie es soll!

      >

      Im Bereich COOKIES VON DRITTANBIETERN empfehle ich dir die Einstellung SPERREN. Es handelt sich bei dieser Sorte von Cookies meist um »Plätzchen« irgendwelcher Werbeanbieter. Genau das ist auch mit Drittanbieter gemeint: Du besuchst z. B. www.phpkid.de und bekommst ein Cookie von www.addcom.com serviert!

      Beachte, dass die Einstellungen erst dann wirken, wenn du den Internet Explorer schließt und wieder neu startest! Du kannst im Internet Explorer sogar Cookies von bestimmten Seiten blockieren. Wähle EXTRAS|INTERNETOPTIONEN und gehe ins Register DATENSCHUTZ. Klicke im Internet Explorer 6 auf die Schaltfläche BEARBEITEN, in Version 7 dagegen auf SITES. Gib die Domain ein, von der du keine Cookies serviert bekommen möchtest. Tippe z. B. msn.de und wähle SPERREN. Damit blockierst du Cookies von der Microsoft-eigenen Suchmaschine. 240

      Krümelmonsters Keksfabrik: Cookies »backen«

      Einstellungen für Firefox Der Firefox-Browser bietet auch recht umfangreiche Optionen zur Behandlung von Cookies.

      > >

      Wähle EXTRAS|EINSTELLUNGEN. Wähle das Register DATENSCHUTZ und schaue zum Pull-down-Menü COOKIES BEHALTEN bzw. BEHALTEN BIS. Wähle für unsere Experimente am besten die Option JEDES MAL NACHFRAGEN.

      >

      Sehr nützlich ist auch die Option BIS FIREFOX GESCHLOSSEN WIRD. Dann überlebt kein Cookie länger als einen Tag – auch wenn dir die Anbieter dauerhafte Cookies andrehen wollen!

      Krümelmonsters Keksfabrik: Cookies »backen« Genug Vorbemerkungen – ran an die Keksdose! Jetzt bist du derjenige, der Plätzchen serviert. Es handelt sich um einen ganz harmlosen Keks: Begrüße deine Besucher mal auf die persönliche Art. Das Prinzip ist einfach: 0 Deine Webseite setzt beim Besucher ein Cookie (sofern der Browser des Besuchers Cookies akzeptiert) 0 Deine Webseite liest das Cookie – falls vorhanden – beim nächsten Besuch wieder aus Wichtig zu wissen: Ein Cookie besteht im einfachsten Fall aus einem Name-Wert-Paar. Wir nennen unser Cookie visit und vergeben den Wert yes. Doch wie?

      Die Funktion setcookie() Zum Setzen eines Cookies verwendest du die Funktion setcookie(). Der Name dieser Funktion ist also Programm. Fehlen noch die Argumente, und zwar der Cookiename und der Cookiewert. Bitte sehr, hier ist die komplette Funktion: setcookie("Cookiename", "Cookiewert")

      Es handelt sich um eine ziemlich anwenderfreundliche, genial einfache Funktion. Eine Sache musst du dir jedoch unbedingt merken! Und da sie so wichtig ist, habe ich sie in einen Kasten gesetzt. 241

      Kapitel

      9

      Surfer wiedererkennen mit Cookies

      Ganz wichtig: Die Funktion funktioniert nur dann, wenn du sie ganz zu Beginn der HTML-Seite einsetzt. Platziere sie noch vor dem einleitenden HTML-Tag! Das Cookie muss im sogenannten Header der HTML-Seite verschickt werden.

      Wie wird das Cookie eigentlich ausgelesen? Dafür gibt es ein Array namens $_COOKIE. Hier handelt es sich, übrigens genau wie beim Array $_POST zur Entgegennahme von Formulardaten, um ein assoziatives Array. Der Name des Cookies wird automatisch zum Key des Arrays. Um auf den Wert des Cookies visit zugreifen zu können, schreibst du einfach $_COOKIE["visit"]. Ist das nicht fantastisch einfach?

      Das Beispiel Und nun zum Beispiel. Die folgende Datei setzt ein Cookie (vor dem einleitenden HTML-Tag!) und liest es in einem zweiten PHP-Block wieder aus. Cookie setzen und auslesen <meta http-equiv="content-type" content="text/html; charset=utf-8">

      Cookie setzen und auslesen

      wieder da bist!\n"; } else { echo "Schön, dass du da bist!\n"; } ?>

      242

      Der Keks bekommt ein MHD



      Du findest das Beispiel auch unter dem Namen cookie1.php im Ordner kapitel09. Probiere das Skript einfach aus.

      Die gleiche Seite nach dem ersten Aufruf und bei einem Reload.

      Nach dem ersten Aufruf wirst du begrüßt mit Schön, dass du da bist!. Spätestens nach dem zweiten Aufruf steht jedoch Schön, dass du wieder da bist! in der Seite.

      Der Keks bekommt ein MHD Unser Cookie besitzt einen Haken. Beim nächsten Aufruf der Seite hat der Browser alles vergessen. Man könnte es auch als »Cookie-Alzheimer« bezeichnen. Und tatsächlich: Nach Schließen des Browsers wird das Cookie normalerweise gelöscht. Logisch, schließlich gilt es nur für die aktuelle Sitzung. Für den Besucher ist das vielleicht ganz vorteilhaft. Doch für dich als CookieErsteller? Schließlich würdest du deine Besucher auch noch nach 30 Tagen gerne persönlich begrüßen dürfen, oder? Solange du dem Cookie kein Enddatum mit auf den Weg gibst, handelt es sich um ein »Sitzungscookie«, um ein temporäres Cookie. Im Klartext: Das Cookie bleibt für eine Sitzung aktiv, bestenfalls vielleicht noch für ein paar Stunden. Wie wäre es, wenn das Cookie für 30 Tage gespeichert bliebe? Kein Problem! Verpasse deinem Keks eine Lebensdauergarantie.

      243

      Kapitel

      9

      Surfer wiedererkennen mit Cookies

      Ablaufdatum angeben Die erweiterte Funktion mit Lebensdauergarantie sieht folgendermaßen aus: setcookie("Cookiename", "Cookiewert", Ablaufdatum)

      Interessant ist hierbei der neue Parameter Ablaufdatum. Es ist ein Zeitwert, der in Sekunden gemessen wird. Ausgangspunkt ist die Zahl der Sekunden, die seit Beginn der sogenannten Unix-Epoche vergangen sind. Addiere nun die Zahl der Sekunden hinzu, die du in die Zukunft denkst. Die Unix-Epoche ist ein festgelegter Wert. Die Unix-Epoche begann am 1.1.1970 um 0:00 Uhr. Wie bekommst du diese mysteriöse Sekundenzahl heraus? Wie ermittelst du die Zahl der Sekunden, die seit Beginn der Unix-Epoche vergangen sind? Dieser Wert ändert sich doch ständig?! Du brauchst eine Funktion. Eine Funktion, die die genaue Sekundenzahl der Unix-Epoche ausgibt. Diese begabte Funktion heißt time() – verwende sie ohne alle Argumente! Diese Funktion ermittelt die Anzahl der Sekunden seit Beginn der Unix-Epoche. Wenn du dem Cookie eine Lebensdauergarantie mit auf den Weg geben willst, addierst du zu time() einfach die Zahl der Sekunden, die du in die Zukunft denkst. Das Cookie soll 30 Tage aktiv sein? Dann musst du 2592000 Sekunden in die Zukunft denken. Übersichtlich ausgeschrieben sieht das so aus: time() + 86400 * 30. (Die 86400 steht dabei für die Sekunden eines Tages, also 60 * 60 * 24.)

      Herumkrümeln: Cookies »verspeisen« Ran an die Praxis. In unserem Beispiel musst du also nichts weiter tun als die Zeile setcookie("visit", "yes");

      wie folgt zu ändern: setcookie("visit", "yes", time() + 86400 * 30);

      244

      Wie kannst du dich davon überzeugen, ob das klappt? Hier hilft der Internet Explorer! Achte darauf, dass die Option EINGABEAUFFORDERUNG eingeschaltet ist, wie einige Seiten zuvor gezeigt.

      Aufgegessen: Cookies löschen Lade dein Dokument nun auf den Webserver. (Offline klappt es in der Regel leider nicht mit der Eingabeaufforderung.) Nun erscheint das Dialogfenster DATENSCHUTZHINWEIS. Du wirst über die bevorstehende Cookieübergabe informiert. Klicke in diesem Dialogfenster auf die Schaltfläche DETAILS:

      Das Cookie bekommt eine Haltbarkeitsdauer mit auf den Weg.

      Das so angepasste Skript mit Lebensdauergarantie findest du unter dem Namen cookie2.php.

      Aufgegessen: Cookies löschen Wie löscht man eigentlich ein Cookie? Diese Technik – so scheint es mir – ist vielen Cookie-Produzenten unbekannt. Sie wollen es nicht wissen. Da musst du als Konsument also von Zeit zu Zeit selber einmal aufräumen! Du arbeitest mit dem Internet Explorer, Version 6? Du möchtest alle deine Cookies auf einen Schlag loswerden? Wähle EXTRAS|INTERNETOPTIONEN. Gehe ins Register ALLGEMEIN. Klicke auf die Schaltfläche COOKIES LÖSCHEN. So einfach ist das! In Version 7 klickst du erst auf LÖSCHEN – danach erscheint dann die Schaltfläche COOKIES LÖSCHEN. Im Firefox kannst du deine Cookies über EXTRAS|PRIVATE DATEN LÖSCHEN loswerden. Aber auch für dich als Produzenten von Cookies gilt: Das Löschen ist sehr simpel. Übermittle dem Nutzer exakt das gleiche Cookie noch einmal. Übergib lediglich ein Enddatum, das in der Vergangenheit liegt. Die Zeile könnte zum Beispiel so aussehen: setcookie("visit", "yes", time() - 86400);

      245

      Kapitel

      9

      Surfer wiedererkennen mit Cookies

      Schlussbemerkung In diesem kurzen Kapitel hast du einen kleinen Einblick in die CookieTechnologie bekommen. Du kannst selber Cookies setzen, auslesen und löschen. Du kennst die Vor- und Nachteile von Cookies.

      Zusammenfassung 0 Du weißt, dass Cookies an sich harmlos sind. Es handelt sich um einfache Textdateien, in denen eine Webseite Informationen auf deinem Rechner speichert. 0 Du weißt, wie du mit der Funktion setcookie() Cookies setzen kannst, die Argumente dieser Funktion lauten: setcookie("Cookiename", "Cookiewert", Ablaufdatum). 0 Du weißt, dass du Cookies löschst, indem du ein Ablaufdatum angibst, das in der Vergangenheit liegt.

      Ein paar Fragen … 1. Wann begann die Unix-Epoche? 2. Darfst du die Funktion setcookie() an allen Stellen des HTMLDokuments angeben?

      … und ein paar Aufgaben 1. Erweitere das Skript so, dass das Cookie nicht nur für 30 Tage, sondern ungefähr für ein ganzes Jahr gültig bleibt. Nenne die Seite cookie3.php. 2. Erstelle eine Seite, die nichts weiter macht, als das Cookie zu löschen. Nenne sie delete.php. 3. Platziere auf der Seite cookie3.php einen Link zu delete.php. Wähle als Linkbeschreibung einfach Gedächnis löschen. Erstelle auf der Seite delete.php einen Link namens Zurück zur Gedächtnisseite. 4. Probiere die beiden Seiten aus. 246

      10 Besucherzähler selbst gebaut Es lebe die Eitelkeit! Wie wär’s mit einem Zähler für die Homepage? Klar willst du wissen, wie viele Besucher sich auf deiner Homepage tummeln. Wer will das nicht? Bei dieser Gelegenheit zeige ich dir, wie du $ Daten in Textdateien schreibst $ Daten aus Textdateien wieder ausliest $ eine Textdatei mit Schreibrechten im Unix-Dateisystem versiehst $ das »künstliche Hochpuschen« des Zählers durch Reloads unterbindest Damit du durch das Beispiel gut durchsteigst, habe ich es so einfach wie möglich gehalten. Aber es funktioniert! Alles in allem ist dieses Kapitel ein sehr wichtiges Kapitel. Du lernst das erste Mal, wie du Daten in Dateien ablegen kannst. Denn gerade dieses Thema zeichnet eine Serverprogrammiersprache aus. Du sicherst Informationen auf dem Webserver und liest sie wieder aus.

      247

      Kapitel

      10

      Besucherzähler selbst gebaut

      Zwei Dateien: So funktioniert das Beispiel Unser Besucherzähler arbeitet mit zwei Dateien. Zum einen ist das die Hauptdatei – also die Datei, in die wir einen Zähler einbauen. Diese nennen wir im Beispiel 0 index.php Außerdem benötigen wir eine zweite Datei, eine einfache Textdatei. Hier soll der aktuelle Zählstand gespeichert werden. Ich schlage folgenden Namen vor: 0 count.txt

      Textdatei anlegen Lege zuerst die Textdatei count.txt an. Mit PSPad geht das ganz fantastisch schnell:

      >

      Klicke auf die Schaltfläche NEUE DATEI ERSTELLEN, also direkt auf das weiße Blatt. Ein leeres Dokument erscheint.

      > >

      Tippe eine 0 für den Zählstand und wähle den Befehl SPEICHERN. Speichere die Datei im gleichen Ordner wie die index.php und nenne sie count.txt.

      So funktioniert das Beispiel Unser Skript macht Folgendes: Die PHP-Datei index.php öffnet die count.txt, liest den Wert aus und zeigt ihn an. Das ist die Zahl, die der Besucher sieht. Gleichzeitig erhöht das Skript diesen Wert um 1. Der neue Wert wird sofort zurückgeschrieben und somit in der aktualisierten count.txt gespeichert. Bei einem erneuten Aufruf der index.php geht das Spielchen von vorne los. Diesmal jedoch mit dem neuen Wert aus der count.txt.

      Hitmaschine: Ein Textcounter 248

      Im Beispiel geht es also um einen Textcounter, um eine »Hitmaschine«. Sie zählt jeden Hit, also auch jeden Druck auf den RELOAD-Button.

      Datei zum Lesen öffnen Zum Verständnis zeige ich dir diesmal den kompletten Quelltext vorab. Es ist der Bereich zwischen den Tags und . Danach gehen wir alle Codezeilen Schritt für Schritt durch!

      Ein Textcounter

      Die Seite wurde -mal aufgerufen.



      Wenn du möchtest, kannst du das Beispiel ruhig schon einmal ausprobieren. Oder du schlägst im Ordner kapitel10 auf der CD nach.

      Bei jedem Neuladen der Seite wird der Zähler um 1 erhöht.

      Datei zum Lesen öffnen Zuerst musst du wissen, wie man eine Datei zum Lesen öffnet.

      Die Funktion fopen() Das gelingt mit Hilfe der Funktion fopen()

      Die Funktion wird meist in folgender Syntax verwendet: fopen("Dateiname", "Modus")

      Die Argumente der Funktion (das Zeugs in runden Klammern) sehen auf den ersten Blick ziemlich kriminell aus. Einverstanden, zumindest den Da-

      249

      Kapitel

      Besucherzähler selbst gebaut

      10

      teinamen kannst du leicht entschlüsseln. Trage innerhalb der Gänsefüßchen den Namen der zu lesenden Datei ein. Im Beispiel ist das count.txt. Doch was hat es mit diesem merkwürdigen Modus auf sich? Ganz einfach: Der Modus drückt aus, was du mit der Datei machen kannst. Folgende Modi gibt es: Modus Erklärung r

      Nur-Lesemodus (r wie read only), die Datei kann nur gelesen werden.

      r+

      Lese- und Schreibmodus (r+ wie read and write), die Datei kann gelesen und beschrieben werden. Nur-Schreibmodus (w wie write only), die Datei kann nur beschrieben werden. Sie wird dabei stets auf 0 Byte gesetzt. Falls die Datei nicht vorhanden ist, wird versucht, sie anzulegen. Lese- und Schreibmodus (w+ wie write and read), die Datei kann gelesen und beschrieben werden. Sie wird dabei stets auf 0 Byte gesetzt. Falls die Datei nicht vorhanden ist, wird versucht, sie anzulegen. Anhänge-Schreib-Modus (a wie append), öffnet die Datei zum Schreiben, alle neuen Werte werden unten ans Dateiende angehängt. Der »Dateizeiger« steht daher ausnahmsweise nicht am Anfang, sondern am Ende der Datei. Falls die Datei nicht vorhanden ist, wird versucht, sie anzulegen. Anhänge-Lese- und Schreib-Modus (a+ wie append and read), öffnet die Datei nur zum Lesen und Schreiben, alle neuen Werte werden unten ans Dateiende angehängt. Der »Dateizeiger« steht daher ausnahmsweise nicht am Anfang, sondern am Ende der Datei. Falls die Datei nicht vorhanden ist, wird versucht, sie anzulegen.

      w

      w+

      a

      a+

      Keine Sorge, du brauchst diese Modi nicht auswendig zu lernen! Wir benötigen lediglich den Modus r+ für read and write. Wir lesen aus einer Datei und schreiben wieder hinein. (Abgesehen davon halte ich noch die Modi r, a und a+ für halbwegs brauchbar, eingesetzt habe ich sie ganz persönlich jedoch bisher noch nicht.) Zurück zum Modus r+: Das Lesen und Schreiben beginnt bei diesem Modus am Anfang der Datei. Anders ausgedrückt: Bei diesem Modus steht der geheimnisvolle Dateizeiger stets am Anfang der Datei.

      Der geheimnisvolle Dateizeiger Was ist das für ein komisches Ding, dieser Dateizeiger? Und was machst du damit? Das schauen wir uns jetzt etwas genauer an! 250

      Der geheimnisvolle Dateizeiger

      Die Funktion fopen() positioniert stets einen Dateizeiger in der Datei. Entweder am Anfang oder am Ende. Wo genau, hängt vom eben besprochenen Modus ab. Beim Modus r+ wird der Zeiger am Anfang platziert. Wenn die Datei einmal geöffnet ist, arbeitet man mit diesem Dateizeiger weiter. Aus diesem Grund wird der Status dieses Dateizeigers zuerst in einer Variablen gesichert. Diese Variable heißt im Beispiel $fp wie file pointer. Diese Bezeichnung ist schön kurz und bedeutet nichts weiter als Dateizeiger. Du könntest diese Variable aber auch $zeiger oder $dateizeiger nennen. Die Namenswahl bleibt dir überlassen! Mit Dateizeiger sieht die Zeile folgendermaßen aus: $fp = fopen("Dateiname", "Modus");

      Du hast Probleme, dir etwas unter diesem Dateizeiger vorzustellen? Stelle es dir wie einen unsichtbaren Cursor vor! Am Anfang steht der Cursor am Beginn der Textdatei. Diesen Stand sicherst du in der Variablen $fp. Im Laufe des Skripts bewegst du diesen unsichtbaren Cursor hin und her!

      Die Funktion fgets() Damit haben wir die erste Zeile des Skripts abgearbeitet. Doch was passiert danach? $counter = fgets($fp, 10);

      Hier kommt die neue Funktion fgets() ins Spiel. Diese Funktion liest Daten aus einer Datei. Der Lesevorgang endet, wenn die Zeile bzw. Datei zu Ende ist. Oder wenn die maximale Zahl an Bytes erreicht ist. Die Grundsyntax dieser Funktion mit diesen gerade erwähnten Argumenten sieht folgendermaßen aus: fgets($fp, Länge_in_Byte)

      Zuerst benötigt die Funktion also den eben ermittelten Dateizeiger. Kein Problem, dafür steht schließlich die Variable $fp bereit. Auch das zweite Argument ist kein Rätsel: Hier muss eine Höchstlänge angegeben werden, und zwar in Byte. Schließlich heißt es nicht umsonst: Der Lesevorgang endet auch dann, wenn die maximale Zahl an Bytes erreicht ist!

      251

      Kapitel

      10

      Besucherzähler selbst gebaut Im Beispiel habe ich mich für die 10 entschieden. Im Klartext: Dein Counter kann bis zu neun Stellen besitzen. Sollte die Zahl länger sein, werden die restlichen Stellen einfach beim Lesen und Schreiben ignoriert, abgeschnitten! (Probiere es ruhig aus. Schreibe eine sehr lange Zahl in die Datei count.txt. Prüfe, wie viele Stellen angezeigt werden!) Zurück zu unserer Funktion: Sie liest die Daten aus der Datei, beim allerersten Aufruf ist das die Zahl 0. Diese Zahl wird nun in der Variablen $counter gesichert. Beachte: Der geheimnisvolle Dateizeiger ist bei dieser Aktion schnurstracks ans Ende der Zeile gewandert! Diese Position musst du dir merken!

      Daten in eine Textdatei schreiben Die nächsten beiden Zeilen erschließen sich sicher sofort: echo $counter; $counter++;

      Der aus der Textdatei ausgelesene Wert wird angezeigt und um 1 erhöht.

      Dateizeiger zurücksetzen per rewind() Doch was passiert in der nächsten Zeile? Hier wird der Dateizeiger zuerst an den Anfang der Datei zurückgesetzt. Denn bisher blinkt unser »unsichtbarer Cursor« immer noch am Dateiende und dort nützt er uns nichts. Das Zurücksetzen an den Anfang gelingt mit Hilfe der Funktion rewind(). rewind($fp);

      Da es sich hier nur um eine Zeile handelt, bewirkt rewind() das Gleiche, als ob du in deiner Textverarbeitung auf die Tastenkombination (Strg) + (Pos1) drücken würdest. Auch da springt der Cursor an den Anfang der Datei. (Da es nur eine Zeile ist, hätte ich auf dem Wort Datei gar nicht so herumreiten müssen. Hätte die Datei jedoch mehrere Zeilen, würde rewind() an den Anfang der allerersten Zeile springen.) 252

      Rechtevergabe mit chmod

      Die Funktion fputs() So, und nun packst du den erhöhten Wert aus der Variablen $counter zurück in die Textdatei count.txt. Dabei hilft dir die Funktion fputs(). Diese Funktion schreibt Daten in eine Datei, und zwar zeilenweise. Die Grundsyntax sieht so aus: fputs($fp, Daten)

      Die Funktion schreibt also ab der Position des Dateizeigers los. Sie trägt im Beispiel also den neuen Zählerstand aus $counter in die Datei ein: fputs($fp, $counter);

      Was passiert dabei eigentlich mit dem alten Wert? Der wird einfach überschrieben, da sich der Dateizeiger vor Ausführung der Funktion am Anfang befand! Schließlich hatten wir die Funktion fgets() nicht umsonst eingesetzt.

      Datei schließen mit fclose() Am Ende der Schreiberei sollte eine Datei stets wieder geschlossen werden. Das gelingt mit der Funktion fclose(), wie file close. Als Argument wird dabei wieder der Dateizeiger übergeben: fclose($fp);

      So einfach ist das also mit dem Zähler!

      Rechtevergabe mit chmod Auf deiner lokalen Festplatte funktioniert sicher alles ganz fantastisch. Du möchtest das Beispiel auf den Webserver laden und online ausprobieren? Mit FTP, wie im Anhang erklärt? Dann beachte unbedingt eine Besonderheit im Zusammenhang mit der Textdatei count.txt! Schließlich wird in diese Datei geschrieben. Was auf dem lokalen Computer prima funktioniert, bereitet auf dem Webserver unter Umständen einige Schwierigkeiten. Du musst bei vielen Dienstleistern erst die entsprechenden Rechte vergeben, damit in diese Datei geschrieben werden kann. 253

      Kapitel

      Besucherzähler selbst gebaut

      10 Wenn du die Rechtevergabe vergisst, hagelt es unter Umständen Fehlermeldungen!

      Die Besucher besitzen normalerweise nur Leserechte. Nach dem Überspielen auf den Webserver gilt die Datei als schreibgeschützt. Wie hebt man den Schreibschutz in einem Unix/Linux-System auf dem Webserver auf? Das gelingt mit dem Befehl chmod.

      chmod 777 Die Radikallösung: Gib die Datei komplett zum Lesen, Schreiben und Ausführen frei. Das entspräche dem Befehl chmod 777. Du arbeitest mit dem von mir empfohlenen Programm FileZilla? Verbinde dich mit dem Server, wie im Anhang gezeigt. Achte darauf, dass die Datei count.txt zu sehen ist. Klicke im rechten Bereich mit der rechten Maustaste auf diese Datei. Wähle nun den Befehl DATEIATTRIBUTE. Das Fenster DATEIATTRIBUTE ÄNDERN erscheint. Hake alle Optionen ab (das sind 3 x 3 Häkchen je bei LESEN/SCHREIBEN/AUSFÜHREN) und klicke auf OK. Jetzt wird die Datei komplett freigegeben, im Hintergrund wird der Befehl chmod 777 ausgeführt. Mit diesen Einstellungen gibst du die Datei komplett frei. Das funktioniert zwar, ist aus Sicherheitsgründen aber keinesfalls die beste Lösung!

      chmod 666 oder 644 Bei vielen Dienstleistern genügt aber auch der Befehl chmod 666 oder gar chmod 644 vollkommen. Das bedeutet, dass du beim Wert 666 allen drei Gruppen (Besitzer, Gruppe, Öffentlich) immerhin Lese- und Schreibberechtigung erteilst. Beim noch restriktiveren Wert 644 bekommt nur der Besitzer die zusätzliche Schreibberechtigung. Je restriktiver die Berechtigung, desto besser. Probiere also auf jeden Fall, ob bei dir auch eine schwächere Berechtigung noch funktioniert! 254

      Rechtevergabe mit chmod

      Probiere es aus: Häufig reicht auch schon chmod 666.

      Schaue in FileZilla auch mal in die Spalte Berechtigung. Suche in der nun angezeigten Textdatei die entsprechende Zeile für die count.txt. Die Zeichenfolge -rwxrwxrwx entspräche der zuerst zugewiesenen Vollberechtigung mit chmod 777. Für chmod 666 sieht das Ganze so aus: -rw-rw-rw-. Interessant zu wissen: Das r steht für read, das w für write und x für execute. Die Berechtigungsreihenfolge lautet: Owner, Group, Other.

      Geht es gar ganz ohne? Experimentiere, ob dein Counter bei dir auch bei weiteren Einschränkungen der Benutzerrechte noch funktioniert. Zumindest beim Dienstleister 1 und 1 GmbH (www.puretec.de) klappt es auch dann, wenn nur dem Besitzer (Owner) Lese- und Schreibrechte eingeräumt wurden. Das entspräche einem chmod 600 und damit bei der DIRINFO-Anzeige folgender Zeichenfolge: -rw-------. Im Klartext: Du brauchst zumindest bei diesem Dienstleister (und inzwischen auch bei vielen anderen) gar nichts mit der Datei count.txt zu machen. Beim Dienstleister Neue Medien Münnich (www.all-inkl.com) dagegen klappte es nicht von Hause aus, aber mit einem Trick! Lege eine Datei namens .htaccess (mit Punkt beginnend und ohne Endung!) in das Wurzelverzeichnis deiner Präsenz und notiere dort Folgendes: AddHandler php-cgi .php .php5

      255

      Kapitel

      Besucherzähler selbst gebaut

      10

      Dadurch wird PHP als CGI-Version ausgeführt, nicht mehr als Modul – viele Restriktionen fallen dadurch weg. Die Hinweise aus diesem Abschnitt gelten übrigens auch für das Gästebuch und für die Umfrage. Denn auch bei diesen Beispielen schreibst du in und liest aus Dateien. Behalte das am besten gut im Hinterkopf!

      Counter de luxe mit Cookies Der Counter hat bisher einen großen Haken: Es handelt sich um einen HitCounter. Wenn du 100-mal auf den RELOAD-Button klickst, simulierst du damit 100 Hits. Das macht sicher ganz schön etwas her, doch damit belügst du dich nur selber. Ich schlage eine Lösung vor, die etwas näher an der Wahrheit ist. Sie funktioniert mit den im vorigen Kapitel kennengelernten Cookies. Ran an den neuen Quelltext: Diesmal zeige ich dir die gesamte PHP-Datei. Hinweis zur CD: Ich habe das Projekt in einem separaten Unterordner namens realcount gespeichert: Ein Cookie-Textcounter <meta http-equiv="content-type" content="text/html; charset=utf-8">

      Ein Textcounter

      Die Seite wurde
      256

      So funktioniert das Skript echo $counter; if (empty($_COOKIE["count"])) { $counter++; } rewind($fp); fputs($fp, $counter); fclose($fp); ?>
      -mal aufgerufen.



      So funktioniert das Skript Die Wirkungsweise des Skripts ist eigentlich ganz einfach. Zuerst erzeugst du mit der Zeile setcookie("count", "yes"); ein Cookie. Der Name lautet count, der Wert yes. (Der Wert spielt im Beispiel aber nur eine untergeordnete Rolle.) Da kein Enddatum angegeben wurde, handelt es sich um ein Sitzungscookie. Es verfällt nach Schließen des Browsers. Zur Erinnerung: Die Cookievergabe muss ganz am Anfang der Datei geschehen, noch vor dem einleitenden HTML-Tag. So wird das Cookie gleich im Header an den Browser geschickt (und von diesem hoffentlich akzeptiert). Die folgenden Zeilen prüfen nun, ob das Cookie mit dem Namen count leer ist, also noch nicht existiert. Beim ersten Aufruf der Seite stimmt die Bedingung, denn dann existiert das Cookie tatsächlich noch nicht. (Ein vom Browser akzeptiertes Cookie kommt erst nach einem Reload zur Geltung!) if (empty($_COOKIE["count"])) { $counter++; }

      Nur dann wird der Zähler erhöht und das ist gut so. Sobald das Cookie nach einem Neuladen existiert, bleibt der Zähler unangetastet. Er wird erst wieder erhöht, wenn der Benutzer den Browser schließt, wieder öffnet und deine Seite erneut besucht! Einen Haken gibt es bei der Sache: Dieser Zählstopp funktioniert nur dann, wenn der Benutzer Cookies akzeptiert. Da das in den meisten Fällen jedoch der Fall ist, handelt es sich um eine funktionierende Zählsperre. 257

      Kapitel

      10

      Besucherzähler selbst gebaut

      Schlussbemerkung Endlich kannst du einen eigenen Counter schreiben. Zähle entweder nur die Hits. Oder erstelle einen Counter de luxe mit Cookie-Zählstopp. Wie auch immer: Du weißt, wie du Daten in Dateien ablegen kannst. Du sicherst Informationen auf dem Webserver und liest sie wieder aus!

      Zusammenfassung 0 Du kennst die Funktion fopen() zum Lesen einer Datei. Dabei wird ein Dateizeiger in der Datei positioniert, dessen Status du in einer Variablen festhältst: $fp = fopen("Dateiname", "Modus"). 0 Du kennst die Funktion fgets() zum zeilenweisen Auslesen der in einer Datei enthaltenen Daten: fgets($fp, Länge_in_Byte). 0 Du weißt, dass du mit der Funktion rewind() den Dateizeiger an den Anfang der Datei setzen kannst: rewind($fp). 0 Du kennst die Funktion fputs(), die ab der Position des Dateizeigers Daten in eine Datei schreibt: fputs($fp, Daten). 0 Mit fclose() wird eine Datei wieder geschlossen: fclose($fp). 0 Du weißt, dass du einer per FTP auf den Webserver geladenen Textdatei in der Regel die entsprechenden Rechte erteilen musst. Dafür nutzt du den Befehl chmod 666, der dem Owner, der Group und der Öffentlichkeit Lese- und Schreibberechtigung erteilt!

      Ein paar Fragen … 1. Mit welcher Funktion kannst du eine Datei öffnen? 2. Welcher Modus sorgt dafür, dass eine Datei im Lese- und Schreibmodus geöffnet wird und dass gleichzeitig der Dateizeiger am Anfang steht? 3. Mit welcher Funktion setzt du den Dateizeiger an den Anfang der Datei zurück? 4. Mit welcher Funktion schreibst du Daten in eine Datei, beginnend mit der Position des Dateizeigers? 5. Mit welcher Funktion wird eine Datei wieder geschlossen? 258

      … und ein paar Aufgaben 6. Was musst du mit einer Textdatei in der Regel machen, nachdem du sie auf den Webserver geladen hast? Wie erreichst du, dass Schreibzugriff besteht?

      … und ein paar Aufgaben 1. Bisher handelt es sich um ein Sitzungscookie. Wandle das Beispiel so um, dass der Zählstopp eine Stunde lang gilt! 2. Wandle das Beispiel so um, dass der Zählstopp 24 Stunden lang gilt!

      259

      11 Eine Umfrage mit grafischer Auswertung Was hältst du von Matheklausuren? Wie erfolgreich ist die Klimapolitik der Bundesregierung? Schafft es Hansa Rostock wieder zurück in die 1. Bundesliga? Wie findest du meine Homepage? Egal welches Thema dich interessiert – finde heraus, was andere darüber denken! In diesem spannenden Kapitel programmierst du eine richtig gehende WebUmfrage. Dabei lernst du, wie man $ Strings anhand von Trennzeichen in Arrays umwandelt $ durch Trennzeichen separierte Textdateien einliest $ ein Säulendiagramm für die grafische Darstellung erstellt $ Radiobuttons in einem Formular ausliest Damit du durch das Beispiel gut durchsteigst, habe ich es wieder möglichst einfach gehalten. Trotzdem kommt hier schon einiges auf dich zu!

      261

      Kapitel

      11

      Eine Umfrage mit grafischer Auswertung

      So sieht das Beispiel aus Nun zum Beispiel! Erinnerst du dich noch an die Umfrage aus Kapitel 1? Richtig, es ging um die Meinung zu deiner Homepage. Am Anfang des Buchs musstest du dich noch mit einer statischen Lösung begnügen. Im diesem Kapitel hast du genügend Know-how beisammen, um das Beispiel mit Leben zu füllen!

      Umfrage und Auswertung werden auf getrennten Seiten geführt.

      Der Unterschied zu Kapitel 1: Statt mit einer statischen HTML-Datei arbeitest du von Anfang an mit PHP. Die Umfrage selber erfolgt in der Datei 0 umfrage.php Für die attraktive grafische Auswertung sehen wir folgende Datei vor: 0 ergebnis.php Zäume das Pferd diesmal von hinten auf: Fange mit dieser attraktiven grafischen Auswertung an!

      262

      Durch Komma separierte Textdatei

      Durch Komma separierte Textdatei Die große Frage lautet: Wie speicherst du die Daten? In welcher Form? Kein Problem. Natürlich in einer Textdatei! Im Beispiel heißt diese Datei 0 result.txt Bei unserer Beispiel-Umfrage müssen drei Werte gesichert werden. Zum einen der Wert für die OPTION 1 (hier: echt super), für die OPTION 2 (hier: ziemlich gut) und für die OPTION 3 (hier: geht so). Jeder Wert besteht aus einer Ziffer, die die Anzahl der entsprechenden Stimmen repräsentiert. Meine Idee: Trenne diese drei Werte jeweils durch ein Komma, und zwar ohne irgendwelche Leerzeichen zwischendrin: 0 Wert_1,Wert_2,Wert_3 Und schon handelt es sich um eine der berühmten kommaseparierten Textdateien.

      Datei result.txt anlegen Jetzt kommt dein Part: Bereite diese Datei result.txt einfach schon einmal vor. Gehe dabei so vor, wie am Beispiel der count.txt aus dem vorigen Kapitel gezeigt. Dabei vergibst du gleichzeitig deine Stimme, denn das Skript geht davon aus, dass mindestens ein Wert vergeben wurde. Die Datei soll im Beispiel also folgendermaßen aussehen: 0,1,0

      Das bedeutet: Bisher wurde eine Stimme abgegeben, und zwar für die mittlere Option. Du willst diese Datei auf den Webserver laden? Beachte auch hier die ausführlichen Hinweise zum Schreibschutz aus dem vorigen Kapitel. Damit das Beispiel auch online funktioniert, musst du bei einigen Dienstleistern den Befehl chmod 666 ausführen!

      263

      Kapitel

      11

      Eine Umfrage mit grafischer Auswertung

      Quelltext der Datei ergebnis.php Die Textdatei result.txt hast du angelegt? Wunderbar! Dann zeige ich dir nun den Quelltext der Auswertungsdatei ergebnis.php. Du siehst alles, was zwischen den Tags und steckt. Schreibe das Beispiel ab oder schaue auf die CD zum Buch, Ordner kapitel11:

      Die Umfrage-Ergebnisse:

      Anzahl der Stimmen:

      -Kram weglassen können? Na klar! Aber ich wollte auf jeden Fall einen Umbruch vermeiden. Mit anderen Worten: Ich wollte verhindern, dass die »Kerzensäule« auseinandergerissen wird!

      Have a break: Abbruchbedingung einfügen Reagiere auf Fehleingaben! Gegen die Eingabe von Buchstaben oder negativen Zahlen ist das Skript von Hause aus immun. Dann wird die Schleife schlicht und einfach nicht ausgeführt. Auch eine 0 wird dank !empty() schon von vornherein abgeblockt. Doch manchmal kann man gar nicht so dumm denken, wie es kommt. Ein Spaßvogel gibt eine irrwitzig hohe Zahl ein, z. B. zehntausend? Dann muss 194

      Und noch eine Schleife: foreach dein Webserver ganz schön arbeiten, um alle diese zehntausend Kerzen an den Browser zu schicken. Was hier spaßig klingt, hat ernste Hintergründe. Gerade solche Möglichkeiten machen dein Skript verwundbar für Angriffe der »Skript-Kids«. Dahinter verbergen sich Amateure die es nur darauf abgesehen haben, deine Präsenz zu stören. Und schon die wiederholte Durchführung solcher »Angriffe« kann deinen Webserver lahm legen und die Site für andere nicht mehr erreichbar machen. Welche Möglichkeit hast du in diesem Fall? Füge eine Abbruchbedingung ein! Nutze das Schlüsselwort break. Das Schlüsselwort break führt innerhalb einer Schleife wie do, do-while oder for zu einem Abbruch der Schleife. Die Schleife wird sofort verlassen und die Programmausführung geht unterhalb der Schleife weiter. Definiere solch eine Abbruchbedingung! Ab der Zahl 108 soll das Skript mit dem Erzeugen von Kerzen aufhören. Mit anderen Worten: Es sollen höchstens 108 Kerzen gezeichnet werden, egal wie hoch das angebliche Alter des Benutzers auch sein mag. Dafür arbeite ich mit einer einfachen ifAbfrage. Diese prüft, ob der Wert größer als 108 ist und setzt im Zweifelsfalle das Schlüsselwort break in die Schleife ein. Da ich im Vergleich zum vorigen Beispiel nur die Schleife verändert habe, zeige ich dir lediglich die erweiterte Schleifenkonstruktion mit eben dieser Abbruchbedingung. Du findest das Beispiel in der Datei kerzen2.php. for ($i = 1; $i <= $_POST['anzahl']; $i++) { echo "
      Kerze$i
      echt super     


      264

      Durch Komma separierte Textdatei
      ziemlich gut     
      geht so     


      Die ersten Zeilen im Überblick Schritt für Schritt weihe ich dich nun in die Geheimnisse dieses Skripts ein. Was steckt hinter den folgenden Zeilen? $datei = "result.txt"; $fp = fopen($datei, "r"); $vote = fread($fp, filesize($datei)); fclose($fp);

      Zuerst speicherst du den Namen der Textdatei in der Variablen $datei, und zwar aus reiner Bequemlichkeit. Als Nächstes öffnest du diese Datei. Da wir an dieser Stelle nichts mehr in die Datei hineinschreiben müssen, genügt der Nur-Lesemodus r. Auch hier wird übrigens wieder mit dem unsichtbaren Dateizeiger gearbeitet (Variable $fp).

      Die Funktionen fread() und filesize() Nun zur dritten Zeile: Hier liest du den Dateiinhalt aus und speicherst ihn in der Variablen $vote. Im Beispiel handelt es sich um die Zeichenfolge 0,1,0. Zum Auslesen benötigst du die Funktion fread(). Du übergibst der Funktion fread() zwei Argumente, einmal den Dateizeiger $fp und zum anderen die Maximalgröße in Byte. Die Funktion liest den Dateiinhalt bis zu dieser Größe – oder aber bis zum Ende. Als Argument für die Maximalgröße kommt zum ersten Mal die Funktion filesize() zum Einsatz.

      265

      Kapitel

      11

      Eine Umfrage mit grafischer Auswertung

      Die Funktion filesize() ermittelt die Größe einer Datei. Die Syntax lautet ganz einfach filesize("Dateiname"), wobei ich statt des Namens natürlich auch eine Variable übergeben kann, wie im Beispiel. Der Vorteil dieser Funktion liegt auf der Hand: Statt eine Höchstlänge in Byte angeben zu müssen, ermittle ich einfach die exakte Länge der Datei. So kommt es weder zum Verschwenden von Speicherplatz noch zum versehentlichen Abschneiden zu langer Strings. Nun steht dir der auszuwertende String zur Verfügung und die Datei kann mit der letzten der vier Zeilen seelenruhig wieder geschlossen werden. Doch wie machst du aus der Zeichenfolge 0,1,0 oder 24,15,6 ein schickes Diagramm? Lies weiter, dann verrate ich es dir!

      Text am Trennzeichen zerlegen Schau dir nun folgende Passage an: // String zerlegen, Array entsteht $vote = explode(",", $vote);

      In der ersten Zeile handelt es sich um einen beschreibenden Kommentar. Wie du siehst, arbeite ich in meinen Skripts viel mit dieser Technik. Die zweite und eigentlich wichtige Zeile beherbergt eine neue und ziemlich geniale Funktion.

      Die Funktion explode() Es handelt sich um die Funktion explode(). Die Syntax lautet: explode("Trennzeichen", "Zu_trennender_String")

      Die Funktion explode() zerteilt einen String anhand eines Trennzeichens. Im Beispiel verwende ich das Komma, aber du könntest auch ein anderes Zeichen als Trenner festlegen. Der String wird dabei in ein Array umgewandelt, also in eine dieser schon häufig besprochenen Wertelisten. Die einzelnen Zahlen (bisher zwei Nullen und eine Eins) werden so zu den Elementen des Arrays. Stelle es dir so vor, als ob an jedem Komma ein klitzekleiner Sprengsatz hängt. Dieser sorgt dafür, dass die einzelnen Werte »auseinander explodieren«. 266

      Die unsichtbare Tabelle für das Diagramm Die drei auf diese Art getrennten Ziffern 0, 1 und 0 werden jetzt als erster, zweiter bzw. dritter Wert des Arrays angesprochen. Halt, das ist nicht ganz korrekt: Eigentlich müssen sie als nullter, erster und zweiter Wert angesehen werden, denn die Zählung beginnt bei numerischen Arrays schließlich bei null! Genau dieses Technik kommt im Beispiel zum Einsatz: Die Daten werden zuerst in einer kommaseparierten Textdatei gespeichert. Die einzelnen Zahlen werden dann zu den Elementen eines Arrays. Die erste Zahl lässt sich z. B. über Arrayname[0] ansprechen, also über $vote[0], die zweite Zahl über $vote[1] und die dritte über $vote[2].

      Gesamtzahl aller Wahlvorgänge Die nächste Passage ist nicht weiter kompliziert. Sie ermittelt die Gesamtzahl aller Wahlvorgänge und legt diesen Wert in der Variablen $gesamt ab. // Gesamtzahl aller Wahlvorgänge $gesamt = $vote[0] + $vote[1] + $vote[2];

      Im Beispiel ergibt die Gesamtzahl den Wert 1, es handelt sich bisher um deine eigene wunderbare Stimme.

      Die unsichtbare Tabelle für das Diagramm So weit, so gut, doch wie entsteht das Säulendiagramm? Ganz einfach – erinnerst du dich an das Diagramm aus Kapitel 6? Auch hier verwende ich den gleichen Trick: Das Säulendiagramm entsteht durch unterschiedlich lange Zellen dreier unsichtbarer Tabellen! Durch verschiedene Farben gelingt auch die optische Unterscheidung. Überzeuge dich: Überspringe einfach die nächsten Zeilen und schaue nun zum Beginn der ersten Tabelle. Oberhalb der Tabelle wird erst einmal die Gesamtstimmenzahl ausgegeben:

      Anzahl der Stimmen:



      267

      Kapitel

      Eine Umfrage mit grafischer Auswertung

      11

      Doch danach geht es los mit den Säulen. Die erste unsichtbare Tabelle (border="0") entsteht:
      echt super     


      Die erste Zelle ist 100 Pixel lang und beherbergt den Text echt super. Interessant ist die zweite Zelle: Wie erreiche ich hier, dass die Länge der Säule variiert? Ich gebe dem Attribut width der zweiten Zelle einen dynamischen Wert mit auf den Weg. Diesen entnehme ich der Variablen laenge0. (Wie wir auf diese Variable kommen, erfährst du gleich!) Die dritte Zelle gibt lediglich die Anzahl der Stimmen aus und damit ist die erste Säule auch schon fertig!

      … und wieder etwas Mathe: Dreisatz Wie du siehst – das Diagramm selber ist dank des »Tabellentricks« kein Problem. Für die Länge der einzelnen Zellen könnten wir eigentlich auch die Werte aus vote[0], vote[1] oder vote[2] verwenden. Für jede Stimme ein Pixel. Wäre das nicht das Einfachste? Zugegeben, das stimmt. Doch wo bleibt die Attraktivität? Wenige Pixel Längenunterschied machen optisch kaum etwas her. Ein anderes Problem besteht in der Höchstlänge: Was machst du bei Zehntausenden von Votern? Dann wären manche Säulen im Zweifelsfalle tausende Pixel breit? So breite Bildschirme gibt es doch gar nicht! Alles in allem musst du die Werte aus $vote[0], $vote[1] oder $vote[2] noch irgendwie umwandeln, damit alles hübsch wohlgeformt aussieht und auf den Bildschirm passt. Das machen wir gleich: Wir zaubern und speichern dann die neuen Werte in laenge0, laenge1, laenge2.

      268

      … und wieder etwas Mathe: Dreisatz

      Verhältnisgleichung Hokuspokus, Zauberei: Du gibst die Breite der Säulen einfach im Verhältnis zueinander an. Du sorgst gleichzeitig dafür, dass eine bestimmte Höchstbreite nie überschritten werden kann! Und nun schau bitte zu folgender Passage weiter oben im Skript, dort »hüpft das Kaninchen aus dem Zylinder«: // Höchstlänge der Balken angeben $laenge = 400;

      Die Höchst-Balkenlänge gebe ich im Beispiel mit 400 (wie 400 Pixel) vor. (Du kannst diesen Wert gerne variieren!) Nun sollen die Anteile der drei Balken gemessen werden, und zwar im Verhältnis zueinander. Arbeite mit einer Verhältnisgleichung, mit einem Dreisatz. Setze die Votes für jede einzelne der drei Optionen einfach zur Gesamtlänge (hier 400) ins Verhältnis! Ich hoffe, dass dir das Prinzip noch aus dem Matheunterricht geläufig ist. Hätte ich das mit dem Matheunterricht jetzt nicht erwähnen sollen? Wie auch immer: Auf diese Weise kannst du die Länge für den ersten Balken (Variable $laenge1) folgendermaßen berechnen: // Anteil von Balken 1 (Indexwert 0!) $laenge0 = $vote[0] * $laenge / $gesamt;

      Alles klar? Genau das gleiche Spielchen führst du auch für die beiden anderen Werte durch. Einen Haken hat die Geschichte: Die Ergebnisse sind meist nicht glatt, es handelt sich um Bruchzahlen. Für das Attribut width einer Tabellenzelle benötigst du jedoch Ganzzahlen! Aus diesem Grund müssen die drei Werte noch auf Ganzzahlen gerundet werden. Dazu dient die allseits bekannte und beliebte Funktion round(). $laenge0 = round($laenge0); $laenge1 = round($laenge1); $laenge2 = round($laenge2);

      Damit haben wir das fehlende Puzzlesteinchen eingefügt und du müsstest das Skript nun hoffentlich gut durchschauen! 269

      Kapitel

      Eine Umfrage mit grafischer Auswertung

      11 Die Anteile aller Stimmen werden gleichmäßig verteilt.

      Tipp: Verändere doch einmal die Textdatei result.txt. Tippe statt 0,1,0 einmal 24,15,6! Sofort verändern sich die Säulen! Nanu, was ist denn da passiert? Du verwendest die Werte 0,0,0 als Ausgangspunkt in der result.txt? Dann gibt es gleich mehrere dicke Fehlermeldungen. Kunststück, eine Division durch 0 ist nicht gestattet! Damit hast du den Pferdefuß dieses Skripts entdeckt. Deshalb sollte mindestens eine der drei Ziffern von Beginn an auf 1 gesetzt werden.

      Die Umfrageseite: So funktioniert das Skript Nun kommt der schwerste Teil. Programmiere die eigentliche Umfrageseite. Hier soll der Nutzer seine Stimme abgeben. Dabei wollen wir außerdem versuchen, Mehrfachvotes möglichst zu unterdrücken.

      Der Quelltext der Datei umfrage.php Zuerst zeige ich dir den Quelltext im Überblick. Es handelt sich um die komplette Seite umfrage.php. Sie besteht aus einem Formular, das den Inhalt an sich selbst schickt. Außerdem gibt es einen Link zur noch zu erstellenden Seite ergebnis.php und natürlich sehr viel PHP-Code, den wir auf den nächsten Seiten ausführlich besprechen müssen. Das Beispiel findest du auch in der Datei umfrage.php aus dem Ordner kapitel11:

      270

      Die Umfrageseite: So funktioniert das Skript Unsere Web-Umfrage <meta http-equiv="content-type" content="text/html; charset=utf-8">

      Wie findest du meine Page?

      echt super
      ziemlich gut
      geht so

      \n"; } else { // Formular abgeschickt? Aber bisher noch nicht gevoted? if (empty($_COOKIE["voted"]) && isset($_POST["ergebnis"])) { $ergebnis = $_POST["ergebnis"]; // Wert aus Formular überprüfen $muster = "/^[0-2]$/"; // regulärer Ausdruck für 0-2 if (preg_match($muster, $ergebnis) == 0) { die("

      Abbruch wegen Manipulation!

      "); } // Dateiname in Variable speichern $datei = "result.txt"; $fp = fopen($datei, "r+"); $vote = fread($fp, filesize($datei)); // String mit Komma als Trenner in Array zerlegen $vote = explode(",", $vote); // Welcher Wert wurde im Formular ausgewählt? // Diese Position wird um 1 erhöht! $vote[$ergebnis]++;

      271

      Kapitel

      11

      Eine Umfrage mit grafischer Auswertung // String neu zusammensetzen $vote = $vote[0].",".$vote[1].",".$vote[2]; rewind($fp); // neuen String in Datei schreiben fputs($fp,$vote); fclose($fp); echo "

      Danke für die Übermittlung der Daten!

      \n"; } } ?>

      [ Umfrageergebnisse ansehen ]



      Ein paar erste Erklärungen Ganz zu Beginn der Datei erzeuge ich ein Cookie namens voted. Dieses wird nach einem Neuladen der Seite zur Verfügung stehen. Das Prinzip ist dir schon aus dem vorigen Kapitel bekannt. Besonders wichtig ist auch das Attribut action. Das Formular schickt den Inhalt praktisch an sich selbst. Aus Sicherheitsgründen setzen wir allerdings nicht die Servervariable $_SERVER['PHP_SELF'] ein, sondern wieder direkt den Dateinamen umfrage.php. Denn auch Servervariablen können manipuliert werden. action="umfrage.php"

      Auch das Formular selber kennst du schon, und zwar aus Kapitel 1. Es arbeitet mit Radiobuttons. Interessant sind die Werte, denn hier gibt es eine kleine Veränderung im Gegensatz zur »Urvariante«. Die Felder besitzen statt 1, 2 und 3 einfach die Werte 0, 1 und 2. Das ist Absicht, ich will diese Zahlen mit den ersten Werten eines numerischen Arrays in Einklang bringen. Die 0 steht schließlich für den Array-Eintrag Nummer 1. Dazu gleich mehr. Auch die Versendemethode des Formulars (method="post") habe im Vergleich zur Urfassung präzisiert. Schließlich wollen wir die Werte im Array $_POST und nicht im Array $_GET empfangen. 272

      Schummeln verboten: Mehrfachvotes unterdrücken

      Schummeln verboten: Mehrfachvotes unterdrücken Das Besondere an unserem Beispiel ist aber der Schummelschutz. Schaue dir nun die nächsten Zeilen an: /* Submit nur zeigen, wenn Formular noch nicht abgeschickt/gevoted */ if (empty($_COOKIE["voted"]) && !isset($_POST["ergebnis"])) { echo "\n"; } else {

      Im Klartext: Der SUBMIT-Button zum Absenden des Formulars soll nur dann angezeigt werden, wenn folgende Bedingungen zutreffen: 0 empty($_COOKIE["voted"]): Es ist noch kein Cookie namens voted vorhanden. 0 !isset($_POST["ergebnis"]): Der Formularinhalt wurde noch nicht abgeschickt, die Variable $_POST["ergebnis"] ist noch nicht gesetzt. Das sorgt für einen gewissen Schutz vor Doppelvotes, denn nach dem Absenden der Ergebnisse ist der SUBMIT-Button erst einmal unsichtbar. So viel schon vorweg: Einen absolute Schummelschutz bei WebUmfragen kann und wird es nie geben! Welche Tricks du dir auch immer ausdenkst: Der Benutzer kann alles umgehen: Sie oder er braucht ja nur mit einem anderen Browser vorbeizusurfen, Cookies auszuschalten, von einem anderen Computer noch einmal zu voten usw. usf. Erst wenn sich jeder mit Benutzernamen und Passwort bei dir genau identifizieren kann, ist eine halbwegs zuverlässige Abstimmung möglich. Doch wer voted dann noch, wenn es solchen Aufwand macht? Lassen wir uns von diesen Schummelmöglichkeiten nicht entmutigen. Spaß soll es machen. Und solange niemand versucht, mit diesem Skript die Bundeskanzlerin zu wählen, ist alles in Ordnung. (Im Kapitel 12 erfährst du, wie du eine Reload-Sperre erzeugst. Im Übungsteil von Kapitel 12 auf Seite 293 baust du diese Reload-Sperre dann auch zusätzlich in das Umfrageskript ein). 273

      Kapitel

      11

      Eine Umfrage mit grafischer Auswertung

      Der else-Zweig Unser Schummelschutz wird auch im else-Zweig verwendet: } else { // Formular abgeschickt? Aber bisher noch nicht gevoted? if (empty($_COOKIE["voted"]) && isset($_POST["ergebnis"])) {

      Das Eintragen der Daten soll nur dann geschehen, wenn folgende Bedingungen zutreffen: 0 empty($_COOKIE["voted"]): Es ist noch kein Cookie namens voted vorhanden. Diese Bedingung verändert sich nicht. 0 isset($_POST["ergebnis"]): Der Formularinhalt wurde schon abgeschickt und die Variable $_POST["ergebnis"] ist also gesetzt. Das ist der wichtige Unterschied zur vorherigen if-Abfrage! Unser Cookie schützt z. B. vor einem Doppelvote bei Druck auf RELOAD. Außerdem soll nur dann ein Eintrag in die Datei result.txt erfolgen, wenn der Voter überhaupt eine Auswahl getroffen hat.

      Nach erfolgreicher Stimmenabgabe wird der SUBMIT-Button ausgeblendet.

      … und wieder entsteht ein Array Schauen wir uns den eigentlichen Akt des Eintragens an. Die Befehle dafür stecken in folgenden Zeilen:

      274

      $ergebnis = $_POST["ergebnis"]; // Wert aus Formular überprüfen $muster = "/^[0-2]$/"; // regulärer Ausdruck für 0-2 if (preg_match($muster, $ergebnis) == 0) { die("

      Abbruch wegen Manipulation!

      "); }

      … und wieder entsteht ein Array // Dateiname in Variable speichern $datei = "result.txt"; $fp = fopen($datei, "r+"); $vote = fread($fp, filesize($datei)); // String mit Komma als Trenner in Array zerlegen $vote = explode(",", $vote); // Welcher Wert wurde im Formular ausgewählt? // Diese Position wird um 1 erhöht! $vote[$ergebnis]++; // String neu zusammensetzen $vote = $vote[0].",".$vote[1].",".$vote[2]; rewind($fp); // neuen String in Datei schreiben fputs($fp,$vote); fclose($fp); echo "

      Danke für die Übermittlung der Daten!

      \n";

      Mit dem vorhandenen Wissen kannst du dir die Wirkungsweise eigentlich schon erklären. Es ist praktisch genau so wie in den ersten drei PHP-Zeilen der ergebnis.php.

      Test mit regulärem Ausdruck Doch was ist das für eine komische Konstruktion unterhalb des Kommentars // Wert aus Formular überprüfen? Das ist eine reine Sicherheitsmaßnahme! Ich überprüfe per regulärem Ausdruck, ob die Formularwerte für das Ergebnis genau zwischen 0 und 2 liegen. Wenn das nicht der Fall ist, wurde das Formular mit großer Wahrscheinlichkeit manipuliert. In diesem Fall sorgt das Sprachkonstrukt die() dafür, dass das Skript an dieser Stelle »stirbt«. Im Beispiel gebe ich zusätzlich innerhalb der runden Klammern einen in Gänsefüßchen notierten Abbruchtext aus und beende die HTML-Datei mit den entsprechenden Abschlusstags. Sind dir die regulären Ausdrücke noch vertraut, diese praktischen »Musterschablonen«? Wenn nicht, studiere noch einmal den Abschnitt ab Seite 222. In diesem Fall haben wir es mit dem »Gebilde« [0-2] zu tun. Diese Zeichenfolge steht als Platzhalter für die Zahlen 0, 1 und 2. Andere Werte werden auf diese Weise zuverlässig abgeblockt! Zugegeben – das Skript würde auch ohne diesen Sicherheitscheck arbeiten. Trotzdem solltest du es dir zur Gewohnheit machen: Überprüfe möglichst alle Werte, die aus Formularfeldern übernommen werden und die du im Skript weiterverarbeitest. Denn Hacker könnten deine Formulare manipulie-

      275

      Kapitel

      Eine Umfrage mit grafischer Auswertung

      11

      ren, deren Rückgabewerte verändern und so im Zweifelsfalle Schaden anrichten. (Auch wenn der Schaden in diesem Fall noch nicht dramatisch ist.) Du merkst: Sicherheit fängt schon bei kleinen Beispielen an!

      So arbeitet der Eintrageteil des Skripts Zuerst wird die Datei result.txt wieder geöffnet, und zwar diesmal im Lese- und Schreibmodus (r+). Der String aus der result.txt wird wieder in der Variablen $vote gespeichert. Auch diesmal benötigst du die Funktion explode(), damit der String am Komma zerlegt und in ein Array umgewandelt werden kann. Zur Erinnerung: Der erste Wert ist nun über vote[0] abrufbar! Ich erinnere dich noch einmal daran: Das Formular gibt eine Variable namens $_POST["ergebnis"] zurück. Als Werte stehen die drei Ziffern 0, 1 oder 2 zur Verfügung; je nachdem, welche Option der Surfer ausgewählt hat. Ich wiederhole: 0, 1 oder 2. Hier hat der Autor ausnahmsweise mal eine gewisse Einfachheit gepaart mit Genialität an den Tag gelegt. Denn auch der 1. Wert eines Arrays beginnt ganz zufällig mit 0. Nun kommt die Zeile, in der ich zu einem kleinen »Kunstkniff« gegriffen habe: $vote[$ergebnis]++;

      Diese Zeile erhöht exakt den Wert um 1, der mit der Eingabe des Benutzers korrespondiert. Ein Beispiel: Wenn der Benutzer die dritte Option auswählt, ist in $_POST["ergebnis"] und damit auch in $ergebnis eine 2 gespeichert. Und $vote[2] bezieht sich schließlich auf die letzte Zahl unserer result.txt. Somit wird auch nur die letzte Zahl erhöht. Die restlichen Zeilen sind dann nur noch Pillepalle. Der String wird unter Berücksichtigung des erhöhten Wertes neu zusammengesetzt $vote = $vote[0].",".$vote[1].",".$vote[2];

      und mit Hilfe der schon bekannten Funktionen rewind() und fputs() wieder zurück in die Datei geschrieben. Mit fclose() beenden wir das Spielchen, geben danach einen Dankestext aus und die neue Stimme zählt. Alles klar wie Kloßbrühe? 276

      Schlussbemerkung

      Schlussbemerkung Nicht schlecht, Herr Specht! Du weißt nun, wie du eine Web-Umfrage programmierst. Nutze kommaseparierte Textdateien für die Sicherung mehrerer Daten. Bei dieser Gelegenheit hast du die Cookie-Technologie und das Speichern in bzw. Lesen aus Dateien wiederholt. Gerne kannst du das Skript erweitern und auf deine Bedürfnisse anpassen.

      Zusammenfassung 0 Du kennst die Technik, Daten in kommaseparierten Textdateien zu sichern. Die einzelnen Werte werden einfach durch ein Komma voneinander getrennt. 0 Du kennst die Funktion explode(), die einen String anhand eines Trennzeichens zerlegt und in ein Array umwandelt: explode("Trennzeichen","Zu_trennender_String")

      0 Du weißt, dass du mit der Funktion filesize() die Größe einer Datei ermittelst. Die Syntax lautet ganz einfach filesize("Dateiname"). 0 Du kennst das Sprachkonstrukt die() zum Abbruch von Skripten. 0 Du hast die Cookie-Technologie und das Lesen aus und Schreiben in Dateien wiederholt.

      Ein paar Fragen … 1. Mit welcher Funktion ermittelst du die Größe einer Datei? 2. Ist es möglich, ohne Benutzeranmeldung Umfragen zu erstellen, die zu 100% schummelsicher sind? 3. Welche Funktion zerteilt einen String anhand eines Trennzeichens? 4. Bei welchem Wert beginnt die Zählung in numerischen Arrays? 5. Schaue in die Datei umfrage.php. Es geht um die beiden if-Abfragen zur Ermittlung, ob die Variable $_POST["ergebnis"] vorhanden ist oder nicht. Warum habe ich die Funktion isset() verwendet? Warum geht die Funktion empty() in diesem Fall nicht? (Tipp: Probiere es ruhig einmal aus, ich mache dich besonders auf die erste Option mit dem Indexwert 0 aufmerksam!)

      277

      Kapitel

      11

      Eine Umfrage mit grafischer Auswertung

      … und ein paar Aufgaben 1. Bei nicht abgegebenen Stimmen gibt es eine Fehlermeldung in der Datei ergebnis.php. Unterdrücke die Fehlermeldung. Solange noch keine Stimmen abgegeben wurden, soll statt des Diagramms die Meldung erscheinen: Bisher wurden noch keine Stimmen abgegeben! Tipp: Nutze eine weit umspannende if-Abfrage in Zusammenarbeit mit der Variablen $gesamt!

      Erklärungstext statt Fehlermeldung: ifelse-Struktur im Einsatz.

      2. Baue das Umfrageskript aus ergebnis.php weiter um! Bisher werden hinter den einzelnen Säulen nur die absoluten Werte angezeigt. Sorge dafür, dass die Verteilung außerdem in Prozent eingeblendet wird, wie in der Abbildung gezeigt. Tipp: Arbeite mit einer zusätzlichen Verhältnisgleichung. Ermittle die Prozentwerte und runde diese wieder, so dass keine Nachkommastellen angezeigt werden. Vergiss nicht das Prozentzeichen.

      Auch das gelingt mit einer Verhältnisgleichung: Angabe der prozentualen Verteilung.

      3. Versuche einmal, das Formular aus der Datei umfrage.php zu manipulieren. Vergib für einen der Radiobuttons einen ungültigen Wert, schreibe statt value="0" einfach value="3" oder gar value="ä". Und, zählt die Umfrage noch? 4. Erstelle eine Umfrage zur Beliebtheit deines Klassenlehrers. (Zu dieser Aufgabe findest du ausnahmsweise keine Lösung auf der CD, ich kenne ja deinen Klassenlehrer nicht.)

      278

      12 Das eigene Gästebuch Natürlich! Jeder möchte ein Gästebuch auf seiner Homepage haben. Du bist da keine Ausnahme. Und da du inzwischen weißt, wie du mit Dateien umgehst, steht unserem Beispiel nichts mehr im Wege. Du lernst in diesem Kapitel: $ wie du Formulardaten in eine Textdatei schreibst $ wie du eine gesamte Textdatei auf einen Schlag ausliest $ wie du Hacking-Versuche und Doppeleingaben verhinderst Wir fangen – wie immer – ganz bescheiden an und steigern uns im Laufe des Kapitels. Trotzdem bleibt das Beispiel einfach und durchschaubar. Falls du später in die Gästebuch-Oberliga aufsteigen möchtest, lege ich dir das Kapitel 14 ans Herz. Dort geht es um eine echte Datenbanklösung, die natürlich noch mehr Möglichkeiten bietet.

      279

      Kapitel

      12

      Das eigene Gästebuch

      (Zu) simpel gestrickt: Version 1 Das Motto lautet: Einfach aber attraktiv! Unser Gästebuch sichert Kommentar, Namen und E-Mail-Adresse. Auf Knopfdruck werden diese Daten in einer Textdatei gespeichert und sofort auf der Seite angezeigt.

      Das eigene Gästebuch: Der Kommentar wird in ein Formular eingetragen.

      Lege zuerst also wieder eine Textdatei an. Im Beispiel heißt sie 0 comment.txt Vergiss nicht, den Schreibschutz aufzuheben, wenn du diese Datei auf den Server lädst. Das Stichwort heißt chmod 666, siehe auch Seite 254.

      Das Beispiel im Überblick Und nun wirfst du zuerst einen Blick auf den Quelltext. Ich zeige dir wieder den Bereich zwischen den Tags . Das meiste davon kommt dir bestimmt schon bekannt vor! Den Beispielcode findest du auf der CD im Ordner kapitel12/version1. 280

      (Zu) simpel gestrickt: Version 1

      Einfaches Gästebuch

      Dein Kommentar:

      Dein Name:

      Deine E-Mail-Adresse:

      Bisherige Meinungen:

      $Email"; // Datum ermitteln und formatieren $datum = date("j.n.Y"); // Meinung zusammensetzen $meinung="

      $name ($Email) schrieb am " . "$datum:
      $comment

      \n"; // neue Meinung unten an Datei anhängen: fputs($fp, $meinung); // Datei schließen fclose($fp); } readfile($datei); ?>


      281

      Kapitel

      12

      Das eigene Gästebuch

      Schaue zur ersten und letzten Zeile: Der Autor benutzt das Tag-Paar
      . Damit sieht er eine feste Breite von 600 Pixeln vor. Das sorgt dafür, dass sich der Text auch bei breiten Bildschirmen nicht unendlich in die Länge zieht und besser lesbar bleibt.

      Der Quelltext kurz erklärt Muss ich den Quelltext groß erläutern? Das meiste erschließt sich bestimmt beim Durchlesen. Ein Formular schickt die Felder comment, name und Email an sich selber ab. Danach lege ich im PHP-Teil den Dateinamen in einer Variablen fest: $datei = "comment.txt";

      Eine if-Abfrage prüft, ob die Formularfelder nicht etwa leer gelassen wurden, denn nur dann soll der Kommentar in die Textdatei eingetragen werden. Aus Bequemlichkeit wandle ich danach die klobigen $_POST-Variablen wie $_POST["comment"] usw. in schlankere Formen um. Hier das Beispiel für den Kommentar. $comment = htmlspecialchars(stripslashes($_POST["comment"]));

      Nun öffne ich – und das ist die Besonderheit – unsere Textdatei im Anhänge-Modus. $fp = fopen($datei, "a+");

      Bei diesem Modus wird der Dateizeiger am Ende der Datei platziert. Im Klartext: Das Skript schreibt den neuen Gästebucheintrag einfach ganz unten in die Datei! Auch die nächsten Zeilen bergen kein Geheimnis, zudem habe ich sie noch gut kommentiert: Ein E-Mail-Link für die Textausgabe entsteht und das Datum wird ermittelt und formatiert. Schließlich soll dem Eintrag auch ein genaues Datum zugeordnet werden. // E-Mail-Link entsteht $Email = "$Email"; // Datum ermitteln und formatieren $datum = date("j.n.Y");

      282

      Hacking-Versuche unterbinden

      Hacking-Versuche unterbinden Erinnerst du dich noch an Kapitel 8? Dort habe ich dir gezeigt, wie man mit der Funktion htmlspecialchars() die HTML-Zeichen entschärft und mit stripslashes() eventuelle Maskier-Schrägstriche entfernt. Das habe ich nicht nur bei $comment, sondern auch für $name und $Email gemacht. $name = htmlspecialchars(stripslashes($_POST["name"])); $Email = htmlspecialchars(stripslashes($_POST["Email"]));

      Warum ist gerade die Funktion htmlspecialchars() so verdammt wichtig für das Skript? Sie verhindert, dass dir irgendein Scherzkeks HTML-Tags im Klartext in dein Skript schummelt. Sonst könnten fremde Links, fremder Quelltext und sogar gefährliche PHP- oder JavaScripte einfach so mir nichts dir nichts in dein Gästebuch eingetragen werden. Und das wäre fatal! Auf diese Weise werden diese Zeichen in ihre Entitäten umgewandelt (< wird z. B. zu <) und die Gefahr ist gebannt! Also: Gib den Hackern und Skript-Kids keine Chance!

      Die Funktionen nl2br() und readfile() Nach so vielen bekannten Funktionen und Anweisungen gibt es auch zwei Novitäten.

      Zeilenumbruch erhalten: nl2br() Die erste Besonderheit steckt in der Zeile: $comment = nl2br($comment);

      Hier kommt die neue Funktion nl2br() zum Einsatz. Lies diese Funktion als new line 2 (2 wie to) break. Diese Funktion sorgt dafür, dass nach Zeilenumbrüchen im Quelltext zusätzlich das Tag
      (bzw.
      je nach Alter der PHP-Version) eingefügt wird. Als Argument übergibst du einfach den umzuwandelnden String und hältst das neue Ergebnis in der gleichen Variablen fest. 283

      Kapitel

      12

      Das eigene Gästebuch Wozu ist das gut? Auf diese Weise wird jeder Zeilenumbruch auch auf deiner Gästebuchseite sichtbar! Denn ein normaler Break würde ansonsten nur im Quelltext erscheinen. Im Klartext: Wenn der Gästebuchschreiber auf [Enter] drückt, sieht man auch ein »Enter«.

      Jeder Druck auf [Enter] wird im Quelltext zusätzlich durch
      gekennzeichnet. Nicht wundern, PHP verwendet schon die XHTML-Syntax. Eigentlich wäre auch
      okay.

      Die weiteren Zeilen sind wieder bekannt und vertraut. Du setzt den Gästebucheintrag zusammen und formatierst ihn ein wenig. Dann hängst du ihn mit fputs() ans Ende der Datei und schließt den ganzen Laden (bzw. die Datei) zu.

      Datei auslesen mit readfile() Doch wie und wo werden die Daten letztendlich angezeigt? Schließlich wollen auch andere die Gästebucheinträge lesen können? Das gelingt mit der genial einfachen Funktion readfile(). Sie liest eine Datei aus uns stellt sie dar. Die entsprechende Zeile sieht so aus: readfile($datei);

      Ganz bewusst habe ich die Funktion unterhalb des if-Blocks notiert. Schließlich soll der Inhalt des Gästebuchs in jedem Fall angezeigt werden und nicht nur, wenn man selber einen Eintrag vornimmt.

      Schon besser: Gästebuch Version 2 Probiere das Gästebuch aus. Zufrieden? Ich bin es nicht, denn die neuesten Einträge werden zuunterst angezeigt. Es sollte eigentlich umgedreht sein! Offenbar war die Sache mit dem Anhänge-Modus wohl doch nicht so eine geniale Idee. 284

      Schon besser: Gästebuch Version 2

      Neueste Einträge zuoberst anzeigen Hast du eine Idee, wie du die neuesten Einträge stets nach oben bekommst? Mit dem vorhandenen Wissen könntest du es schaffen. Ändere einfach etwas im Modus beim Öffnen der Datei, füge ein paar Zeilen hinzu … und fertig.

      Schon besser: Jetzt stehen die neuesten Einträge zuoberst.

      Hat nicht geklappt? Hier mein Vorschlag. Ich zeige dir lediglich den PHPTeil. Alle veränderten bzw. ergänzten Passagen habe ich hervorgehoben. $Email"; // Datum ermitteln und formatieren $datum = date("j.n.Y"); // Meinung zusammensetzen

      285

      Kapitel

      12

      Das eigene Gästebuch $meinung="

      $name ($Email) schrieb am " . "$datum:
      $comment

      \n"; // Dateizeiger marschiert an den Anfang rewind($fp); // neue Meinung vor alte in Datei schreiben fputs($fp, "$meinung \n $old"); // Datei schließen fclose($fp); } readfile($datei); ?>

      Und, begeistert? Die Lösung ist im Prinzip wirklich simpel. Du sicherst den alten Inhalt aus comment.txt in der Variablen $old und platzierst den neuen Eintrag einfach vor dem alten. Da wir den Dateimodus auf r+ geändert haben, musst du den Dateizeiger natürlich vorher mit rewind($fp) zurücksetzen. Ich habe mir für dieses erweiterte Gästebuchprojekt einen neuen Ordner angelegt. Schließlich kannst du auch die alte, andersherum sortierte Datei comment.txt nicht weiter verwenden. Mein Beispiel findest du daher unter kapitel12/version2.

      So vermeidest du Doppeleinträge Schön, schön. Bisher macht das Gästebuch durchaus etwas her. Oder gibt es da noch einen Haken? Es gibt mehrere Haken. Beginnen wir bei der Sache mit den Doppeleinträgen. Da braucht bloß mal ein übereifriger Gästebuchschreiber auf den RELOAD-Button zu drücken: Zack, schon steht der Eintrag ein zweites Mal im Gästebuch.

      Nervt: Dieser unqualifizierte Eintrag steht gleich doppelt im Gästebuch.

      286

      So vermeidest du Doppeleinträge Aber auch dagegen ist ein Kraut gewachsen. Wage dich an die dritte Version des Gästebuchs. Falls du stecken bleibst: Mein Beispiel findest du unter kapitel12/version3.

      Die Funktion time() Schaue zuerst nach oben in den Formularteil. Füge ein neues Feld in dein Formular ein, und zwar ein verstecktes Formularfeld:

      Die Position spielt keine Rolle, da das Feld versteckt wird. Dafür sorgt die Angabe type="hidden". Hauptsache, du setzt das Feld innerhalb des Tagpaars
      ein. (Ich habe es unter dem Feld für die E-MailAdresse platziert.) Was passiert in diesem Geheimfeld? Der Trick steckt hinter diesem Attribut-Werte-Paar: value=""

      Hier wird praktisch ein Zeitstempel erzeugt und in die Datei geschrieben. Erinnerst du dich an das Cookie-Kapitel 9? Dort hattest du die Funktion time() schon kennengelernt. Sie macht nichts weiter, als die Zahl der Sekunden seit dem 1.1.1970, 0:00 Uhr zu ermitteln, also die Sekunden, die seit Beginn der Unix-Epoche vergangen sind. Da ich ein echo vorangestellt habe, wird bei jedem Aufruf des Formulars eine andere Zahl hinter das Attribut value geschrieben. Diese Zahl kann später bequem über $_POST["uw"] aufgefangen werden.

      Vorgehensweise planen Ahnst du schon, was ich vorhabe? Richtig! Diese Sekundenzahl spielt eine Schlüsselrolle bei unserem Reload-Killer. Jeder wirklich neue Gästebucheintrag erzeugt auch einen neuen Wert. Schließlich heißt es: Time goes – die Zeit läuft. Doch was passiert bei einem »Reload«? Da erscheint der gleiche Gästebucheintrag noch einmal. Er stammt quasi aus dem Browser-Cache, aus dem unsichtbaren Zwischenspeicher. Zwischengespeichert wurde dabei auch die Sekundenzahl, und zwar die alte! 287

      Kapitel

      12

      Das eigene Gästebuch

      >

      Zum Festhalten der Sekundenzahl bereitest du nun eine Textdatei vor namens unique.txt!

      >

      Lege sie in den gleichen Ordner. Das wird die Speicherdatei für unsere Sekundenzahl.

      >

      Denke nach dem Hochladen ggf. wieder an den chmod 666.

      Wir müssen nun bei jedem Gästebucheintrag lediglich den entsprechenden Sekundenstempel festhalten. Beim nächsten Eintrag muss die neue Zahl höher sein als die alte. Falls beide Werte jedoch gleich sind, handelt es sich um eine Doppelung aus dem Browsercache. Stelle fest, was Sache ist! Und zwar mit Hilfe der handgestrickten Funktion isDouble(). Du notierst sie direkt hinter dem einleitenden
      Die Funktion isDouble() Alles klar? Dann zeige ich dir nun diese großartige Funktion: function isDouble() { $gleichheit = false; if (isset($_POST["uw"])) { $datei = "unique.txt"; $fp = fopen($datei, "r+"); $aw = fgets($fp, 30); if ($aw == $_POST["uw"]) { $gleichheit = true; } rewind($fp); fputs($fp, $_POST["uw"]); fclose($fp); } return $gleichheit; }

      Beachte wieder, dass bei Funktionen die öffnende geschweifte Klammer auf einer eigenen Zeile stehen sollte – ganz im Gegensatz zu if-else-Kontrollstrukturen oder Schleifen. 288

      So vermeidest du Doppeleinträge

      Dir ist das Prinzip der Funktion schon entfallen? Dann schlage schnell im Kapitel 6 nach. Dort hatte ich dich mit der Wirkungsweise vertraut gemacht. Die Funktion führt im Beispiel einen Test durch und gibt je nach Sachstand den entsprechenden Wahrheitswert zurück. Ich habe deshalb eine Funktion erstellt, weil man den Code so bequemer wiederverwerten kann. Unterhalb der Funktion ergänzt du bitte noch folgende Zeile: $double = isDouble();

      Im Klartext: Du speicherst den Rückgabewert der Funktion in einer Variablen namens $double. Denn mit dieser Variablen wollen wir arbeiten. Bei der Funktion isDouble() kommt die sogenannte »Kamelschreibweise« zum Einsatz. Als »Höcker« gilt der große Buchstabe D. Diese gut lesbare Schreibweise mit einem oder mehreren Großbuchstaben ist bei Profis beliebt. Sie nutzen sie gern für Funktionsnamen und Variablen.

      Die Funktion im Überblick Nehmen wir die Funktion isDouble() auseinander! Was passiert da genau? Zuerst gehe ich davon aus, dass eine Ungleichheit zwischen der in der Datei unique.txt gespeicherten und der aus dem Formular stammenden Sekundenzahl besteht. Ich initialisiere die Variable $gleichheit mit dem Wert false. Wurde das Formular abgeschickt? Existiert die Variable $_POST["uw"]? Dann öffne ich die Datei unique.txt zum Schreiben und Lesen und lese den Inhalt aus. Der Inhalt wird in der Variablen $aw gesichert. Nun vergleiche ich den Wert aus $aw mit dem, was das Formular aktuell abgeschickt hat. Gibt es hier eine Gleichheit? Dann wird die Variable $gleichheit auf true geschaltet. Unterhalb des if-Bereichs wird der neue Wert in der unique.txt gespeichert und die Datei wird geschlossen. Die Funktion gibt nun den entsprechenden Wahrheitswert aus $gleichheit zurück. Entscheidend ist nun die schon gezeigte Zeile unter-

      halb der Funktion. Hier wird die Funktion schließlich aufgerufen: $double = isDouble();

      289

      Kapitel

      Das eigene Gästebuch

      12

      Die Variable $double beherbergt also je nach Sachstand den Wert false (keine Doppeleingabe) oder true (Doppeleingabe). Warum verwende ich innerhalb der Funktion eigentlich so ungeniert die Variablen $fp und $datei? Ist es nicht problematisch, da diese Variablen auch im zweiten Teil des Skripts vorkommen? Nicht im Geringsten! Erstens werden die Variablen jedes Mal neu initialisiert, also mit einem neuen Wert gefüttert. Schon von daher kann es keine Probleme geben. Zum anderen überleben die in der Funktion initialisierten Variablen sowieso nur innerhalb dieser Funktion!

      Bedingung erweitern Zurück zum Beispiel. Die Funktion hat ermittelt, ob es sich um eine Doppeleingabe handelt oder nicht. Der entsprechende Wahrheitswert liegt in der Variablen $double bereit. Und nun? Nun musst nun nichts weiter tun, als die existierende Bedingung if (!empty($_POST["comment"]) && !empty($_POST["name"]) && !empty($_POST["Email"])) {

      wie folgt zu erweitern: if (!empty($_POST["comment"]) && !empty($_POST["name"]) && !empty($_POST["Email"]) && !$double) {

      Im Klartext: Es darf keine Doppeleingabe vorliegen, sonst wird der Gästebucheintrag kaltblütig vom Skript storniert!

      Gästebuch sicherer machen Aber ist das Gästebuch in dieser Fassung wirklich schon sicher? Leider nein! Du solltest es so möglichst nicht im Web veröffentlichen.

      Die Gefahr durch Spammer Gästebücher sind inzwischen zu einem beliebten Objekt von Spammern geworden, also von den Zeitgenossen, die überall unaufgefordert ihre Werbung eintragen und zweifelhafte Links hinterlassen. Häufig erfolgt dieses Spamming sogar automatisch durch ein Skript. 290

      Schlussbemerkung Ein weiteres Problem stellt das Eingeben der E-Mail-Adresse dar. Auch E-Mail-Adressen werden längst automatisch von Programmen ausgelesen, von Betrügern gesammelt und zum Versand von Spam verwendet.

      Lösungen für diese Probleme Das erste Problem wird häufig durch ein sogenanntes CAPTCHA gelöst, durch einen Test, ob es sich wirklich um einen Menschen oder eine Maschine handelt. Dabei kommt oft ein verschleiertes Bildchen zum Einsatz. Der Eintragende muss eine Zeichenfolge auslesen und diese zur Sicherheit in ein Zusatzfeld eintragen. Der Haken: Das Erzeugen und Einbinden derartiger, sich ständig verändernder Bildchen ist kompliziert – für dieses PHP-Einstiegsbuch überfordert es uns bei weitem. (Aber auch eine Rechenaufgabe oder ein anderer Test sind denkbar.) Typisches CAPTCHA bei professionellen Gästebüchern. Bild: Wikipedia.de.

      Und inzwischen gibt es auch schon die ersten Programme, mit denen sich selbst ausgefuchste Bild-CAPTCHAs knacken lassen. Ich schlage eine sehr simple, aber wirkungsvolle Methode vor: Erlaube nur deinen Freunden und Bekannten, sich im Gästebuch einzutragen. Gib ihnen vorab ein spezielles Passwort. Und damit du deine Freunde erkennst, schützt du das Gästebuch dann einfach mit eben diesem Passwort. Außerdem solltest du das Feld für die E-Mail-Adresse weglassen oder durch ein Feld für die Homepage ersetzen – gerne für die Lieblings-Homepage. (Es kann ja sein, dass der Eintragende noch keine eigene Homepage hat.) Für beide Ideen halte ich im Übungsteil die passenden Aufgaben bereit!

      Schlussbemerkung Du hast dein eigenes, einfaches Gästebuch erstellt und es funktioniert. Glückwunsch! Dabei konntest du viele der Techniken aus den vorigen Kapiteln festigen. Als Höhepunkt des Beispiels kam eine Funktion zum Einsatz. Du weißt aber auch, dass du das Gästebuch für den Einsatz im Web noch etwas sicherer machen musst! Und damit fangen wir gleich an.

      291

      Kapitel

      12

      Das eigene Gästebuch

      Zusammenfassung 0 Du kennst die Funktion nl2br(). Diese Funktion sorgt dafür, dass nach Zeilenumbrüchen im Quelltext zusätzlich das Tag
      eingefügt wird. 0 Du kennst die Funktion readfile(), mir der du den Inhalt einer Datei auslesen kannst. 0 Du weißt, wie du mit der selbsterstellten Funktion isDouble() Doppeleinträge verhindern kannst. Sichere einen Zeitstempel in einer Extradatei und prüfe bei jedem Eintrag, ob der neue und alte Zeitstempel Unterschiede aufweisen.

      Ein paar Fragen … 1. Wofür steht die Funktion nl2br(), was bedeutet die Zeichenfolge nl2br? 2. Wozu dient die Funktion time()? 3. Welchen Buchstaben setzt du in fopen() ein, wenn du eine Datei im Anhänge-Modus zum Lesen und Schreiben öffnen möchtest? 4. Sind die in einer Funktion definierten Variablen auch außerhalb der Funktion sichtbar?

      … und ein paar Aufgaben 1. Zuerst die leichteste Aufgabe zum Gästebuch. Ersetze das Feld zur Abfrage der E-Mail-Adresse durch eines zum Erfassen der Homepage. Der Name des Feldes soll www lauten. Passe auch den Link bei der Anzeige an. Es darf kein mailto-Link mehr sein, sondern ein normaler. 2. Füge ein zusätzliches Feld zur Abfrage des Kennwortes ein. Das Kennwort soll t6rzXi2P heißen. Frage das Kennwort ebenfalls mit ab. 3. Sorge dafür, dass der Inhalt der Felder – vom Passwortfeld abgesehen – nach dem Absenden nicht verloren geht! Tipp: Erinnere dich an das Feedbackformular in Kapitel 8 – dort haben wir das schon gemacht! (Es genügt mir, wenn die Inhalte in den Feldern stehen bleiben. Du musst die Werte nicht unbedingt nach dem Abschicken löschen.) 292

      … und ein paar Aufgaben 4. Du hast vergessen, die Datei comment.txt anzulegen? Dann produziert die Funktion readfile() eine Fehlermeldung. Versuche, diese Fehlermeldung zu unterdrücken. Tipp: Du benötigst nur ein kleines Zeichen. 5. Baue die Reload-Sperre aus der Funktion isDouble() in die Meinungsumfrage aus dem vorigen Kapitel ein. Einfach zur zusätzlichen Sicherheit! 6. Prüfe, ob du die Reload-Sperre korrekt in die Umfrage eingebaut hast. Deaktiviere Cookies im Browser. Stimme ab. Gehe zurück mit dem BACKButton des Browsers. Stimme noch einmal ab. Diese zweite Stimme darf nun nicht mehr gezählt werden!

      293

      13 Ein Adressbuch für dein Team Keine Angst vor Datenbanken! In diesem Kapitel wagen wir uns von der praktischen Seite an das Thema heran. Wie wäre es mit einem Adressbuch für dein Team? Dabei ist es ganz egal, ob es sich bei diesem »Team« um deine Klassenkameraden, die Vereinsmitglieder oder die Kunden eines Online-Shops handelt. Das Schöne an der Sache: Dank unserer fabelhaften XAMPP-Installation bist du schon im Besitz des Datenbankprogramms MySQL. Auch die für uns unentbehrliche grafische Oberfläche phpMyAdmin wurde bei dir automatisch installiert. Auf diese Weise ist das Anlegen und Bearbeiten von Datenbanken kinderleicht. Bei dir ist noch nichts Derartiges auf deiner Festplatte installiert? Dann studiere unbedingt noch einmal das Kapitel 2 zur Installation deines lokalen Webservers! Du lernst in diesem Kapitel: $ wie du eine Datenbanktabelle planst und einrichtest $ wie du mit dem Tool phpMyAdmin arbeitest $ wie du mit SQL und MySQL arbeitest $ wie du Daten eingibst und ausliest $ wie du SQL-Befehle in eine PHP-Datei einfügst

      295

      Kapitel

      13

      Ein Adressbuch für dein Team

      Planung ist die halbe Miete Was ist eine Datenbank? Eine Bank für Daten! Also eine Art Datenspeicher! Eine Datenbank besteht aus Datenbanktabellen. Herrjeh, Tabellen? Gleich mehrere auf einmal? Nicht unbedingt! Im einfachsten Fall besteht die Datenbank nur aus einer einzigen Datenbanktabelle. Und da das Kapitel einfach wird, fangen wir mit dieser einen Tabelle an. Und zwar mit unserer Adressliste. Doch bevor es losgeht, planst du zuerst die Struktur!

      Die Struktur der Datenbank planen Planen? Das klingt ja furchtbar. Es stimmt – Datenbanken sind ein Graus für alle diejenigen, die das »geordnete Chaos« lieben. Trotzdem gilt: Für Datenbankdesign brauchst du eine klare Struktur. Da kommst du nicht drum herum. Vor dem Aufbau einer Datenbanktabelle musst du dir eine DatenbankStruktur ausdenken. Überlege dir, welche Einträge erforderlich sind. Definiere also die sogenannten Feldnamen. Das nachträgliche Ändern einer Datenbankstruktur ist nur unter Schwierigkeiten möglich – vor allem, wenn du schon viele Daten eingetragen hast! Datenverlust könnte die Folge sein. Hier zeige ich dir, was bei meinen Struktur-Überlegungen zum Adressbuch herausgekommen ist. Dazu habe ich mir die künftige Datenbanktabelle schon einmal als Tabelle »skizziert«: Vorname Name Hans Meier

      Str Waldweg 7

      PLZ 12345

      Ort Neustadt

      Tel 234567

      EMail WWW Notizen [email protected] www.lexi.de

      Feldnamen und Datensätze Für unsere Adressdatei habe ich mir also folgende sinnvolle Feldnamen ausgedacht: Vorname, Name, Str, PLZ, Ort, Tel, EMail, WWW und Notizen. Die Feldnamen sind hier selbsterklärend. Okay! Da sind wir also bei den Fachbegriffen angelangt. Das ist aber gar nicht schlimm: Die erste Zeile einer Tabelle enthält die Beschriftung. Man spricht von den sogenannten Feldnamen. In den übrigen Zeilen befinden sich die Einträge, die Datensätze. Jeder Datensatz besteht aus den einzelnen Datenbankfeldern. 296

      Planung ist die halbe Miete

      Du planst eine Datenbanktabelle? Denke dir kurze, präzise und selbsterklärende Feldnamen aus. Verzichte auf Umlaute, Leer- und Sonderzeichen. Beachte, dass zwischen Groß- und Kleinschreibung unterschieden wird. Außerdem ist der Bindestrich nicht erlaubt. Das E-Mail-Feld darf also keinesfalls E-Mail heißen, sondern nur EMail, email, eMail usw. Eine Datenbanktabelle kann übrigens hunderte oder sogar tausende von Datensätzen enthalten. Eigentlich ist die Zahl fast unbegrenzt.

      Die Sache mit dem Schlüsselfeld Halt, unsere Planung ist noch nicht ganz vollständig! Jede gute Datenbanktabelle sollte ein sogenanntes Schlüsselfeld erhalten. Das ist eine Kennung, die jeden Datensatz eindeutig identifiziert. Dazu habe ich meine Skizze um eine zusätzliche Spalte am Anfang erweitert. Die Spalte heißt id. id Vorname Name Str PLZ Ort Tel EMail WWW Notizen Meier Waldweg 7 12345 Neustadt 234567 [email protected] www.lexi.de 1 Hans mag 2 Martina Weber Waldweg 2 12345 Neustadt 234568 [email protected] Kaugummis

      Das Schlüsselfeld heißt also id wie identifier (Identifizierer, eindeutige Kennung). Solch ein Schlüsselfeld ist deshalb wichtig, damit man jeden Datensatz eindeutig identifizieren kann. Der Name reicht im Beispiel zum Identifizieren kaum aus. Denn es kann durchaus sein, dass es drei Meiers und fünf Schulzes in deinem Team gibt. Als Zähler verwenden wir eine Zahl. Jeder Datensatz bekommt einen um eins erhöhten Wert. Im Beispiel habe ich einen weiteren Datensatz in die Tabelle eingetragen. Damit du dich nicht aus Versehen verzählst, solltest du die Zählerei deinem Datenbankprogramm überlassen. MySQL kennt einen Befehl namens auto_increment. Das steht für »automatisch zählen«. Wir werden beim Einrichten der Datenbanktabelle also darauf achten, dass wir solch eine »Zählautomatik« in unser Schlüsselfeld einbauen. Wichtig zu wissen: Solch ein Schlüssefeld wird auch als Primärschlüssel bezeichnet. Dafür kannst du dir den Befehl PRIMARY KEY merken. Diese eindeutige Kennung alias Primärschlüssel ist auch dann wichtig, wenn man mehrere Datenbanktabellen miteinander in Beziehung setzen möchte. Doch halt – so weit sind wir an dieser Stelle noch nicht. Dafür musst du dich noch ein paar Kapitel gedulden!

      297

      Kapitel

      13

      Ein Adressbuch für dein Team

      Was benötigen wir? Halten wir fest: Wir benötigen eine Datenbank. Ich schlage folgenden Namen vor: 0 team Außerdem brauchen wir die eben geplante Datenbanktabelle, also den eigentlichen Datenspeicher. Diese Tabelle nennen wir im Beispiel – Nomen est Omen – einfach mal: 0 adressen In dieser Datenbanktabelle legen wir zuerst die Feldnamen fest und tragen dann die Daten ein. Doch schön der Reihe nach …

      Geniales Tool: phpMyAdmin Wir nutzen das Datenbankprogramm MySQL. Das ist klar. Der Haken bei der Geschichte: MySQL ist alles andere als komfortabel. Für die Bedienung von MySQL musst du auf Kommandozeilen-Ebene hinabsteigen. Im Klartext: Du musst eine DOS-Box öffnen und das Programm von dort aus mit Befehlen füttern. Hast du dazu Lust? Nein? Kein Problem! Es gibt ein Programm, mit dem man MySQL auf ganz komfortable Weise bedienen kann! Sowohl mit Befehlen also auch grafisch mit Komfort. Dieses Programm heißt phpMyAdmin! Es ist also eine Art grafische Oberfläche für MySQL.

      phpMyAdmin aufrufen Du hast XAMPP und deinen lokalen Webserver erfolgreich installiert? Dann ist phpMyAdmin fix und fertig eingerichtet. Das Tool wartet auf seinen großen Auftritt. Der einzige Haken: phpMyAdmin sieht in jeder Version und bei jedem Webhoster ein wenig anders aus. Immer wieder ändern die Macher das Layout. Wundere dich also nicht, wenn meine Abbildungen etwas von der Ansicht abweichen, die du am PC siehst. Das Prinzip bleibt gleich!

      > 298

      Tippe http://localhost/phpmyadmin und drücke [Enter] – das Programm phpMyAdmin erscheint. Stellen wir es erst etwas ein. Schaue in den rechten Bereich und wähle in den Listenfeldern das Oberflächendesign ORIGINAL und eine Schriftgröße von 90%.

      Geniales Tool: phpMyAdmin

      Die Datenbank anlegen Als erstes werden wir nun die Datenbank anlegen. Ich rede über die Datenbank, noch nicht über die Datenbanktabelle! Die Datenbank soll team heißen. Auf los geht’s los!

      >

      Klicke in das Feld NEUE DATENBANK ANLEGEN. Tippe den Namen der Datenbank, im Beispiel team.

      >

      Wähle im Feld namens Kollation die Einstellung utf8_general_ci. Im Feld darunter, bei Zeichensatz / Kollation der MySQL-Verbindung sollte ebenfalls utf8_general_ci stehen. Das ist meist die Voreinstellung.

      >

      Drücke auf die Schaltfläche ANLEGEN.

      Auf Knopfdruck legst du eine neue Datenbank an.

      >

      Zack! Die Datenbank ist fertig! Das erkennst du an einer Bestätigungsseite. Allerdings meldet dir diese Seite auch, dass noch keine Tabellen gefunden wurden. Wie denn auch. Es gibt noch keine. Das Anlegen der Tabellen folgt schließlich erst im nächsten Schritt!

      Zum Verständnis: Die Datenbank selbst ist nur die übergeordnete Hülle. Die eigentlichen Daten liegen jedoch in den Datenbanktabellen. Im Beispiel benötigen wir eine einzige Tabelle namens adressen. Die meisten »günstigen« Anbieter mit PHP/MySQL-Unterstützung erlauben dir leider nicht, eigene Datenbanken anzulegen. Du darfst in der Regel oft nur eine einzige MySQL-Datenbank nutzen, deren Name noch dazu fest vorgegeben ist. Das ist aber nicht weiter schlimm. Schließlich kannst du in dieser Datenbank immerhin Datenbanktabellen nach deinem Geschmack einrichten. Und ob die »übergeordnete Hülle« nun team oder v945rz3 heißt, spielt für die eigentlichen Daten keine Rolle. 299

      Kapitel

      13

      Ein Adressbuch für dein Team

      Etwas SQL zum Anlegen der Datenbanktabelle Genug geredet. Nun geht es um das Anlegen der Datenbanktabelle. Do you speak SQL? In diesem Kapitel bekommst du einen ersten Einblick in eine »neue Fremdsprache«. Du lernst die Grundzüge der Sprache SQL kennen. SQL ist die Abkürzung für Structured Query Language. Das heißt so viel wie »strukturierte Abfragesprache«. Dahinter verbirgt sich eine Sprache zum Abfragen, aber auch zum Einrichten von Datenbanken und Datenbanktabellen. Das Schöne daran: SQL ist international, sie wird »weltweit« gesprochen. Du kannst damit praktisch jede Datenbank abfragen, egal ob sie nun MySQL, Access oder Oracle heißt. Es handelt sich also um eine Art »Datenbank-Esperanto«, allerdings mit »englischen Akzent«. Tatsache: Die Sprache SQL ähnelt dem gesprochenen Englisch! Sie lehnt sich an die Kleinkind-Sprache mit ganz einfachen Sätzen an. Solch ein Satz könnte (auf Deutsch) lauten »ERZEUGE TABELLE adressen«. Auf SQLEnglisch heißt das dann »CREATE TABLE adressen«. Merke: SQL-Befehle schreibt man nur deshalb groß, um sie besser unterscheiden zu können. Du könntest sie ebenso gut auch klein schreiben, da Groß- und Kleinschreibung nicht unterschieden werden. Im Buch bleibe ich aber bei der Großschreibung – die hat sich durchgesetzt.

      Syntax zum Anlegen der Tabelle Nutzen wir SQL doch gleich zum Anlegen einer neuen Datenbanktabelle. Schließlich wartet das Feld SQL-BEFEHL(E) IN DATENBANK TEAM AUSFÜHREN in phpMyAdmin regelrecht darauf, dass hier etwas passiert. Die Syntax zum Einrichten einer Tabelle lautet wie folgt: CREATE TABLE Tabellenname () DEFAULT CHARACTER SET utf8;

      Hinter unserem »Tabellenerzeugungssatz« folgt also noch ein Paar runder Klammern. In den runden Klammern gibst du nacheinander die Felder und die jeweiligen Datentypen an. Jede Felddefinition bekommt eine eigene Zeile – damit es übersichtlicher wird. Du trennst solch eine »Definitionszeile« jeweils durch ein Komma von der nächsten! 300

      Nach dem Klammernpaar legst du UTF-8 als Standard-Zeichensatz fest.

      Etwas SQL zum Anlegen der Datenbanktabelle

      Datenbankfelder definieren Zur Erinnerung: Für unsere Adressdatei habe ich mir folgende Feldnamen ausgedacht: id, Vorname, Name, Str, PLZ, Ort, Tel, EMail, WWW und Notizen. Doch wie sehen diese Felddefinitionen aus? Geduld! Zuerst liste ich dir die entsprechenden Befehle schon einmal vorab auf: Feldname id Vorname Name Str PLZ Ort Tel EMail WWW Notizen

      Datentyp (Felddefinition) INT NOT NULL AUTO_INCREMENT PRIMARY KEY VARCHAR(20) VARCHAR(20) VARCHAR(20) CHAR(5) VARCHAR(30) VARCHAR(25) VARCHAR(30) VARCHAR(30) TEXT

      Schlüsselfeld anlegen (Primärschlüssel) Fangen wir mit der ersten und wohl schwierigsten Zeile an. Es geht um die Befehle zum Anlegen des Primärschlüssels: INT NOT NULL AUTO_INCREMENT PRIMARY KEY

      Was bedeutet INT? Ganz einfach: Das Feld soll eine Zahl von Datentyp Integer (INT) sein! Schließlich wird hier automatisch gezählt! Der Datentyp Integer erlaubt Werte, die bis in den »Milliardenbereich« gehen. Konkret sind das Werte zwischen -2.147.483.648 und 2.147.483.647. Das genügt, findest du nicht auch? Wenn du dich jedoch auf weniger Adressen beschränken möchtest, kannst du den Datentyp SMALLINT UNSIGNED verwenden. Das erlaubt immer noch bis zu 65.535 Datensätze! (Die wichtigsten Datentypen bespreche ich gleich.) Mit dem Schlüsselwort NOT NULL klammere ich den Wert 0 aus. AUTO_INCREMENT bedeutet wiederum, dass das Hochzählen ganz automatisch erfolgt. Der Wert wird bei jedem neuen Datensatz automatisch inkrementiert (hochgezählt). Besonders wichtig ist der Befehl PRIMARY KEY. Damit mache ich dieses Feld zum Schlüsselfeld, zum Primärschlüssel. Es ist der eindeutige Bezeichner. Jedes Feld bekommt dadurch also einen abweichenden Wert, eine eindeutige id! 301

      Kapitel

      13

      Ein Adressbuch für dein Team

      VARCHAR, CHAR und TEXT In fast allen übrigen Feldern verwende ich den Datentyp VARCHAR(). Das ist ein Datentyp, der das Speichern von Zeichenketten mit variabler Länge erlaubt. Wie lang diese Zeichenketten sein dürfen, gibst du innerhalb der runden Klammern an. Es ist eine maximale Länge von 255 Zeichen möglich! Wenn das Feld nur 20 Zeichen umfassen soll, schreibst du: VARCHAR(20). Wenn du dagegen 255 Zeichen ausschöpfen möchtest, schreibst du VARCHAR(255). Du darfst die runden Klammern bei diesem Datentyp nicht weglassen. Für die Postleitzahl benötige ich dagegen (bei uns in Deutschland) immer genau 5 Zeichen. Die Länge variiert nicht. Da genügt der Datentyp CHAR für eine feste Länge. Das spart pro Datensatz ein Byte: CHAR(5). Warum speichere ich Zahlen wie die PLZ oder Telefonnummer mit einem Text-Datentyp, also mit VARCHAR bzw. CHAR? Warum nicht! Schließlich benötige ich diese Zahlen nicht für irgendwelche Berechnungen. Außerdem kann ich auf diese Weise auch Telefonnummern mit großer Länge sichern, ohne mich darum kümmern zu müssen, welchem Zahlen-Datentyp diese Länge entspricht. Fast noch wichtiger ist folgender Fakt: Nur so lassen sich Telefonnummern mit Binde- oder Querstrichen sichern; Zeichen, die man bei aller Liebe nicht dem Zahlenformat zuordnen kann. Das Feld Notizen bekommt dagegen den Datentyp TEXT zugewiesen. Solch ein Feld hat Platz für eine ganze Kurzgeschichte. Du kannst weit ausschweifende Passagen mit bis zu 65.535 Zeichen Länge eintragen!

      Die Tabelle anlegen So, und nun bauen wir mit diesem Wissen die Tabelle zusammen. Zuerst notierst du CREATE TABLE adressen () wie vorhin besprochen. Außerdem bereitest du zwischen den runden Klammern schon ein paar Leerzeilen vor. In den runden Klammern werden wir nun Zeile für Zeile die Definition des entsprechenden Datenfelds festlegen. Bei dieser Gelegenheit legen wir den Feldnamen und den entsprechenden Datentyp fest.

      302

      Zuerst notierst du den Namen des künftigen Feldes. Dann lässt du ein Leerzeichen frei. Danach folgt die schon besprochene Definition des Datentyps. Bei Bedarf (z. B. beim ersten Feld für den Primärschlüssel) kommen weitere Befehle und Anweisungen hinzu. Am Schluss der Zeile setzt du ein Komma. Nur bei der letzten Zeile verzichtest du auf das Komma!

      Etwas SQL zum Anlegen der Datenbanktabelle Und so sieht die Befehlsfolge im Beispiel aus: CREATE TABLE adressen ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, Vorname VARCHAR(20), Name VARCHAR(20), Str VARCHAR(20), PLZ CHAR(5), Ort VARCHAR(30), Tel VARCHAR(25), EMail VARCHAR(30), WWW VARCHAR(30), Notizen TEXT ) DEFAULT CHARACTER SET utf8;

      Tippe diese Zeilen in das Eingabefeld für die SQL-Befehle. Dieses Feld erreichst du durch Klick auf die Registerzunge SQL. Dein Dienstleister bietet MySQL-Unterstützung? Du hast dort über das Konfigurationsmenü schon eine Datenbank eingerichtet bzw. findest eine vorinstallierte Datenbank vor? Dann kannst du die nächsten Übungen auch direkt auf dem Server durchführen! Lies die Hinweise am Anfang von Kapitel 17! Lies den Abschnitt MySQL und dein Dienstleister. Egal ob online oder offline: Hast du das Feld gefunden? Beachte, dass die letzte Zeile vor der schließenden runden Klammer kein Komma mehr bekommen darf. Lasse also diesen »Pausenhaken« hinter TEXT auf jeden Fall weg. Und setze hinter DEFAULT CHARACTER SET utf8 ein Semikolon. Alles klar? Klicke auf die Schaltfläche OK. Tippe die Befehle in das entsprechende Eingabefeld.

      303

      Kapitel

      Ein Adressbuch für dein Team

      13

      Wenn es geklappt hat, erscheint nun dieses oder ein ähnliches Bild. Hier eine Ansicht aus einer älteren Version von phpMyAdmin:

      Hoppla, du hast einen Fehler gemacht? Prüfe noch einmal ganz genau, ob du dich nicht irgendwo verschrieben hast! Schon ein vergessenes Komma oder ein falsch gesetztes Leerzeichen führt dazu, dass der SQLCode fehlerhaft ist. Zum Glück zeigt dir phpMyAdmin stets die fehlerhafte Zeile und du bekommst eine zweite Chance. Korrigiere deinen Code und probiere es erneut! Wenn es partout nicht klappen will, schaue einfach auf die CD! Im Ordner mit den Beispieldateien findest du die Datei SQL_adressen.txt. Dort habe ich die SQL-Befehle zum Anlegen dieser Tabelle für dich abgelegt. Du brauchst einfach nur diese Textdatei aufzurufen und die Befehlsfolge in phpMyAdmin hineinzukopieren! Oder du schaust zum Register IMPORTIEREN und klickst auf die Schaltfläche DURCHSUCHEN. Suche die Textdatei mit den SQL-Befehlen aus dem Dateisystem aus. Nach Klick auf OK werden die Befehle ausgeführt.

      Die Datentypen im Überblick Reden wir nun kurz über die Datentypen. (Wenn du schnell an deiner Tabelle weitermachen möchtest, kannst du diesen Abschnitt auch überfliegen. Lies ihn später. Aber lies ihn!)

      304

      PHP ist einfach, erinnerst du dich? Du brauchst dich um den Datentyp nicht zu kümmern. Das Programm erkennt automatisch, ob es sich um eine Ganzzahl, eine Kommazahl oder um Text handelt. Es gibt nur wenige Da-

      Die Datentypen im Überblick tentypen. Und auch die können dir egal sein, denn die Zuweisung erfolgt automatisch. Ganz anders ist das jedoch in einer Datenbank! Hier spielen die Datentypen eine enorm wichtige Rolle. Bei Datenbanken mit mehreren tausend Einträgen geht es schließlich um die optimale Ausnutzung des Speicherplatzes. Bisher kennst du lediglich INT, VARCHAR, CHAR und TEXT, aber es gibt weit mehr Datentypen. Du erwartest unzählige Einträge in deiner Datenbanktabelle? Dann wähle möglichst den Datentyp mit dem geringsten Speicherbedarf. Bei zehn Adressen ist das Thema Speicherplatz sicher egal, bei zehntausend spielt es schon eine entscheidende Rolle, ob das Feld ein paar Bytes mehr oder weniger benötigt!

      Die wichtigsten Datentypen Keine Angst, hier folgen keine seitenlangen Tabellen. Ich zeige dir nur die wichtigsten Datentypen. Es sind die Datentypen, die am häufigsten verwendet werden. Aus diesem Grund habe ich die Datentypen auch ausführlich beschrieben. Datentyp

      Beschreibung

      VARCHAR(M) Zeichenkette mit variabler

      Länge

      CHAR(M)

      Zeichenkette mit fester Länge

      TEXT

      Zeichenkette mit maximal 65.535 Zeichen (64 KB)

      INT oder auch INT(M)

      Ganzzahl zwischen -2,147 Mrd und 2,147 Mrd, (M) bezieht sich auf die Anzeige breite und ist optional.

      Besonderheit

      Speicherbedarf

      1 bis 255 Zeichen Länge möglich, die maximal erlaubte Länge wird durch M gekennzeichnet, (M) darf nicht weggelassen werden 1 bis 255 Zeichen Länge möglich, die maximal erlaubte Länge wird durch M gekennzeichnet, (M) darf nicht weggelassen werden Groß- und Kleinschreibung werden nicht berücksichtigt (wichtig für Sortierung und Vergleich) Der Zusatz UNSIGNED (ohne Vorzeichen) beschränkt auf den positiven Wertebereich. INT UNSIGNED beherbergt Zahlen zwischen 0 und 4,3 Mrd.

      Länge des Wertes plus 1 Byte

      M Bytes

      Länge des Wertes plus 2 Bytes

      4 Bytes (32 Bits)

      305

      Kapitel

      13

      Ein Adressbuch für dein Team Datentyp

      Beschreibung

      SMALLINT oder auch SMALLINT(M)

      Ganzzahl zwischen -32.768 und 32.767, (M), die Anzeigebreite, ist optional

      TINYINT oder auch TINYINT(M)

      FLOAT

      DOUBLE

      DATE

      DATETIME

      TIMESTAMP bzw. TIMESTAMP(M)

      306

      Besonderheit

      bei zusätzlicher Verwendung des Attributs UNSIGNED ist ein Wertebereich von 0 bis 65.535 möglich sehr kleine Ganzzahl bei zusätzlicher Verwenzwischen –128 und dung des Attributs 127, (M) ist optional UNSIGNED ist ein Wertebereich von 0 bis 255 möglich Fließkommazahl (Kom- In anderen Worten: eine mazahl) mit einem Kommazahl mit einer Wertebereich von 0 und recht hohen Genauigkeit von +/-1,175494351E- hinter dem Komma (Be38 bis +/achte, dass du beim 3,402823466E+38 Eintragen in die Datenbank statt des Kommas einen Dezimalpunkt setzen musst!) Fließkommazahl (Kom- Eine Kommazahl mit einer mazahl) mit einem enormen Genauigkeit Wertebereich von 0 und hinter dem Komma von +/(Double Precision) 2.2250738585072014E -308 bis +/1.7976931348623157E +308 Feld zum Speichern des Mit Überprüfung, ob Datums im Format weniger als 32 Tage und YYYY-MM-DD (‘200413 Monate verwendet 12-31’) wurden, Wertebereich zwischen 01.01.1000 und 31.12.9999 Feld zum Speichern von Erfasst auch die Zeit, Datum und Zeit im Wertebereich zwischen Format YYYY-MM-DD 01.01.1000 und hh:mm:ss (‘2004-12-31 31.12.9999 23:58:58’) Aktueller Zeitstempel Kann durch M gesteuert im Format YYYwerden, M kann z. B. die YMMDDhhmmss, reicht Werte 14, 12, 8 oder 6 von 19700101000000 annehmen, bei bis zum Jahr 2037 TIMESTAMP(12) ist das Datum nur noch zweistellig YYMMDDhhmmss, bei TIMESTAMP 8 ist das Datum zwar vierstellig, aber die Uhrzeit entfällt usw.

      Speicherbedarf 2 Bytes (16 Bits)

      1 Byte

      4 Bytes (32 Bits)

      8 Bytes (64 Bits)

      3 Bytes (24 Bits)

      8 Bytes (64 Bits)

      4 Bytes (32 Bits)

      Trage ein paar Adressen ein!

      Trage ein paar Adressen ein! Das Grundgerüst der Tabelle steht? Wunderbar! Trage einfach ein paar Adressen in deine Datenbanktabelle ein. Auch hierbei hilft dir der phpMyAdmin auf ganz hervorragende Weise.

      Datensatz eintragen

      >

      Klicke auf einen Link bzw. eine Registerzunge namens EINFÜGEN. Nun öffnet sich die Ansicht zur Eingabe deiner Daten. Das sieht aus wie eine Datenbankmaske.

      >

      Das Feld id lässt du frei. Dahinter steckt schließlich der Primärschlüssel, der automatisch ausgefüllt wird. Trage nun Schritt für Schritt die anderen Daten in die entsprechenden Felder ein.

      Trage die Daten in die entsprechenden Felder ein!

      Die Auswahlfelder beim Eintrag FUNKTION sind für unsere Zwecke nicht wichtig. Doch was bedeutet das Häkchen bei NULL? Wenn du ein Feld frei lässt, wird automatisch der Wert 0 eingetragen. Um das zu unterbinden, hättest du in der Definition der Feldnamen zusätzlich das Schlüsselwort NOT NULL eintragen müssen, z. B. Tel VARCHAR(25) NOT NULL! Das haben wir aber nicht gemacht, da die 0 überhaupt nicht stört und gleichbedeutend ist mit »Nichts«. (Die Datenbank gibt an dieser Stelle später keine 0, sondern einen Leerstring aus.)

      Nach Klick auf EINFÜGEN kannst du bis zu zwei Datensätze untereinander eingeben.

      307

      Kapitel

      13

      Ein Adressbuch für dein Team

      >

      Du möchtest einen dritten Datensatz eintragen? Schaue zum Ende der Eingabeseite. Wähle eine Option, die je nach Version von phpMyAdmin Neuen Datensatz eintragen oder (und dann) anschließend einen weiteren Datensatz einfügen heißt und wähle die Schaltfläche OK.

      Du kannst dir auch die schon eingegebenen Datensätze anzeigen lassen! Klicke dafür auf den Link Anzeigen. Du möchtest nun von dieser Ansicht aus Daten eingeben? Du benötigst also eine neue Zeile? Klicke dazu je nach phpMyAdmin-Version auf Einfügen bzw. Neue Zeile einfügen.

      Geht auch: Daten per SQL-Befehl INSERT eingeben Lerne wieder etwas SQL! Denn natürlich kannst du auch per SQL deine Daten in die Tabelle einfügen. Die entsprechende Syntax ist ausnahmsweise relativ kompliziert, aber du solltest sie trotzdem lernen. Du benötigst sie für später! Notiere zuerst das Schlüsselwort 0 INSERT INTO wie EINFÜGEN IN. Gib danach den Namen der Tabelle und ein paar runde Klammern an: 0 INSERT INTO adressen () In den runden Klammern notierst du alle Feldnamen der Datenbanktabelle, und zwar in der von dir gewünschten Reihenfolge. (Du kannst dabei eine ganz beliebige Reihenfolge wählen.) Trenne die Feldnamen lediglich durch ein Komma voneinander. 0 (id, Vorname, Name, Str, PLZ, Ort, Tel, EMail, WWW, Notizen)

      Danach schreibst du nach einem Leerzeichen (oder in einer neuen Zeile) das Schlüsselwort 0 VALUES ()

      308

      und vergisst auch hier die runden Klammern nicht. Du gibst nun die einzufügenden Werte an, und zwar genau in der gleichen Reihenfolge wie oben! Ganz wichtig: Setze jeden Wert in ein Paar einfache Gänsefüßchen! Auch das Schlüsselfeld bekommt ein paar Gänsefüßchen, diese lässt du jedoch leer.

      Trage ein paar Adressen ein! ('', 'Peter', 'Geppert', 'Hafenstr 3', '76543', 'Küstenstadt', '', '[email protected]', '', 'schwimmt gerne')

      Wenn du für ein Feld keine Daten vorgesehen hast, setzt du ein paar leerer Gänsefüßchen! Beachte auf jeden Fall die Reihenfolge innerhalb der runden Klammern. Du darfst auf keinen Fall einen Wert weglassen! Der ganze Befehl sieht nun so aus. Notiere ihn in das Feld zur EINGABE DER SQL-BEFEHLE: INSERT INTO adressen (id, Vorname, Name, Str, PLZ, Ort, Tel, EMail, WWW, Notizen) VALUES ('', 'Peter', 'Geppert', 'Hafenstr 3', '76543', 'Küstenstadt', '', '[email protected]', '', 'schwimmt gerne')

      Übung macht den Meister! Trage ruhig auch den zweiten Datensatz ein, im Beispiel handelt es sich um eine gewisse Monika Hasemann: INSERT INTO adressen (id, Vorname, Name, Str, PLZ, Ort, Tel, EMail, WWW, Notizen) VALUES ('', 'Monika', 'Hasemann', 'Am Feldrand', '01234', 'Kuhdorf', '0170-8739874', '[email protected]', '', '')

      Und, hat das Eintragen der Daten funktioniert? Prüfe es! Klicke auf den Link Anzeigen, um alle Datensätze einzublenden! Hinweis: Das erste runde Klammernpaar kannst du auch weglassen – immer dann, wenn du beim Eintragen der Daten alle Felder berücksichtigst und dabei die vorgegebene Reihenfolge der Felder einhältst. (Das werden wir aber erst im Gästebuch von Kapitel 15 ausprobieren!) Du erntest ständig Fehlermeldungen? Du findest deinen Fehler nicht? Kein Problem, ich habe dir diese beiden SQL-Befehle auf die CD zum Buch gelegt. Rufe einfach die Datei SQL_Datensaetze.txt auf und übernimm die dort enthaltenen SQL-Befehle. (Da ich dort zwei SQLAnweisungen hintereinander notiert habe, musste ich sie durch ein Semikolon trennen!)

      Wo legt MySQL die Daten ab? Hast du dich eigentlich schon einmal gefragt, wo MySQL die ganzen Daten sichert? Wo landet deine Datenbank team? Wo stecken die Daten der Datenbanktabelle adressen? Zumindest für dein lokales System kann ich dir

      309

      Kapitel

      13

      Ein Adressbuch für dein Team diese Frage beantworten! Die Daten liegen in einem Unterordner unter mysql. Dieser Unterordner heißt data. Da MySQL in unserem Beispiel unter C:\xampp\mysql installiert wurde, finden sich alle Datenbanken unter C:\xampp\mysql\data.

      Jede Datenbank bekommt einen eigenen Unterordner.

      Du kannst diese Unterordner sichern und auf diese Art sogar auf andere Rechner übertragen. Wo diese Datenbanken jedoch beim Dienstleister genau abgelegt werden, ist in der Regel nicht bekannt! Bei den preisgünstigen Dienstleistern mit PHP/MySQL-Unterstützung kommst du normalerweise nicht an diesen Ordner heran. Diese Anbieter erlauben dir lediglich, über das Tool phpMyAdmin mit deiner Datenbank zu kommunizieren. Für den »vollen Datenbankzugriff« benötigst du einen eigenen Webserver – und das wird teuer!

      Tipps und Tricks zur Bedienung von phpMyAdmin phpMyAdmin bietet eine freundliche und einfach zu bedienende Oberfläche! Mit diesem Tool kannst du alle deine Datenbanken und Datenbanktabelle verwalten. Trage Daten ein, lasse sie dir anzeigen. Hier ein paar Tipps und Tricks zur Bedienung: Hauptseite aufrufen Die »Hauptseite« oder auch Willkommens-Seite des Programms erreichst du, wenn du links oben auf den Link HOME klickst – also auf das Häuschen. 310

      Trage ein paar Adressen ein! Datenbank auswählen Die gewünschte Datenbank wählst du links aus dem Listenfeld aus – zumindest bei neueren Versionen von phpMyAdmin. Hier werden nicht alle Datenbanken gezeigt? Die Datenbank team fehlt? Manchmal hängt die Anzeige etwas! Wähle zuerst eine vorhandene Datenbank aus, in der Regel wird die Anzeige dann aktualisiert. Datenbanktabellen einblenden Die in einer Datenbank enthaltenen Datenbanktabellen findest du ebenfalls im linken Bereich. Klicke das Symbol vor dem Namen der Datenbanktabelle an, um die Tabellenstruktur zu sehen. Klicke im Beispiel auf das Symbol links von adressen. Infos zum Speicherplatzverbrauch der Datenbanktabelle Rolle in der Tabellenstruktur nach unten. Klicke auf Tabellenstruktur analysieren. Hier findest du nützliche Infos und Tools rund um diese Datenbanktabelle. Interessant sind z. B. die Angaben zum Speicherplatzverbrauch. Inhalt der Datenbanktabelle anzeigen Du möchtest den Inhalt der Datenbanktabelle anzeigen? Das geht zum einen durch Klick auf die Registerzunge ANZEIGEN. Zum anderen kannst du aber auch links direkt auf den Namen der Datenbanktabelle klicken.

      Der Klick auf den entsprechenden Link zeigt den Inhalt der Datenbanktabelle.

      Datensätze sortieren Du möchtest deine Datensätze sortiert anzeigen? Kein Problem! Klicke einfach auf die entsprechende Spaltenbeschriftung. Ein neuerlicher Klick dreht die Sortier-Reihenfolge um. Zum »Hauptmenü« der Datenbank wechseln Du möchtest zwar nicht auf die »Willkommens-Seite« von phpMyAdmin, aber ins »Hauptmenü« der jeweiligen Datenbank? Vielleicht, weil du weitere Datenbanktabellen einrichten möchtest? Klicke im linken Bereich einfach auf den Namen der Datenbank, hier auf team. Auch das ist also ein Hyper-

      311

      Kapitel

      Ein Adressbuch für dein Team

      13

      link! phpMyAdmin ist ein nützliches Werkzeug mit vielen Möglichkeiten. Probiere am Anfang ruhig ein wenig herum! SQL geht dir momentan etwas auf den Senkel? Du möchtest eine Datenbanktabelle auf komfortablere Art und Weise einrichten? Gehe ins »Hauptmenü« der jeweiligen Datenbank, z. B. durch Klick auf den Namen der Datenbank oder durch Auswahl der Datenbank im Listenfeld ganz links. Rolle dann etwas tiefer zum Bereich Neue Tabelle in Datenbank soundso erstellen. Trage den Namen der gewünschten Datenbanktabelle in das Feld NAME ein. Lege die Anzahl der Felder im Feld FELDER fest. Nach Klick auf OK erscheint eine Seite, auf der du die Namen der einzelnen Felder und die jeweiligen Datentypen über Menüs auswählen kannst. phpMyAdmin generiert den entsprechenden SQL-Code automatisch für dich und zeigt ihn dir an! Ideal auch zum spielerischen Lernen von SQL! Lerne am Vorbild!

      Alle Teammitglieder da? Schaue nach! Datenbanking mit SQL macht Spaß! Wetten? Ich empfehle dir – trage ruhig ein paar weitere Adressen in die Datenbanktabelle adressen ein. Damit hast du etwas Material zum Spielen. Denn jetzt zeige ich dir, wie du mit SQL Datenbanktabellen abfragst – spielerisch natürlich! Für die nächsten Experimente benötigst du stets die »Hauptansicht«. Klicke am besten im linken Bereich auf den Namen deiner Datenbank. Klicke im Beispiel auf den Namen team. Wähle dann die Registerzunge SQL. Dann siehst das Feld zur Eingabe der SQL-Befehle – und genau das brauchst du! Gib die SQL-Befehle im Register »SQL« ein oder importiere sie aus einer Textdatei! Letzteres gelingt im Register »Importieren«.

      312

      Alle Teammitglieder da? Schaue nach!

      Alle Datensätze ausgeben mit SELECT Und nun geht’s weiter mit unserem SQL-Crashkurs! Du möchtest Daten ausgeben? Dafür benötigst du das Schlüsselwort SELECT wie AUSWÄHLEN. Wenn du alles auswählen möchtest, tippst du das Sternchen * und schreibst zum Schluss das Schlüsselwort FROM. Dahinter gibst du den Namen der Tabelle an. Vergiss nicht die obligatorischen Leerzeichen zwischen den einzelnen Schlüsselwörtern. Du möchtest alle Datensätze aus deiner Tabelle adressen ausgeben? Folgender Befehl erledigt den Job für dich: SELECT * FROM adressen

      Klicke auf OK und staune. So einfach ist SQL!

      Nur einzelne Felder ausgeben Du möchtest nicht alle Felder anzeigen? Du willst nur den Namen wissen? Oder den Namen und den Vornamen? Nichts leichter als das. Folgende Zeile SELECT Name FROM adressen

      gibt nur die Namensspalte aus. Alle anderen Spalten werden weggeblendet. Wenn du dagegen Namen und Vornamen möchtest (Feld Name und Feld Vorname), trennst du diese Angaben einfach mit einem Komma. SELECT Name, Vorname FROM adressen

      Nach bestimmten Auswahlkriterien filtern mit WHERE Du möchtest nur diejenigen herausfiltern, die aus Neustadt kommen? Nutze das Schlüsselwort WHERE und gib zuerst den Feldnamen an, z. B. den Ort. Nach einem Gleichheitszeichen notierst du in Gänsefüßchen den Wert, nach dem du filtern möchtest. Im Beispiel schreibst du: WHERE Ort='Neustadt'

      Du möchtest die entsprechenden Datensätze komplett ausgeben? Dann schreibe: SELECT * FROM adressen WHERE Ort='Neustadt'

      313

      Kapitel

      Ein Adressbuch für dein Team

      13

      Und wie lautet der Befehl, wenn du nur Namen und Vornamen aller Teammitglieder aus Neustadt anzeigen möchtest? Genau so: SELECT Name, Vorname FROM adressen WHERE Ort='Neustadt'

      Groß- und Kleinschreibung spielt hier übrigens keine Rolle. Auch wenn du in der Datenbank aus Versehen neustadt notiert hast, wird dieser Datensatz gefunden! Allerdings sind keine Zusätze zum Wort Neustadt erlaubt, das Gleichheitszeichen verlangt exakt diese Zeichenfolge. Was machst du jedoch, wenn einige der Teammitglieder in NeustadtSüd, andere dagegen in Neustadt-Nord und andere wiederum in Groß Neustadt wohnen? Denn mit Ort='Neustadt' erwischst du doch wirklich nur diejenigen, die genau in Neustadt wohnen?! Du verwendest den Operator LIKE. Denn so kannst du außerdem auf den Platzhalter % zurückgreifen, der quasi als Joker für kein, ein oder auch beliebig viele andere Zeichen steht. Folgender Vergleich SELECT * FROM adressen WHERE Ort LIKE '%Neustadt%'

      liefert wirklich alle Datensätze, in denen das Feld Ort irgendwas mit Neustadt zu tun hat.

      Auswahlkriterien miteinander verknüpfen Wenn du möchtest, kannst du auch mehrere Auswahlkriterien miteinander verknüpfen. Dafür stehen dir z. B. folgende Operatoren zur Verfügung: 0 AND (wie UND) 0 OR (wie ODER) Du möchtest alle Teammitglieder aus Neustadt anzeigen, die mit Nachnamen Meier heißen? Schreibe SELECT * FROM adressen WHERE Ort='Neustadt' AND Name='Meier'

      Du möchtest dagegen die Mitglieder herausfinden, die in Neustadt wohnen oder die Meier heißen? SELECT * FROM adressen WHERE Ort='Neustadt' OR Name='Meier'

      314

      Dann bekommst du zum einen die Neustädter angezeigt und auch alle anderen eventuellen Meiers. Probiere es aus! Trage ggf. noch ein paar Datensätze in die Liste ein!

      Alle Teammitglieder da? Schaue nach!

      Wundere dich nicht: phpMyAdmin hängt an alle Abfragen noch das Schlüsselwort LIMIT 0, 30. Damit werden nur die ersten 30 Datensätze angezeigt. Der erste Wert steht für den Startdatensatz. Die Zählung beginnt hierbei wieder bei 0 – die Arrays lassen grüßen! Der zweite Wert sagt aus, wie viele Datensätze du gleichzeitig sehen möchtest. Wenn du die nächsten 30 Datensätze einblenden möchtest, gibst du den SQLBefehl erneut ein. Füge dann LIMIT 30, 30 ein.

      Sortieren mit ORDER BY Auch das Sortieren deiner Datensätze ist mit SQL überhaupt kein Problem! Dafür benötigst du das Schlüsselwort ORDER BY. Sortiere deine Adressliste doch einfach nach dem Nachnamen. Dafür setzt du nach diesem Schlüsselwort lediglich den Feldnamen ein: 0 ORDER BY Name Dabei wird automatisch aufsteigend nach dem Alphabet sortiert. Um z. B. alle Datensätze nach Namen sortiert anzuzeigen, schreibst du: SELECT * FROM adressen ORDER BY Name

      Wenn du jedoch nach dem Ort und innerhalb des Ortes auch nach dem Namen sortieren möchtest, schreibst du SELECT * FROM adressen ORDER BY Ort, Name

      In diesem Falle richtet sich die Hauptsortierreihenfolge nach dem Ort. Die Orte stehen alphabetisch geordnet untereinander. Innerhalb eines Ortes jedoch werden die Datensätze zusätzlich nach Namen sortiert. Du kannst aber auch absteigend sortieren. Dann notierst du hinter dem Sortierbefehl zusätzlich das Schlüsselwort DESC für descending, absteigend. Du möchtest alle Datensätze nach dem Namen sortieren, und zwar alphabetisch rückwärts? Dann sieht die Zeile folgendermaßen aus: SELECT * FROM adressen ORDER BY Name DESC

      Nun werden die Namen mit X, Y oder Z an allererster Stelle erscheinen.

      315

      Kapitel

      13

      Ein Adressbuch für dein Team

      Wie wär’s mit einem UPDATE? Du möchtest den bestehenden Inhalt einer Datenbank aktualisieren? Das ist manchmal sogar verdammt wichtig! Schließlich kannst du nicht davon ausgehen, dass deine Team-Mitglieder immer am gleichen Ort wohnen bleiben. Die Möglichkeit für Adressänderungen solltest du schon vorsehen. Ändere eins oder auch mehrere Felder eines Datensatzes, und zwar mit dem Schlüsselwort UPDATE. Danach gibst du wieder den Tabellennamen an und notierst außerdem das Schlüsselwort SET 0 UPDATE tabellenname SET Doch welche Felder möchtest du aktualisieren? Und von welchem Datensatz? Hier kommt wieder die WHERE-Klausel ins Spiel. Angenommen, Petra Kulicke (Datensatz mit der id 5) zieht von der Parkstr. 12 in Platanenallee 22. Dann schreibst du. UPDATE adressen SET Str='Platanenallee 22' WHERE id='5'

      Dadurch werden die alten Werte dieser Felder automatisch überschrieben! Die Zahl musst du übrigens nicht in Gänsefüßchen einkleiden. Das Feld id ist schließlich ein Feld vom Typ INT (Integer), also ein Zahlenfeld. Wenn du die Gänsefüßchen jedoch setzt, ist das nicht schlimm. Soll neben der Straße gleichzeitig die Postleitzahl geändert werden? Kein Problem! Liste das zweite (oder dritte, vierte usw.) Feld einfach nach einem Komma auf. UPDATE adressen SET Str='Platanenallee 22', PLZ='23010' WHERE id='5'

      Auch das geht: Datensätze löschen mit DELETE Zum Schluss stelle ich dir den wohl mächtigsten, aber auch gefährlichsten SQL-Befehl vor. Es ist der Befehl DELETE. Die Syntax lautet 0 DELETE FROM tabellenname WHERE bedingung Du möchtest den Datensatz mit der id 2 aus deiner Tabelle entfernen? Dann schreibst du DELETE FROM adressen WHERE id='2'

      316

      Daten als HTML-Tabelle ausgeben Auf ähnliche Weise könntest du auch alle Meiers oder alle Teammitglieder aus Kuhdorf aus deiner Datenbank herausradieren. Für die Meiers sähe das so aus: DELETE FROM adressen WHERE Name='Meier'

      Du möchtest eine ganze Tabelle auf einen Rutsch löschen? Dann verwendest du statt DELETE das Schlüsselwort DROP. Der Befehl DROP TABLE adressen löscht die gesamte Tabelle adressen auf einen Rutsch. Halt – nicht ausprobieren, das war doch nur als Information gedacht. Wie bitte, schon zu spät? Nimm’s von der heiteren Seite! Das ist immerhin eine gute Übung zum Wiederholen und Festigen! Lege die Tabelle adressen einfach erneut an. Richte die entsprechenden AdressDatensätze ein. Und hüte dich beim nächsten Mal vor dem Befehl DROP!

      Daten als HTML-Tabelle ausgeben Hast du dich schon etwas eingefuchst mit SQL? Klappt es mit den Befehlen und Abfragen? Hervorragend! Die kleine Mühe war nicht umsonst, wie du gleich merken wirst. Du benötigst das SQL-Wissen für den Zugriff auf die Datenbank! Blende die Daten mit PHP und HTML ein. Das ist gar nicht so einfach, aber wir schaffen das! Zuerst fangen wir ganz bescheiden an und geben lediglich ein paar Felder unserer Adressliste aus. Danach steigern wir uns bis zu einer schicken Tabelle, die alle Datenfelder anzeigt.

      Einfache Ausgabe der Daten Im ersten Beispiel liest du alle Datensätze aus. Zeige von allen Datensätzen den Vornamen, Namen und den Ort an. Also nur diese drei Felder. Erstelle dazu eine PHP-Datei und füge folgenden Code ein. Ich liste dir den gesamten Bereich zwischen auf. Speichere das Dokument und probiere es aus. Funktioniert es?

      Adressen anzeigen


      317

      Kapitel

      13

      Ein Adressbuch für dein Team $sql = "SELECT * FROM adressen"; $result = mysqli_query($db, $sql); while ($row = mysqli_fetch_assoc($result)) { echo "$row[Vorname] $row[Name], $row[Ort]
      \n"; } mysqli_close($db); ?>



      Gib Vorname, Name und Ort von allen Datensätzen zeilenweise aus.

      Es hat nicht geklappt? Du hast beim Abschreiben einen Fehler gemacht? Du findest die Datei unter dem Namen zeige_adressen1.php auf der CD. Beachte, dass du für deine Datenbank evtl. Benutzernamen und Passwort anpassen musst. Wo genau, verrate ich dir gleich. Hast du’s gemerkt? Hier greift der Autor auf die Komfortschreibweise bei assoziativen Arrays zurück. Komfortschreibweise bedeutet, dass der key nicht in Gänsefüßchen notiert wird, wie es eigentlich sein sollte. Also statt $row["Vorname"] verwendet der Autor stets die Schreibweise $row[Vorname] und statt $row["Name"] einfach $row[Name] usw. Dieser kleine Trick vereinfacht den Code. Er ist dann zulässig, wenn die Variable selber innerhalb eines Strings notiert wurde, also selber Teil eines weit umspannenden Gänsefüßchen-Paars ist. Auf diese Weise ersparst du dir das Verketten der Variablen und kommst nicht so leicht mit den vielen Punkten und Gänsefüßchen durcheinander. Im weiteren Verlauf dieses Kapitels greift der Autor aus Gründen der Vereinfachung zumindest in diesem Fall immer wieder auf diese übliche Methode zurück! 318

      Daten als HTML-Tabelle ausgeben Wenn die Variable selber jedoch nicht innerhalb von Gänsefüßchen platziert wurde, dürfen die Gänsefüßchen um den key herum nicht fehlen. 0 Orientiere dich an den Farben im PSPad. Wenn der key des Arrays farbig hervorgehoben wird, ist alles in Ordnung. In diesem Fall sind keine weiteren Gänsefüßchen nötig. 0 Bleibt er schwarz, fehlen die Gänsefüßchen und sollten nicht weggelassen werden. Setze dann je nach Geschmack doppelte oder einfache Gänsefüßchen.

      So funktioniert das Skript Nach diesem hoffentlich erfolgreichen Versuch schauen wir uns die Wirkungsweise etwas genauer an. Du wirst sehen – vieles ähnelt vom Prinzip her dem Umgang mit Textdateien! Die Funktion mysqli_connect() Was macht folgende Zeile? $db = mysqli_connect("localhost", "root", "");

      Diese Zeile sorgt zuerst einmal für die Verbindung mit dem Datenbankserver. Dafür verwendest du die Funktion mysqli_connect. Als Argumente gibst du folgendes an, und zwar in Gänsefüßchen, jeweils durch ein Komma getrennt. 0 localhost (Ort der Datenbank, gilt sowohl offline auf dem heimischen Rechner als auch auf dem Webserver. Nur, wenn du von einer anderen Domäne aus auf die Datenbank zugreifst, musst du den Namen der Domäne angeben.) 0 Benutzername für die MySQL-Datenbank (z. B. root) 0 Kennwort (z. B. Leerstring) Beachte, dass bei den meisten Dienstleistern Benutzernamen und Kennwort für dich eingerichtet sind. Schaue in die Anmeldungs-E-Mail oder in deine Vertragsunterlagen! Und was macht die Variable $db am Anfang? Sie speichert die Verbindungskennung, das ist eine Art Verbindungszeiger. Über diese Kennung beziehst du dich auf die jeweilige Datenbankverbindung. Andere Funktionen benötigen diese Kennung. $db ist praktisch der rote Faden, der sich durch alle wichtigen Datenbankfunktionen hindurchzieht. Du kennst das Prinzip ja schon vom Umgang mit Textdateien!

      319

      Kapitel

      13

      Ein Adressbuch für dein Team Die Funktion mysqli_set_charset() Diese Funktion legt den Standard-Zeichensatz fest: UTF-8! Sie benötigt zwei Argumente: Verbindungskennung und Namen des Zeichensatzes. mysqli_set_charset($db, "utf8");

      (Wenn du diese Zeile weglässt, wird der Inhalt aus der Datenbanktabelle automatisch als ISO-8859-1 ausgegeben. Das ergibt in unserer als UTF-8 gekennzeichneten und gespeicherten PHP-Datei natürlich fürchterlichen »Umlautsalat«. Du musst in diesem Fall erst das Meta-Tag für den Zeichensatz bearbeiten. Ändere – wenn du es unbedingt willst - die Zeichenfolge utf-8 um in iso-8859-1. Und konvertiere die Datei per FORMAT|ANSI.) Die Funktion mysqli_select_db() Die Verbindung steht! Die Funktion mysqli_select_db() sucht nun die gewünschte Datenbank heraus. Notiere wieder zwei Argumente: zuerst die Verbindungskennung, dann den Namen der Datenbank in Gänsefüßchen. mysqli_select_db($db, "team");

      Dein Dienstleister hat dir eine Datenbank vorgegeben? Dann musst du statt team natürlich diesen Namen in Gänsefüßchen eintragen. Beachte das bitte! SQL-Code in einer Variablen speichern Die nächste Zeile wird dir vertraut vorkommen. Hier speicherst du vorab den gewünschten SQL-Befehl. Der Musterbefehl wählt alle Datensätze aus der Datenbanktabelle adressen aus. $sql = "SELECT * FROM adressen";

      Zum Speichern nutze ich eine Variable, die ich sinnigerweise $sql genannt habe. Zugegeben, du musst den SQL-Befehl nicht vorab in einer separaten Variablen speichern. Du könntest ihn auch direkt in den Befehl aus der nächsten Zeile einfügen. Aus Gründen der Übersichtlichkeit empfehle ich dir jedoch die von mir gezeigte Vorgehensweise! Abfrage ausführen mit mysqli_query() In der nächsten Zeile führst du die SQL-Abfrage aus. Dabei hilft dir die Funktion mysqli_query(). In den runden Klammern übergibst du erst die Kennung, dann den in der Variablen $sql gespeicherten SQL-String: 320

      $result = mysqli_query($db, $sql);

      Daten als HTML-Tabelle ausgeben oder du trägst den SQL-Code direkt in Gänsefüßchen ein: $result = mysqli_query($db, "SELECT * FROM adressen");

      Das Abfrage-Ergebnis wird in einer Variablen festgehalten, die ich $result genannt habe, result wie Ergebnis. Bei diesem Ergebnis handelt es sich um eine sogenannte Ergebnisliste, um ein result set. Die einzelnen Zeilen werden in Listenform in dieser Variablen gespeichert. Die Zeilen stehen im Prinzip untereinander, wie in einer Tabelle. Diese Ergebnisliste wird später Zeile für Zeile ausgelesen werden. Daten mit Hilfe einer Schleife ausgeben Die nächsten drei Zeilen sind nicht mehr ganz so einfach zu verstehen. Das gebe ich zu: while ($row = mysqli_fetch_assoc($result)) { echo "$row[Vorname] $row[Name], $row[Ort]
      \n"; }

      Zum einen gibt es da eine while-Schleife. Diese führt die Befehle aus, solange die Bedingung wahr ist. Doch was ist hier die Bedingung? Diese steckt in der Funktion mysqli_fetch_assoc($result)! Das ist eine ganz ungewöhnliche und recht talentierte Funktion. Diese Funktion »holt sich« die Ergebnisliste aus unserer Abfrage, also unsere Datenbanktabelle mit allen Zeilen. Und diese liegt schließlich in der Variablen $result vor. Liste ist das Stichwort, die Daten liegen hier zeilenweise vor. Zuerst holt sich die Funktion mysqli_fetch_assoc($result) die erste Zeile und wandelt diese in ein Array um. »Fetch assoc« heißt so viel wie »hole assoziatives Array«. Dieses Array wird in einer Variablen gespeichert, die ich sinnigerweise $row genannt habe, row wie Zeile! Die jeweilige Zeile wird dabei als assoziatives Array verwaltet, wie der Name assoc schon sagt. Der Name des Arrays heißt $row. Der key ergibt sich aus den Feldnamen. Du möchtest stattdessen ein indiziertes Array erhalten, also ein Array mit Zahlen? Dann wählst du die Funktion: 0 mysqli_fetch_row() 321

      Kapitel

      13

      Ein Adressbuch für dein Team

      Am häufigsten findest du in der Praxis merkwürdigerweise folgende Funktion, die mich persönlich jedoch nicht überzeugt hat: 0 mysqli_fetch_array() Diese liefert beides, und zwar ein assoziatives und ein indiziertes Array zugleich. Das ist einerseits natürlich ein Komfortgewinn. Diese Funktion wird in unserem bisherigen Beispiel deshalb auch funktionieren. Diese doppelte Array-Buchführung bereitet jedoch dann Probleme, wenn du die Elemente des Array zählen und mit einer foreach()-Schleife durchlaufen möchtest. In solch einem Falle wird diese Funktion eher hinderlich sein, da sie alles doppelt zählt und jeden key bzw. value zweimal ausgibt. Zurück zur Funktion mysqli_fetch_assoc(). Der Clou an der Geschichte: Diese Funktion greift sich nach Abarbeitung der vorigen nun die nächste Zeile. Diese Zeile existiert? Die Funktion in runden Klammern gibt true zurück? Dann wird die while-Schleife erneut aktiv. Die Funktion mysqli_fetch_assoc($result) »holt sich« die nächste Zeile der Datenbanktabelle und wandelt diese in das Array $row um usw. usf. Das geschieht dank unserer while-Schleife so lange, bis alle Zeilen der Ergebnisliste abgearbeitet sind. Denn erst dann gibt mysqli_fetch_assoc($result) false zurück und die while-Schleife wird verlassen. Auf diese Weise kannst du also Zeile für Zeile auf die gewünschten Werte zurückgreifen! Im Beispiel gebe ich dabei jedoch lediglich Vornamen, Namen und Ort aus: echo "$row[Vorname] $row[Name], $row[Ort]
      \n";

      Das geschieht so lange, bis alle Zeilen abgearbeitet sind. Verbindung zur Datenbank beenden Die letzte Zeile mysqli_close($db); beendet die Verbindung zur Datenbank. Das ist zwar nicht unbedingt nötig, gehört aber zu einem sauberen Programmierstil. Auch hier muss die Verbindungskennung als Parameter übergeben werden.

      322

      Daten als HTML-Tabelle ausgeben

      Zeilenzahl ausgeben mit mysqli_num_rows() Wäre es nicht schick, wenn du zusätzlich zu den Daten selbst auch die Anzahl der ermittelten Datensätze ausgeben könntest? Wieso könntest, du kannst! Dabei hilft dir die Funktion mysqli_num_rows(). Diese Funktion erwartet das Ergebnis der SQL-Abfrage, also unsere schon besprochene Ergebnisliste. In unserem Falle also die Variable $result. Die Funktion mysqli_num_rows() macht nichts weiter, als hier die Zeilen durchzuzählen! Die so ermittelte Zeilenzahl kannst du in einer weiteren Variablen (hier $zeilen) festhalten und mit echo ausgeben. Platziere diese Zeilen über der while-Schleife: $zeilen = mysqli_num_rows($result); echo "$zeilen Einträge:

      \n";

      Gib die Zahl der auszugebenden Datensätze an.

      Nicht schlecht, oder? Das derart erweiterte Skript findest du auch in der Datei zeige_adressen2.php.

      Fehlermeldungen unterdrücken Unser Skript funktioniert, besitzt bisher jedoch noch einige Schönheitsfehler! Was passiert, wenn der Datenbankzugriff einmal nicht gelingt? Vielleicht, weil MySQL gerade nicht zur Verfügung steht? Weil das Passwort verkehrt ist? Oder der Name der Datenbank nicht stimmt? Mache dir doch einmal den Jux und verfälsche sowohl Benutzernamen oder Passwort in der ersten PHP-Zeile und den Datenbanknamen in der dritten PHP-Zeile.

      323

      Kapitel

      13

      Ein Adressbuch für dein Team

      $db = mysqli_connect("localhost", "root", "falscher_Eintrag"); mysqli_set_charset($db, "utf8"); mysqli_select_db($db, "teamz");

      Was passiert? Es hagelt Fehlermeldungen noch und nöcher!

      Fehler über Fehler – so macht der Datenbankzugriff keinen Spaß!

      Was kann man dagegen unternehmen? Ich präsentiere dir zwei Geheimtricks! Der Trick mit dem Klammeraffen Der erste Trick besteht darin, vor den jeweiligen Funktionen einen Klammeraffen zu notieren. Das geht bei den meisten Funktionen und unterdrückt alle Fehlermeldungen: $db = @mysqli_connect("localhost", "root", "falscher_Eintrag"); mysqli_set_charset($db, "utf8"); @mysqli_select_db($db, "teamz");

      Wenn du deine Seite jetzt aktualisierst, siehst du … möglicherweise überhaupt nichts. Die Daten werden nicht angezeigt. In der Regel erscheinen keine, oder zumindest weit weniger kryptische Fehlermeldungen! Hmm. Trotzdem willst du sicher gerne wissen, wo genau das Problem steckt? Kein Problem! Da greift mein zweiter Trick: Friss oder stirb, Liebling! Verlängere die gewünschten Funktions-Zeilen einfach um die weiter vorne schon besprochene Anweisung. or die();

      324

      Dadurch wird die Ausführung des Skriptes an dieser Stelle abgebrochen. In den runden Klammern notierst du eine sinnvolle Fehlermeldung. Die so präparierten Zeilen sehen folgendermaßen aus, ich wende diese Technik bei der Verbindung zu MySQL und der Verbindung zur Datenbank an.

      Daten als HTML-Tabelle ausgeben $db = @mysqli_connect("localhost", "root", "falscher_Eintrag") or die("Verbindung zu MySQL gescheitert!"); mysqli_set_charset($db, "utf8"); @mysqli_select_db($db, "teamz") or die("Datenbankzugriff gescheitert!");

      Je nach Problem bekommst du nun entweder die Meldung Verbindung zu MySQL gescheitert oder Datenbankzugriff gescheitert zu sehen. Probiere es aus, indem du mal das Passwort in der ersten und dann den Tabellennamen in der dritten Zeile »fälschst«. Ab jetzt werden wir diese beiden Tricks ganz selbstverständlich in unsere Datenbankabfrage hineinpacken. Vergleiche mit der Datei zeige_adressen3.php, wo du beide Tricks im Einsatz findest. Und noch einen Trick gibt es: Funktionen wie mysqli_connect() und mysqli_select_db() geben je nach Erfolg oder Misserfolg entweder true oder false zurück. Du kannst also auch mit einer if-Abfrage arbeiten. Das zeige ich dir ganz am Schluss des Kapitels, und zwar bei der Eingabe von Datensätzen. Denn gerade dann ist es nützlich zu wissen, ob die Abfrage überhaupt funktioniert hat.

      Ausgabe aller Datensätze in einer Tabelle Aber ich hatte dir ja eine Tabelle versprochen. Außerdem sollen im Beispiel die Felder von allen Datensätzen eingeblendet werden, und nicht nur der Vorname, der Name und der Ort. Geht das? Na klar! Dabei hilft uns wieder die schon bekannte whileSchleife in Zusammenarbeit mit einer zusätzlichen foreach-Schleifenkonstruktion.

      Gib deine Datenbanktabelle aus – und zwar als HTML-Tabelle!

      Schau dir das Beispiel an, vielleicht verstehst du es ja schon beim Lesen. Wenn du keine Lust zum Abschreiben hast – du findest den Quellcode auch in der Datei zeige_adressen4.php.

      325

      Kapitel

      13

      Ein Adressbuch für dein Team

      Adressen anzeigen

      $zeilen Einträge:

      \n"; // Tabelle definieren: echo "\n"; // Kopfzeile der Tabelle anlegen: echo "" . "" . "" . "\n"; // while-Schleife Anfang while ($row = mysqli_fetch_assoc($result)) { echo ""; // Zeile erzeugen // foreach Anfang: foreach ($row as $key => $value) { echo "\n"; } // foreach Ende echo ""; // Zeile schließen } // while Ende echo "
      idVornameNameStrPLZOrtTelEMailWWWNotizen
      $value 
      \n"; // Tabelle schließen mysqli_close($db); ?>


      Der Quellcode kurz erklärt Blickst du durch? Als kleine Lesehilfe habe ich einige Kommentare eingefügt: Zuerst erzeuge ich die Elemente für die HTML-Tabelle: Ich definiere die Tabelle und lege die Kopfzeile an. Die Spaltenköpfe werden in eingekleidet. Sie erscheinen dadurch fett. Sinnigerweise verwende ich als Beschriftung die Feldnamen. Das dient der Wiedererkennung. 326

      Mit PHP: Eingabeformular selbst gestrickt Das eigentlich Interessante findet jedoch innerhalb der while-Schleife statt. Als erstes wird mit echo ""; die Zeile erzeugt, vergleiche mit meinem Kommentar. Danach folgt eine foreach-Schleife, also eine Schleife in einer Schleife. Foreach durchläuft das gesamte Array, also alle Datenfelder der jeweiligen Zeile. Ausgegeben wird der $value, also der Inhalt des jeweiligen Datenfeldes. Diesen kleide ich kunstvoll in eine Tabellenzelle ein: echo "$value ";

      Wozu dient das Zeichen  ? Das ist ein non breaking space, ein geschütztes Leerzeichen. Mit diesem Trick sichere ich zu, dass auch leere Zellen zumindest mit einem Leerzeichen ausgefüllt werden! Denn völlig leere Zellen erscheinen in Browser irgendwie als Fehlstellen – das würde den optischen Gesamteindruck der Tabelle doch arg beeinträchtigen. Außerhalb von foreach, aber noch innerhalb von while schließe ich die Tabellenzeile mit ab. Unterhalb der Schleife wird auch die Tabelle selbst mit geschlossen. Du wunderst dich, warum in den meisten Beispielen anderer Bücher oder Skripte immer nur die Funktion mysqli_fetch_array() verwendet wird, hier jedoch nicht? Da wundere ich mich aber auch, denn ich finde die Funktion mysqli_fetch_array() nicht so ideal. Spätestens in diesem Fall sind wir zwingend auf mysqli_fetch_assoc() oder auf mysqli_fetch_row() angewiesen! Probiere es aus: Beim Einsatz von mysqli_fetch_array() wird die Tabelle völlig schief und krumm aussehen, da mysqli_fetch_array() schließlich zwei Arrays gleichzeitig erzeugt. Und so ein »Doppelarray« lässt sich halt schlecht auswerten, denn foreach() würde hier alles doppelt zählen.

      Mit PHP: Eingabeformular selbst gestrickt Doch nun zur Dateneingabe selbst. Auch die erfolgt natürlich wieder mit SQL. Zum einen benötigst du ein Eingabeformular. Dieses schickt die Daten im Beispiel an sich selbst. Ich habe es dir auf der nächsten Seite abgebildet. 327

      Kapitel

      Ein Adressbuch für dein Team

      13

      Mit dieser selbst gestrickten Maske werden neue Adressen eingegeben.

      Im PHP-Teil musst du die Dateneingabe mit folgender SQL-Anweisung durchführen: INSERT INTO adressen () VALUES ()

      Erinnerst du dich? Wir hatten diesen Befehl ganz am Anfang schon einmal trainiert! Dabei werden im ersten runden Klammernpaar die Feldnamen notiert, nur durch ein Komma getrennt. Im zweiten Klammernpaar müssen die entsprechenden Werte eingetragen werden. Diese notierst du in einfachen Gänsefüßchen. Beachte außerdem auf jeden Fall die richtige Reihenfolge.

      Der Quelltext im Überblick Im Endeffekt sieht das Skript folgendermaßen aus. Es ist lediglich eine reine Abschreib-Fleißarbeit. Eine kleine Besonderheit steckt in der zweiten if-Abfrage, die wir danach besprechen:

      Adressen eingeben

      Vorname:
      Name:
      Str:
      PLZ:


      328

      Mit PHP: Eingabeformular selbst gestrickt Ort:
      Tel:
      E-Mail:
      Webadresse:

      Notizen:

      Abfrage erfolgreich!

      "; } else { echo "

      Abfrage nicht erfolgreich!

      "; } mysqli_close($db); } ?>

      Eigentlich ist das Skript nicht schwer zu durchschauen. Du verbindest ein HTML-Formular mit einem PHP-Teil. Das HTML-Formular schickt die Daten per POST an sich selber. Der PHP-Teil wird aktiv, wenn die Variable $_POST["submit"] nicht leer ist (also wenn der Submit-Button angeklickt wurde). Dafür sorgt die dir schon bekannte Technik mit einer alles umspannenden if-Abfrage. Wir verwenden die schon besprochene Funktion empty(). Diese prüft schließlich, ob der Wert der Variablen nicht gesetzt ist, leer ist oder 0 entspricht. Dann gibt diese Funktion true zurück. Da wir in der if-Abfrage aber das Gegenteil auslesen möchten, stellen wir der Funktion den Operator ! voran.

      329

      Kapitel

      13

      Ein Adressbuch für dein Team Im Klartext: Nur bei gesetzter Variable empty($_POST["submit"]) – also wenn die Variable nicht leer ist – wird der Code der if-Abfrage ausgeführt. So weit, so gut. Und der SQL-Teil? Den hatten wir vom Prinzip her schon mehrfach besprochen. Beachte, dass der SQL-Code für die Variable $sql diesmal ziemlich lang wird. Das geht los mit INSERT INTO adressen ... und setzt sich über mehrere Zeilen fort. Ich teile diesen Code daher auf mehrere Zeilen auf und nutze dabei den Verkettungsoperator Punkt (.). Wunderst du dich über die if-Abfrage im letzten Teil des Skriptes? Also über die Zeile if (mysqli_query($db, $sql)) {? Damit teste ich, ob die Abfrage an die Datenbank korrekt war. Nur dann kann ich davon ausgehen, dass die Daten vermutlich richtig eingetragen wurden. Vermutlich bedeutet: Ich kann damit nicht feststellen, ob beim Eintragen der Daten auch wirklich alles geklappt hat. Das gelingt erst mit der Funktion mysqli_affected_rows(). Die besprechen wir im nächsten Kapitel. Wir müssen uns ja schließlich noch eine Steigerungsmöglichkeit offen lassen! Wenn du neugierig bist – blättere zur Seite 348. Du findest den Code auch auf der CD, und zwar in der Datei eingabe_ adressen.php.

      Verbinde beide Seiten mit einem Hyperlink Verbinde am Schluss beide Seiten mit einem Hyperlink. Meine beiden fertigen Hauptseiten heißen: 0 zeige_adressen.php (Darstellung der Adresstabelle) 0 eingabe_adressen.php (Formular zur Eingabe der Daten) Auf der Formularseite baust du in diesem Fall folgenden Link ein:

      Adressen anzeigen



      Auf der Tabellenseite wiederum steht

      Adressen eingeben



      Was ist noch nicht perfekt? 330

      Kurz: eine ganze Menge! Unser Skript hat noch mehrere erhebliche Mängel und Schönheitsfehler!

      Mit PHP: Eingabeformular selbst gestrickt

      Probleme mit Gänsefüßchen Zum einen gibt es Probleme mit dem einfachen Gänsefüßchen. Probiere doch einmal das Eintragen eines Namens wie O'Hara. Zumindest auf unserem lokalen Webserver klappt es nicht! Auch bei vielen Dienstleistern gibt es Schwierigkeiten. Warum? Schon die entsprechende Array-Variable wird von einfachen Gänsefüßchen umhüllt: '$_POST[Name]'. Und ein weiteres einfaches Gänsefüßchen bringt den SQL-Code durcheinander. Diese Gänsefüßchen kommen sich gegenseitig ins Gehege. Fazit: Wir müssten die eventuell störenden Gänsefüßchen noch entwerten, also einen Backslash davorsetzen. Das ist nur die halbe Wahrheit. Bei manchen Dienstleistern werden die Gänsefüßchen automatisch entwertet, dank der »magic quotes«. Das Problem: Du kannst (und solltest) dich nicht darauf verlassen! Dieses Kuddelmuddel gehen wir im nächsten Kapitel auf Seite 351 an! Dort stelle ich dir die Funktion mysqli_real_escape_string() vor und verrate dir mehr zu den Vor- und Nachteilen der »magic quotes«.

      Werte werden nicht überprüft Ein weiteres Problem: Die Werte aus den Formularfeldern werden nicht getestet. Für den Praxiseinsatz solltest du umfangreiche Prüfroutinen in das Formular einbauen. Nutze dafür beispielsweise die regulären Ausdrücke, prüfe auf korrekten Aufbau der E-Mail-Adresse, auf Mindestlänge usw. Wenn du dieses Formular ungeschützt im Web einsetzt, musst du die Formularfelder unbedingt überprüfen! Sonst ist deine Datenbanktabelle schneller zugespammt, als dir lieb ist. Wurden alle wichtigen Felder ausgefüllt? Handelt es sich bei der E-Mail-Adresse um eine gültige E-MailAdresse? Wurde bei bestimmten Feldern eine Mindest-Zeichenlänge erreicht? Weiterhin benötigst du im Skript auch eine Funktion namens mysqli_real_escape_string(), um das Hacken deiner Datenbank zu unterbinden. Ihre Wirkungsweise lernst du im nächsten Kapitel kennen. Außerdem solltest du gegebenenfalls die Ausgabe von HTML-Zeichen entschärfen. Dazu steht dir die Funktion htmlspecialchars() zur Verfügung. Das ist vor allem dann nötig, wenn du vermutest, dass jemand böswilligen Quellcode in deine Datenbanktabelle schummeln wird! Doch ich bitte um Geduld! An dieser Stelle verkneife ich mir jedoch diesen ganzen Aufwand. Schließlich ist das Formular nur als Lehrbeispiel gedacht – zum Warmwerden. Es soll in dieser Form ja auch gar nicht im Web einge-

      331

      Kapitel

      13

      Ein Adressbuch für dein Team setzt werden! Und wenn, dann höchstens mit Passwortschutz – und damit für ausgewählte Nutzer. Bei den Praxisbeispielen der nächsten Kapitel achten wir jedoch verstärkt auf Sicherheit!

      Schlussbemerkung Uff. Was für ein Kapitel! Datenbanking ist wohl doch nicht so einfach wie vermutet. Aber du hast es geschafft – Du kennst dich mit SQL aus! Mit diesem Kapitel hast du die Grundlagen für dynamisches Webdesign erworben. Und dafür hat sich die harte Arbeit gelohnt, oder?

      Zusammenfassung 0 Du weißt, dass du eine Datenbank vor dem Anlegen planen musst. Du benötigst den Namen der Datenbank, der übergeordneten Hülle. Am wichtigsten ist jedoch der Name der Datenbanktabelle. Denke dir außerdem die Feldnamen aus und vergiss nicht das Schlüsselfeld (Primärschlüssel) für die eindeutige Identifizierung eines jeden Datensatzes. 0 Du kennst das Tool phpMyAdmin, eine Art grafische Oberfläche für MySQL. Damit kannst du Datenbanken und Datenbanktabellen anlegen, SQL-Anfragen starten, Daten eintragen, ausgeben und löschen und vieles andere mehr. 0 Du kennst den grundlegenden SQL-Befehl zum Anlegen einer Datenbanktabelle, und zwar CREATE TABLE Tabellenname (). 0 Du kennst wichtige Datentypen, z. B. VARCHAR für variable Zeichenfolgen bis 255 Zeichen Länge, TEXT für Passagen mit einer Länge von bis 65.535 Zeichen und INT für Ganzzahlen bis zu vier Milliarden. 0 Du kennst den Befehl zum Eintragen von Datensätzen in eine Tabelle, und zwar INSERT INTO adressen () VALUES (). Im ersten runden Klammernpaar trägst du die Feldnamen, im zweiten Klammernpaar die Werte ein, jeweils durch ein Komma getrennt. Die Werte müssen außerdem in Hochkommata gesetzt und in der richtigen Reihenfolge notiert werden.

      332

      0 Du kennst die diversen SQL-Befehle zur Ausgabe von Daten. Du weißt, dass SELECT * FROM tabelle alle Datensätze auswählt und dass du statt des Sternchens auch die einzelnen Felder angeben kannst. Du verwendest WHERE zum Filtern von Daten, ORDER BY zum Sortieren, UPDATE zum Ergänzen und DELETE zum Löschen von Werten.

      Ein paar Fragen … 0 Du kennst die Grundfunktion für den Verbindungsaufbau mit der Datenbank wie mysqli_connect() und die Funktion für die Auswahl der Datenbank mysqli_select_db(). 0 Du kennst die Funktion zum Festlegen des Standardzeichensatzes für die Verbindung: mysqli_set_charset(). 0 Du speicherst das Ergebnis von mysqli_query() in einer Variablen $result und erhältst damit die sogenannte Ergebnisliste. Hier sind die einzelnen Datensätze zeilenweise gespeichert. 0 Mit mysqli_num_rows($result) kannst du die Zahl der Zeilen eines Ergebnisses zählen. 0 Die Funktion mysqli_fetch_assoc($result) geht diese Ergebnisliste Zeile für Zeile durch und gibt jede Datenbankzeile als assoziatives Array zurück. Dieses Array legst du in einer selbst festzulegenden Variable ab, fange es z. B. auf mit $row = mysqli_fetch_assoc ($result). Für den Zeilenvorschub arbeitest du mit einer whileSchleife. 0 Jeder einzelne Wert lässt sich nun nach dem Schema $row[Feldname] ermitteln. 0 Du kennst auch die Funktion mysqli_fetch_row($result) für die Ausgabe eines indizierten Arrays und die problematische Funktion mysqli_fetch_array($result), die sowohl ein assoziatives als auch ein indiziertes Array gleichzeitig erzeugt. 0 Du kennst Techniken zum Abfangen von Fehlermeldungen. Notiere einen Klammeraffen vor der entsprechenden Funktion. Gib durch die Anweisung or die() im Misserfolgsfalle eine Meldung aus. Oder nutze einfach eine »klassische if-Abfrage« für die Darstellung von Erfolg oder Misserfolg. 0 Du weißt, wie du eine Eingabeseite zum Eintragen von Daten in die Datenbank programmierst. Du verbindest ein HTML-Formular mit dem entsprechenden PHP-Abschnitt. Dort greifst du auf den SQL-Code INSERT INTO adressen () VALUES () zurück.

      Ein paar Fragen … 1. Wozu benötigst du einen Primärschlüssel und wie lautet der Befehl zum Festlegen dieses Schlüssels? 2. Mit welchem Befehl sicherst du zu, dass ein Feld automatisch hochzählt?

      333

      Kapitel

      13

      Ein Adressbuch für dein Team 3. Angenommen du löschst einen Datensatz komplett mit DELETE. Angenommen, dieser Datensatz besitzt den Primärschlüssel 8. Wo die Zahl 8 doch nun »frei geworden ist«, wird sie für den nächsten Datensatz wieder vergeben werden? Und wenn nicht, warum nicht? 4. Mit welchem SQL-Befehl fragst du alle Datensätze der Tabelle adressen ab? 5. Welcher Datentyp speichert das Datum im Format YYYY-MM-DD, also Jahr vierstellig, Monat zweistellig und Tag zweistellig? 6. In welchem Unterordner auf deiner lokalen Festplatte legt MySQL seine Daten ab? 7. Wie lautet der Befehl zur Verbindung mit einer Datenbank? Welche Argumente benötigst du? 8. Welche Techniken kennst du zur Unterdrückung von Fehlermeldungen bei Funktionen?

      … und ein paar Aufgaben 1. Bearbeite die HTML-Datei zur Ausgabe der Adressen so, dass die Datensätze nach Namen geordnet ausgegeben werden. 2. Bearbeite die Datei zur Eingabe der Daten. Passe das HTML-Formular so an, dass die Länge der Felder dem Datentyp der Datenbanktabelle adressen entspricht. Im Klartext: Wenn ein Feld den Datentyp VARCHAR(20) besitzt, darf das entsprechende Feld im Eingabeformular auch nicht mehr als 20 Zeichen zulassen! (Tipp: Dafür benötigst du gute HTML-Kenntnisse. Du musst zumindest wissen, wie du in einem Formularfeld die maximale Länge erzwingst.) 3. Für Profis: Baue die Seite zur Eingabe der Adressen weiterhin so um, dass man nur bei Kenntnis des folgenden Passwortes ?zk63Xxd Daten eingeben kann. Sorge außerdem dafür, dass der Nutzer bei Unkenntnis des Passworts darüber informiert wird. 4. Für Profis: Erstelle ein drittes Dokument, mit welchem du einzelne Datensätze bearbeiten, »updaten« kannst. Dabei sollen alle Datenfelder auf einen Schlag überarbeitet werden. Erkenne die Datensätze anhand ihrer id. Nenne das Dokument update_adressen.php und verlinke es mit den anderen beiden Seiten.

      334

      14 Gästebuch de luxe als Datenbanktabelle Wie wär’s mal mit einem »richtigen« Gästebuch? Kein Problem mit MySQL! Schritt für Schritt baust du dein Gästebuch de luxe zusammen. In diesem Kapitel zeige ich dir, wie du $ die Gästebuch-Tabelle planst und Gästebuchdaten mit PHP ausgibst $ nur vier Datensätze zugleich und die neusten Einträge zuoberst anzeigst $ ein Eingabeformular für die Daten schreibst $ Doppeleingaben zuverlässig verhinderst – diesmal auf Datenbankebene $ Gästebuchspammer durch ein CAPTCHA (Rechenaufgabe) ausschließt $ eine Möglichkeit zum Freischalten der Einträge vorbereitest Einiges davon kommt dir sicher bekannt vor. Wenn nicht, blättere zum Kapitel 12, zu unserer »Nur-PHP-Gästebuchversion«. Auch aus dem Kapitel 8 (Feedbackformular) werden wir einiges übernehmen. Vieles jedoch ist neu, z. B. die Blättermöglichkeit mit Begrenzung der Anzeige auf vier Datensätze. Es muss schließlich Vorteile besitzen, mit einer Datenbank zu arbeiten! Wie bei den meisten »großen Projekten« gilt auch hier: Wir fangen bescheiden an. Du baust das Skript Schritt für Schritt zusammen, die entsprechenden Verbesserungen folgen erst, wenn du das Prinzip verstanden hast. Du findest den aktuellen Stand stets auch auf der CD zum Buch.

      335

      Kapitel

      Gästebuch de luxe als Datenbanktabelle

      14

      Datenbanktabelle planen Es geht langweilig und profan los. Du planst die Datenbanktabelle für dein Gästebuch. Wie viele Spalten soll die Tabelle besitzen? Welche Feldnamen brauchst du und wie nennst du diese? Welche Felddatentypen wären ideal?

      Feldnamen und Felddatentypen festlegen Hier mein Vorschlag: Feldname

      id

      Felddatentyp INT (Primärschlüssel)

      Name

      Home

      Datum

      Kommentar Zeigen

      VARCHAR(35)

      VARCHAR(50) VARCHAR(30) TEXT

      TINYINT

      Die meisten Felder erschließen sich sofort. Besonders wichtig ist natürlich der Primärschlüssel, die automatisch erzeugte eindeutige Kennung. Dafür sehe ich wieder ein Feld namens id vor. Im Feld Name gibt die oder der Eintragende seinen Namen ein. Das kann der Vorname, Nachname, beides oder einfach nur der Spitzname sein. Dafür sollten 35 Zeichen ausreichen. Im Feld Home möchte ich auf freiwilliger Basis die Webadresse oder aber die E-Mail-Adresse des Eintragenden sichern. Hierfür sind 50 Zeichen sicher ausreichend. Das Datum soll als komplettes Datum nebst Uhrzeit gespeichert werden. Mit 30 Zeichen kommt man gut über die Runden. Für den eigentlichen Eintrag (Feld Kommentar) biete ich mit dem Felddatentyp TEXT wieder reichlich Platz an, und zwar 65.535 Zeichen. Warum nehme ich für das Feld Datum den Felddatentyp VARCHAR() und nicht DATE? Weil ich mit DATE auf das Zwangsformat des Felddatentyps angewiesen wäre, auf das Format YYYY-MM-DD (Jahr-Monat-Tag). Das gefällt mir aber nicht! Ich erzeuge das Format lieber selber, und zwar als Tag-Monat-Jahr, Stunde:Minute. Dafür werde ich die PHP-Funktion date() mit den entsprechenden Formatierschaltern verwenden. Das Feld Zeigen bestimmt, ob der Eintrag angezeigt werden soll oder nicht. Nur wenn hier eine 1 steht, soll der Eintrag sichtbar sein – der Felddatentyp TINYINT (sehr kleine Ganzzahl) ist dafür bestens geeignet. Immerhin reicht der Wertebereich von -128 bis 127 und der Speicherplatzbedarf ist mit 1 Byte minimal. Du bestimmst im Skript, ob ein Gästebucheintrag sofort oder erst nach Begutachtung und Freischaltung durch dich angezeigt werden soll! 336

      Datenbanktabelle planen

      SQL-Befehle zum Einrichten der Tabelle Nun setzt du das Ganze wieder in SQL um! Zuerst erstellst du die Grundstruktur für diese Datenbanktabelle. Überlege dir einen Namen für die Tabelle – wie wäre es mit guestbook? Der Einfachheit halber legst du diese Tabelle in unserer im vorigen Kapitel erzeugten Datenbank team ab. Bei vielen Dienstleistern darfst du sowieso nur eine einzige Datenbank verwenden. Doch nun zum Erstellen der Datenbanktabelle guestbook. Starte phpMyAdmin, öffne deine Datenbank team und gib den entsprechenden Code in das Eingabe-Feld ein. Trage im Beispiel also Folgendes ein und klicke auf OK: CREATE TABLE guestbook ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, Name VARCHAR(35), Home VARCHAR(50), Datum VARCHAR(30), Kommentar TEXT, Zeigen TINYINT ) DEFAULT CHARACTER SET utf8;

      Erstelle einige Testeinträge! Die Datenbank ist fertig. Nun trägst du mit Hilfe von phpMyAdmin schon ein paar Testeinträge ein. Das können ruhig »Fälschungen« sein, wir brauchen diese Einträge nur für Übungszwecke. Wie du die Eingabemaske aufrufst, hast du dir gemerkt? Klicke in phpMyAdmin auf EINFÜGEN, dann erscheint die Datenmaske. Denke dir nun ein paar Einträge aus. Im Feld Datum trägst du das Datum im folgenden Stil ein: 0 18.04.2010, 12:11 Uhr Im Feld Kommentar kannst den Text ruhig durch Druck auf [Enter] gliedern. Du musst also nicht alles hintereinander schreiben. Du wunderst dich, warum das Eingabefeld für den Kommentar in phpMyAdmin so klein ist? Schreibe einfach los! Drücke auf [Enter] – du wirst sehen, wie es möglicherweise mitwächst. Dieses gewöhnungsbedürftige, sich selbst in der Höhe verändernde Texteingabefeld findest du zum Glück nur bei älteren Versionen von phpMyAdmin. Im Feld Zeigen notierst du übrigens schon einmal eine 1. Sonst kann der Eintrag ja gar nicht angezeigt werden!

      337

      Kapitel

      Gästebuch de luxe als Datenbanktabelle

      14

      Trage ein paar Daten in die Tabelle guestbook ein. Das Kommentarfeld wächst mit!

      Daten erst einmal ausgeben Die MySQL-Tabelle steht. Nun bauen wir Schritt für Schritt das dazugehörige Gästebuch zusammen. Ich habe mir für das Gästebuch den Dateinamen guestbook.php ausgedacht. Ehe wir uns über das Eingabeformular hermachen, sollen die Einträge erst einmal ausgegeben werden. Im Beispiel also das, was du eben in die Datenbanktabelle guestbook geschrieben hast. Du hast doch schon ein paar Testeinträge eingegeben, oder? Gerade bei komplexen Projekten wie diesem Gästebuch empfehle ich dir unbedingt die hier von mir verwendete »Modulbauweise«! Fange klein an. Setze zuerst einen Teilabschnitt deines Projekts um. Prüfe, ob es klappt. Erweitere das Projekt um das nächste »Modul«. Arbeite dabei – wenn es sein muss – ruhig mit Platzhaltertext. Füge die entsprechenden Elemente erst nach und nach ein. Teste regelmäßig, und zwar gleich nach dem Einbau eines »neuen Moduls«. Auf diese Weise entsteht das »große Projekt« Schritt für Schritt und du kannst deine Fehler leichter entdecken! Ganz wichtig bei der Geschichte – mache von jedem Bearbeitungsschritt eine Sicherheitskopie. So ist bei einem Fehler nicht gleich »alles verloren«. Du kannst problemlos zur vorherigen Entwicklungsstufe zurückkehren. 338

      Daten erst einmal ausgeben

      Der Ausgabe-Quellcode Modulbauweise, einverstanden! Der erste Schritt besteht in nichts weiter als der Ausgabe der Daten. Hier zeige ich dir den kompletten Abschnitt zwischen den Tags . Du findest diesen Quelltext komplett auf der CD zum Buch, und zwar in der Datei guestbook1.php. Schaue in den Ordner kapitel14, Unterordner guestbook.

      Gästebuch auf Datenbankbasis

      Bisherige Einträge:"; echo "

      Anzahl der Einträge: $zeilen

      \n"; // while-Schleife Anfang while ($row = mysqli_fetch_assoc($result2)) { echo "

      <strong>1. " . htmlspecialchars($row["Name"]) . " "; if (!empty($row["Home"])) { echo "(" . htmlspecialchars($row["Home"]) . ")"; } echo "
      --> schrieb am " . "<strong>" . $row["Datum"] . ":

      " . "

      " . nl2br(htmlspecialchars($row["Kommentar"])) . "


      \n"; } // while Ende mysqli_close($db); ?>


      Probiere es aus. Werden deine bisher notierten Datensätze angezeigt? Nein? Vergiss nicht, dass du die Zugriffsdaten ggf. an deine Bedürfnisse anpassen musst! Die 1 im Feld Zeigen hattest du notiert? 339

      Kapitel

      Gästebuch de luxe als Datenbanktabelle

      14

      Nach jedem Datensatz wird mit
      eine Linie erzeugt.

      Sieh’ wohlwollend darüber hinweg, dass mit dieser Version des Skriptes nur höchstens vier Datensätze angezeigt werden können und jeder Datensatz ein »1.« vorangestellt bekommt. Kleiner Layout-Trick: Auch bei diesem Gästebuch legt der Autor die Breite der Seite mit einem DIV-Container fest. Dafür sorgt das Tag
      direkt unter dem Tag . Dieses Tag wird über dem ausschaltendem mit
      wieder ausgeschaltet. Aber das ist nur eine Empfehlung. Ob du deine Seite lieber mit einer Tabelle »in Form« hältst oder auf eine exakte Breite ganz verzichtest, bleibt dir überlassen!

      Besonderheiten des Skriptes Die ersten beiden eigentlichen PHP-Zeilen stellen nichts Besonderes dar. Damit wird zum einen die Verbindung zu MySQL und zum zweiten die Verbindung zur Datenbank team aufgebaut. Dabei kommen die schon erwähnten bewährten Tricks zur Unterdrückung von Fehlermeldungen zum Einsatz.

      340

      Darunter folgen merkwürdigerweise zwei Zeilen mit zwei unterschiedlichen SQL-Abfragen. Die Zeile $sql1 = "SELECT * FROM guestbook WHERE Zeigen = 1"; ermittelt alle freigeschalteten Datensätze der Tabelle, also alle Einträge, bei denen im Feld Zeigen eine 1 notiert wurde. Diese Be-

      Daten erst einmal ausgeben schränkung erreichen wir mit der WHERE-Klausel WHERE Zeigen = 1. Wir benötigen diese Abfrage für unsere Variable $zeilen, also für die Ausgabe der Gesamtzahl der (anzuzeigenden) Einträge. Die zweite, längere Zeile $sql2 = "SELECT * FROM guestbook WHERE Zeigen = 1 ORDER BY id DESC LIMIT 0, 4"; dient lediglich für die Anzeige der freigeschalteten Daten. Dabei soll zum einen absteigend nach dem Feld id sortiert werden. Das gelingt mit ORDER BY id DESC und auf diese Weise stehen die neuesten Einträge zuoberst. Zum anderen wird die Ausgabe mit dem SQL-Befehl LIMIT 0, 4 (vorerst) auf die ersten vier Einträge limitiert. (Wir werden diese Werte später dynamisch anpassen für eine seitenweise Ausgabe der Daten!) Den Rest haben wir vom Prinzip her schon besprochen, doch vielleicht wunderst du dich über die Passage

      <strong>1.? Wird doch dadurch jedem Eintrag ein fett formatiertes 1. vorangestellt? Auch das dient vorerst nur als Platzhalter. In einem späteren Projektstadium soll diese Zahl mit einer Variablen natürlich dynamisch ermittelt werden! Erinnerst du dich noch an das erste Gästebuch von Kapitel 12? Auch im neuen Gästebuch arbeite ich bei der Ausgabe der Daten zum Schutz vor Scherzbolden mit der Funktion htmlspecialchars(). Diese Funktion sorgt dafür, dass spezielle HTML-Zeichen in ihre entsprechenden Entitäten umgewandelt und somit entschärft werden. Wichtig, damit dir niemand HTML-Code, CSS-Anweisungen oder sogar JavaScript-Code in dein Gästebuch schummelt! Das Kommentarfeld wird zusätzlich mit der Funktion nl2br() verschönt. Diese ebenfalls schon besprochene Funktion sorgt dafür, dass Umbrüche auch im Browser angezeigt werden. (Deshalb hatte ich dich gebeten, beim Eintragen der Daten ruhig mal den einen oder anderen Druck auf [Enter] zu wagen!)

      Homepage-Feld soll freiwillig sein? Das Feld für die Homepage soll freiwillig sein. Darauf muss ich im Ausgabeskript natürlich reagieren. Das gelingt mit folgender if-Abfrage: if (!empty($row["Home"])) { echo "(" . htmlspecialchars($row["Home"]) . ")"; }

      Nur wenn das Feld nicht leer ist, wird die Internetadresse angezeigt!

      341

      Kapitel

      Gästebuch de luxe als Datenbanktabelle

      14

      Wichtig: Datenbank-Zugangsdaten auslagern! Mehr Sicherheit, bitte! Ich rate dir: Lagere deine Zugangsdaten für die Datenbank einfach aus. Nutze dafür die schon bekannte Funktion include(). Das ist bequemer, da du auf diese Weise Benutzernamen und Passwort an zentraler Stelle speicherst und nur einmal schreiben musst. Auf der nächsten Seite zeige ich dir, wie das geht:

      >

      Erstelle eine leere Textdatei, die du zugriff.inc.php nennst. Füge folgendes Listing in diese Datei ein:

      >

      Speichere diese Datei im gleichen Ordner wie die guestbook.php. Du musst sie später mit auf den Webserver laden!

      >

      So, und nun zur guestbook.php! Binde hier den eben ausgelagerten Code ein. Lösche dazu die drei Zeilen von @mysqli_connect ... bis @mysqli_select_db ... im Quelltext der guestbook.php. Trage an der entsprechenden Stelle einfach die folgende Anweisung ein: include("zugriff.inc.php");

      >

      Teste die Ausgabe im Browser. Es dürfte sich nichts geändert haben. Vergleiche mit der Datei guestbook2.php!

      Du musst die zugriff.inc.php nicht im gleichen Ordner ablegen. Packe sie z. B. in den Ordner cgi-bin (bei manchen Dienstleistern gibt es diesen), da dieser oft von Hause aus geschützt ist! Du kannst diese Datei auch in einen separaten Unterordner legen, den du mit der auf Seite 154 erwähnten .htaccess-Datei geschützt hast. Es genügt, wenn diese .htaccess-Datei folgende beiden Zeilen enthält: order deny,allow deny from all

      342

      Gib bei include() lediglich den Pfad zu diesem Ordner an. Von außen jedoch ist der Inhalt dieses Ordners nicht zugänglich. Prüfe, ob diese .htaccess-Lösung auch bei deinem Webhoster funktioniert!

      Das Eingabeformular entsteht

      Das Eingabeformular entsteht Hast du die Funktion des Skripts erfolgreich getestet? Mit ausgelagerten Zugangsdaten? Sehr gut! Dann schreibst du nun das Eingabeformular. Dabei achten wir auf verständlichen Code, Sicherheit und – das vor allem im nächsten Kapitel – Spamschutz.

      Quelltext für das Formular Erweitere die guestbook.php zunächst um den HTML-Code für das Formular. Notiere die entsprechenden Zeilen für das Formular unterhalb der Passage

      Gästebuch auf Datenbankbasis

      und oberhalb des einleitenden Tags Dein <strong>Name:

      Homepage (freiwillig):

      Deine Botschaft:

      Ziehe vom Jahr (YYYY) den Tag (TT) ab:



      Ein Mini-CAPTCHA In diesem Formular gibt es eine Besonderheit – und zwar das Feld resultat. Hier stelle ich dem Besucher eine Rechenaufgabe. Er soll vom Jahr (z. B. 2011) den Tag (z. B. 22) abziehen und diese Zahl dann in das Feld eintragen. Wir werden im Skript überprüfen, ob er diese Rechenaufgabe gelöst hat. Das dient als Spam-Schutz. Wir hoffen, dass die automatisierten Gästebuchspammer mit dieser Aufgabe nicht fertig werden und so (erst einmal) außen vor bleiben. Und sollten sie es dann doch geschafft haben, ist das auch kein Beinbruch. Du kannst die Aufgaben aus dem CAPTCHA komplizierter machen. Erweitere sie beispielsweise um die Eingabe zusätzlicher

      343

      Kapitel

      14

      Gästebuch de luxe als Datenbanktabelle Sternchen, Rauten, Sonderzeichen usw. Und wenn selbst das nichts hilft, bleibt immer noch die Option mit der Freischaltung. Bestimme, ob die Datensätze gleich oder erst nach Begutachtung sichtbar sein sollen. Außerdem gibt es einen Button zum Zurücksetzen und einen zum Absenden des Formularinhalts. Der Submit-Button besitzt den Namen submit. Daraus wird nach dem Absenden $_POST["submit"]. Das Vorhandensein dieser Variablen werden wir später prüfen – und erst dann das Eintragen der Werte veranlassen! So wie beim Feedback-Formular aus Kapitel 8. Wie auch immer: Vergleiche erst einmal mit der Datei guestbook3.php.

      Das Formular ist fertig: Als Spamschutz dient eineinfaches CAPTCHA.

      Formulardaten erst einmal überprüfen Aber auch jetzt wird nach Klick auf den Button EINTRAGEN! nichts weiter Aufregendes passieren! Schauen wir uns deshalb endlich an, wie die Formulardaten überprüft und danach in die MySQL-Datenbanktabelle eingetragen werden. Hier zeige ich dir den entsprechenden Quellcode. Notiere ihn unterhalb der Zeile include("zugriff.inc.php"); und oberhalb von $sql1 = "SELECT * FROM guestbook WHERE Zeigen = 1";

      344

      Bekomme keinen Schreck, das ist einfacher als es auf den ersten Blick aussieht! Viele Dinge kennst du schon aus den vorhergehenden Kapiteln, vor allem aus Kapitel 8 und 12.

      Das Eingabeformular entsteht // Formular abgesendet? if (isset($_POST["submit"])) { // Formularwerte in freundlichen Variablen speichern $Name = $_POST["Name"]; $Home = $_POST["Home"]; $Kommentar = $_POST["Kommentar"]; $resultat = $_POST["resultat"]; $endwert = date("Y") - date("j"); $fehler = false; $fehlertext = "

      "; // Eingaben prüfen und Fehlertext zusammensetzen if (empty($Name)) { $fehler = true; $fehlertext .= "Der Name fehlt!
      "; } if (empty($Kommentar)) { $fehler = true; $fehlertext .= "Bitte einen Kommentar eintragen!
      "; } // CAPTCHA-Prüfung erst, wenn keine weiteren Fehler if (!$fehler && (empty($resultat) || $resultat != $endwert)) { $fehler = true; $fehlertext .= "Test nicht bestanden!"; } // Fehlertext ausgeben und Skriptabbruch if ($fehler) { echo "$fehlertext

      "; die("
      "); } else { // Eintrag in die Datenbanktabelle $datum = date("d.m.Y, H:i") . " Uhr"; $sql = "INSERT INTO guestbook VALUES ('', '$Name', '$Home', '$datum', '$Kommentar', '1')"; mysqli_query($db, $sql); // Erfolgsanzeige if (mysqli_affected_rows($db) > 0) { echo "

      Eintrag erfolgreich

      "; } else { echo "

      Eintrag nicht erfolgreich

      "; } } }

      345

      Kapitel

      14

      Gästebuch de luxe als Datenbanktabelle Wurde das Formular abgesendet? Der gesamte Bereich wird durch eine if-Abfrage umspannt. Hier prüfe ich auf das Vorhandensein von $_POST["submit"]. Und diese Variable existiert nur, wenn das Formular auch abgesendet wurde. Und nur dann soll der Eintrageteil wirksam werden. Formularwerte und weitere Variablen Danach sichere ich die Werte der vier Formularfelder Name, Home, Kommentar und resultat in freundlicheren Variablen. So finde ich z. B. $Name einfach schöner und handlicher als das sperrige $_POST["Name"]. (Natürlich hätte ich an dieser Stelle vorher noch mit isset() oder !empty() prüfen können, ob diese Variablen auch existieren. Lediglich aus Schutz vor der Manipulation von Formluarfeldern. Das spare ich mir jedoch auf Gründen der Vereinfachung.) Darunter berechne ich den Endwert für das CAPTCHA. In $endwert wird also die Differenz aus dem aktuellen Jahr und dem Tag des Monats gespeichert. Also exakt der Wert, den der Nutzer auch korrekt in das letzte Formularfeld eingeben muss. Der eigentliche Vergleich folgt dann etwas tiefer. Darunter initialisiere ich die Variable $fehler mit dem Wert false und die Variable $fehlertext mit einem einleitenden

      -Tag. Du ahnst es schon – ich verwende die gleiche Fehlerbehandlung wie im Feedbackformular von Kapitel 8. Eingaben prüfen und Fehlertext zusammensetzen Als Nächstes prüfe ich, ob die Variablen $Name und $Kommentar leer geblieben sind. Falls ja, wird $fehler auf true gesetzt und der entsprechende Fehlertext in $fehlertext abgelegt. Es ist von Prinzip her wirklich genau so wie in Kapitel 8! Lediglich das Feld für die Homepage wird im Beispiel nicht überprüft, da es freiwillig ist. Natürlich könnte und sollte ich sicher noch umfangreicher prüfen: auf Mindestlänge oder gar auf Übereinstimmung mit einem bestimmten Suchmuster. So, wie du es in Kapitel 8 schon kennengelernt hast. Darauf verzichte ich im Beispiel jedoch, um die Übersichtlichkeit des Skripts nicht (weiter) zu gefährden. CAPTCHA-Prüfung erst, wenn keine weiteren Fehler vorliegen Schau dir nun die kunstvolle if-Abfrage für die CAPTCHA-Prüfung an: if (!$fehler && (empty($resultat) || $resultat != $endwert)) {

      346

      Das Eingabeformular entsteht Sie soll erst dann zur Wirkung kommen, wenn kein weiterer Fehler vorliegt. Deshalb formuliere ich als allererste Prüfbedingung: !$fehler – die Variable $fehler darf also nicht den Wert true beinhalten. Diese Bedingung verknüpfe ich per Und-Operator (&&) mit zwei weiteren Bedingungen. Diese weiteren Bedingungen habe ich in einer runden Klammer zusammengefasst, da sie zusammengehören. Denn sie sind ebenfalls miteinander verknüpft – und zwar mit dem Oder-Operator (||) . Mit anderen Worten: Das CAPTCHA wurde dann nicht ordnungsgemäß aufgelöst, wenn das entsprechende Feld nicht ausgefüllt wurde (leer blieb) oder aber der eingegebene Wert nicht mit dem Endwert übereinstimmt. Erst wenn alle diese Teilausdrücke zusammen wahr sind, wird $fehler auf true gesetzt und der Text Test nicht bestanden in $fehlertext gesichert. Alles unklar? Probiere es einfach aus! Schicke das Formular ab, wobei du mal dieses oder jenes Formularfeld frei lässt.

      Eintragen der Daten per SQL Im else-Zweig erfolgt dann endlich der ersehnte Eintrag in die Datenbanktabelle. Zuerst speichere ich das aktuelle Datum im Format 27.04.2010, 12:35 Uhr in der Variablen $datum. Das gelingt unter anderem unter Mithilfe der schon erwähnten Funktion date() in folgender Zeile: $datum = date("d.m.Y, H:i") . " Uhr";

      Danach wird die SQL-Abfrage nach dem Schema INSERT INTO Tabellenname VALUES () zusammengesetzt und in der Variablen $sql gesichert. Dabei lasse ich das erste runde Klammernpaar hinter guestbook einfach weg. Dadurch erspare ich mir das Auflisten der Feldnamen der Datenbanktabelle guestbook. Das kann man immer dann machen, wenn man beim Eintragen der Werte im zweiten runden Klammernpaar ganz exakt die Reihenfolge einhält, in der die Feldnamen in der Datenbanktabelle stehen. Und wenn man – wie im Beispiel – auch alle Felder berücksichtigt. Einträge erst später freischalten? Apropos alle Felder – für das Feld Zeigen habe ich im Beispiel eine 1 eingetragen. Dadurch sind alle eingegebenen Datensätze sofort sichtbar. Wenn du die Datensätze jedoch erst nachträglich freischalten möchtest, notierst du an der entsprechenden Stelle statt 1 einfach eine 0: VALUES ('', '$Name', '$Home', '$datum', '$Kommentar', '0')";

      Am Ende wird die Abfrage per mysqli_query($db, $sql); ausgeführt.

      347

      Kapitel

      14

      Gästebuch de luxe als Datenbanktabelle

      Erfolgsanzeige mit mysqli_affected_rows() Doch damit nicht genug! Wir wollen dem Nutzer auch eine Statusanzeige präsentieren. Dabei hilft uns die Funktion mysqli_affected_rows($db). Als Parameter übergeben wir wieder die Datenbankkennung. Die Funktion ermittelt, wie viele Datensätze (Zeilen) von einer MySQL-Aktion betroffen waren. In unserem Fall müssen es eben mehr als 0 sein. Und genau das fragen wir auch ab: if (mysqli_affected_rows($db) > 0) {

      Hilfreiche Statusmeldung für den Anwender.

      Wenn alles geklappt hat, lautet die Meldung: Eintrag erfolgreich. Ansonsten jedoch Eintrag nicht erfolgreich. Alles klar? Diese Version findest du in der Datei guestbook4.php. Es handelt sich immerhin schon um eine funktionierende Gästebuch-Variante. Probiere es aus!

      Mit Sicherheit: Reloadsperre und Magic Quotes Sicherheit ist das große Thema! Und deshalb sorgen wir an dieser Stelle wieder vor: vor lästigen Doppeleinträgen und vor Angriffen auf die Datenbanktabelle durch Einschleusung von SQL-Code (SQL-Injection).

      Unique Index: Doppeleinträge verhindern Schutz vor Doppeleinträgen? Kein Problem! Natürlich können wir die Funktion isDouble() aus Kapitel 12 »recyceln«. Doch inzwischen arbeiten wir schließlich mit Datenbanktabellen. Und da gibt es eine elegantere Lösung – den Unique Index. Es handelt sich um einen speziellen Index-Typ, also einen Schlüssel, mit dem sich Doppeleingaben zuverlässig verhindern lassen. 348

      Mit Sicherheit: Reloadsperre und Magic Quotes Index-Typ? Schlüssel? Klar! Einen Index-Typ kennst du sogar schon – den Primärschlüssel. Dieser sorgt für die eindeutige Kennung in deiner Datenbanktabelle: jeder Wert darf nur ein einziges Mal vorkommen. Ganz ähnlich arbeitet auch der Unique Index. Er wird immer dann gebraucht, wenn außer dem Primärschlüsselfeld weitere Felder beim Schutz vor Doppeleinträgen herangezogen werden soll. Im Beispiel wollen wir die Felder Name und Kommentar gemeinsam zu einem Unique Index machen. Es soll sich also um einen Index über 2 Spalten handeln. Damit schließen wir aus, dass es zwei Einträge gibt, bei denen Name und Kommentar gleich sind. Natürlich hätten wir uns auch auf das Namefeld beschränken können. Doch das wäre unklug. Es kommt durchaus vor, dass zwei Gästebuchschreiber den gleichen Namen haben. Und das kann man ja schließlich nicht verbieten! Und so erzeugst du einen Unique Index über 2 Spalten:

      >

      Rufe die zu bearbeitende Tabelle in phpMyAdmin auf, im Beispiel die Gästebuchtabelle guestbook.

      >

      Klicke auf die Registerzunge STRUKTUR, damit du die Struktur der Datenbanktabelle bearbeiten kannst.

      >

      Rolle im rechten Fensterbereich ein Stück nach unten und schaue dorthin, wo Index über 1 Spalten anlegen steht. (Du siehst dieses Feld nicht? Klicke vorher auf den Link Details, damit dieser Bereich eingeblendet wird.) Ersetze nun die 1 durch eine 2 und klicke auf OK!

      >

      Der Bereich Neuen Index anlegen erscheint: Wähle bei INDEXTYP den Eintrag UNIQUE.

      349

      Kapitel

      14

      Gästebuch de luxe als Datenbanktabelle

      >

      Bei FELD wählst du die gewünschten Felder aus den Pull-down-Menüs aus – im Beispiel NAME und darunter KOMMENTAR.

      >

      Beim Feld Kommentar musst du noch eine Größe eingeben – und nur bei Kommentar. Der Grund liegt im Felddatentyp text. Der ist zu lang für den Index! Maximal 256 Zeichen können berücksichtigt werden, sonst gibt es eine Fehlermeldung. Tippe im Beispiel einfach eine 50.

      >

      Klicke auf SPEICHERN, keinesfalls jedoch auf OK. PhpMyAdmin präsentiert dir nun den dazugehörigen SQL-Quellcode:

      >

      Der neue Index ist fertig! Du kannst den Status darüber übrigens jederzeit unten in der Strukturansicht ablesen. Dort lässt sich dieser Schlüssel auch nachträglich bearbeiten und ggf. löschen. (Klicke vorher ggf. wieder auf den Link Details, um diese Ansicht einzublenden.)

      Nanu, das Anlegen schlägt fehl? Es gibt immer wieder eine Fehlermeldung? Dann hast du möglicherweise schon Doppeleinträge in deiner Tabelle. Lösche diese und versuche es erneut.

      350

      Und nun drücke doch einmal nach Eintragen eines Gästebucheintrags auf die Browserschaltfläche RELOAD. Richtig! Die Anzeige lautet jetzt Eintrag nicht erfolgreich. War doch gar nicht so dumm, unsere Statusanzeige mit mysqli_affected_rows()!

      Mit Sicherheit: Reloadsperre und Magic Quotes

      Schutz vor Angriffen auf die Datenbank Zeit für etwas Magie! Jetzt geht es um den Schutz unserer Datenbank vor Code-Einschleusung (SQL-Injection).

      Automatische Sicherheit dank »magic quotes«? Früher galt in der Regel: Alle Daten aus Formularen oder URL-Anhängen werden von PHP automatisch »escaped«. Mit anderen Worten: Alle einfachen bzw. doppelten Gänsefüßchen, der \ (und der Wert Null-Byte) erhalten wie von Zauberhand einen Backslash. Dafür sorgte eine Zeile namens magic_quotes_gpc = On in der php.ini. Wie gesagt – so war es früher. Das ist übrigens genau das, was auch die Funktion addslashes() erledigt: Sie setzt vor die eben genannten Zeichen einen Backslash. Wie sieht es bei dir und deinem Dienstleister aus? Rufe die Funktion phpinfo() auf, sie erzeugt ja eine PHP-Info-Seite. Suche hier den Eintrag magic_quotes_gpc.

      Per Voreinstellung war »magic_quotes_gpc« früher meist auf On gestellt – das hier ist eine ältere Abbildung.

      Die Zeichenfolge gpc bezieht sich dabei auf get, post und cookie. Diese »magische Quotierung« wirkt also auf alle Werte aus $_GET, $_POST und $_COOKIE – in unserem Beispiel natürlich auf $_POST. Die Idee dahinter war nicht so dumm. Denn derart gefährliche Zeichen müssen auf jeden Fall entwertet werden. Angreifer könnten es sonst schaffen, eigene SQL-Abfragen in die Datenbank zu schummeln. So provozieren sie Fehlermeldungen, lesen Daten aus der Datenbanktabelle aus oder löschen diese sogar. Auch das Umgehen eines Passwortschutzes kann auf diese Weise möglich sein. Im Praxisbuch findest du dazu sogar ein kleines Beispiel. Noch vor einigen Jahren haben sich viele PHPProgrammierer noch nicht viel Gedanken um Sicherheit gemacht. Sie »vergaßen«, Werte vor dem Eintragen in die Datenbanktabelle mit addslashes() zu behandeln. Deshalb erfand man die »magic quotes«. So wurden gefährliche Zeichen gleich automatisch entschärft und viele Angriffe auf die Datenbank konnten abgewehrt werden. 351

      Kapitel

      14

      Gästebuch de luxe als Datenbanktabelle

      Heute: »magic quotes« sind nicht mehr sicher genug Heute sieht das Bild anders aus. Jeder ernsthafte PHP-Programmierer weiß, dass man Daten entschärfen muss, bevor sie in die Datenbanktabelle geschrieben werden können. Weiterhin gilt: Die Funktion addslashes() ist nicht mehr leistungsstark genug. (»Magic quotes« ist ja nichts weiter, als eine addslashes()-Automatik.) Es genügt nicht, lediglich Gänsefüßchen zu entwerten. Durch Unicode sind neue Zeichen hinzugekommen, die ebenfalls gefährlich werden können. Der Zeichensatz muss also auch berücksichtigt werden! Mit anderen Worten: »magic quotes« ist ein Auslaufmodell und in PHP 6 wird diese Option abgeschafft!

      mysqli_real_escape_string() Die Lösung heißt: mysqli_real_escape_string(). Diese Funktion arbeitet gründlicher als addslashes(). Sie erzeugt eine Zeichenfolge, die du auf jeden Fall in deine SQL-Abfragen übernehmen kannst. Sie erwartet zwei Parameter, die Verbindungskennung und den umzuwandelnden String. Und sie berücksichtigt dabei den Zeichensatz der aktuellen Verbindung. mysqli_real_escape_string($db, string)

      Du möchtest den Namen »escapen«? Ersetze $Name = $_POST["Name"] durch $Name = mysqli_real_escape_string($db, $_POST["Name"]); Diese Prozedur solltest du auch den anderen drei Variablen gönnen. Der entsprechende Abschnitt sieht dann so aus: // Formularwerte escapen und speichern $Name = mysqli_real_escape_string($db, $_POST["Name"]); $Home = mysqli_real_escape_string($db, $_POST["Home"]); $Kommentar = mysqli_real_escape_string($db, $_POST["Kommentar"]); $resultat = mysqli_real_escape_string($db, $_POST["resultat"]);

      Dank dieser Funktion können Inhalte aus Formularen direkt mit INSERT INTO tabellenname VALUES ('Wert1', 'Wert2', usw.) in die Datenbanktabelle geschrieben werden, ohne dass wir uns Sorgen machen müssten. Die gefährlichen Gänsefüßchen werden auf jeden Fall maskiert – vor allem das einfache ist problematisch, da es in schädlichen SQLAbfragen eingesetzt werden kann! Und ein Herr O'Hara kann jetzt auch eingefügt werden. In der Datenbanktabelle tauchen diese »Escape-Zeichen« übrigens später nicht mehr auf, da MySQL sie vorher entfernt.

      352

      Vergleiche mit der Datei guestbook5.php, wo du diese Ergänzung bewundern kannst. Wir haben mit dieser Maßnahme einen wichtigen Schritt in Richtung Sicherheit getan!

      Mit Sicherheit: Reloadsperre und Magic Quotes

      get_magic_quotes_gpc() Unser Skript ist bisher schon ganz super. Doch was passiert, wenn die »magic quotes« bei deinem Dienstleister eingeschaltet sind? Dann werden viele Zeichen doppelt entwertet! Zumindest jedes einfache und doppelte Gänsefüßchen bekommt einen zusätzlichen Slash. Und der bleibt in der Datenbanktabelle drin! Das ist nicht sehr schön. In diesem Fall musst du die Wirkung von »magic quotes« (= addslashes()) durch ein Gegengift aufheben. Dieses Gegengift kennst du schon: stripslashes(). Erfrage einfach per Skript, wie dieser »magische Schalter« bei dir eingestellt ist. Das gelingt mit der Funktion get_magic_quotes_gpc(). Ist der Schalter on, gibt sie eine 1, bei off dagegen eine 0 zurück. Und so könnte eine derartige Abfrage aussehen: if (get_magic_quotes_gpc()) { // eingeschaltet? $Variable = stripslashes($Variable); }

      Im Beispiel sieht die Ergänzung für unser Gästebuch folgendermaßen aus: // Reaktion auf eingeschaltete magic quotes if (get_magic_quotes_gpc()) { // eingeschaltet? $_POST["Name"] = stripslashes($_POST["Name"]); $_POST["Home"] = stripslashes($_POST["Home"]); $_POST["Kommentar"] = stripslashes($_POST["Kommentar"]); $_POST["resultat"] = stripslashes($_POST["resultat"]); }

      Notiere den Block direkt unter if (isset($_POST["submit"])) {. So wird er ausgeführt, bevor die Funktion mysqli_real_escape_string() wirken kann. Vergleiche mit der Datei guestbook6.php. Du bist bis hierher nur mit Mühe und Not mitgekommen? Du bist zufrieden mit der bisherigen Gästebuch-Version? Kein Problem. Mache an dieser Stelle eine »schöpferische Pause«. Wenn du das Gästebuch in der bisherigen Fassung verwenden möchtest, änderst du zuerst die SQL-Abfrage $sql2 = "SELECT * FROM guestbook WHERE Zeigen = 1 ORDER BY id DESC LIMIT 0, 4"; wie folgt: Entferne die Passage LIMIT 0, 4, da sonst immer nur die letzten vier Einträge angezeigt werden würden! Außerdem musst du echo "

      <strong>1. " .

      streichen. Schließlich soll nicht jeder Eintrag mit 1. beginnen! 353

      Kapitel

      14

      Gästebuch de luxe als Datenbanktabelle

      Nicht alle Datensätze auf einmal Du willst weitermachen? Herzlichen Glückwunsch. Dann teste doch gleich die bisherige Version des Gästebuches. Gib ruhig noch ein oder zwei Einträge ein! Und, funktioniert alles? Klappt auch der Reload-Schutz? Super!

      Den Zähler zusammenbauen Als nächstes baust du den Zähler zusammen. Aus der sich ständig wiederholenden Anzeige 1. soll schließlich 1., 2., 3. usw. werden. Der jeweils oberste Eintrag (der neuste) bekommt dabei die 1., alle anderen werden fortlaufend nummeriert. Außerdem bereitest du die Ausgabe der ersten vier Datensätze schon vor.

      >

      Schaffe in deinem Skript etwas Platz, tippe ein paar Leerzeichen. Den entsprechenden Abschnitt habe ich hier gekennzeichnet:
      >

      Füge an dieser frei gehaltenen Stelle nun folgende Codezeilen ein: $start = 0; // Startwert setzen (0 = 1. Zeile) $step = 4; // Wie viele Einträge gleichzeitig? // Startwert verändern: if (isset($_GET["start"])) { $muster = "/^[0-9]+$/"; // reg. Ausdruck für Zahlen if (preg_match($muster, $_GET["start"]) == 0) { $start = 0; // Bei Manipulation Rückfall auf 0 } else { $start = $_GET["start"]; } } $nr = $start + 1;

      354

      Was passiert in diesem neuen Abschnitt? Ich »erschaffe« insgesamt drei weitere Variablen. Die Variable $start beherbergt den Startwert für meine SQL-Abfrage, sie wird am Anfang mit 0 initialisiert. Schließlich soll die Ausgabe mit dem 0. Datensatz beginnen – also mit der ersten Zeile. Als nächstes folgt die Variable $step. Hier lege ich fest, wie viele Einträge gleichzeitig ausgegeben werden sollen. Das können 2, 3, 4 oder auch 10

      Nicht alle Datensätze auf einmal Einträge sein! Dank dieser fabelhaften Variablen kann ich den Wert hinterher immer wieder problemlos anpassen! Zum Schluss dieses Code-Abschnitts wird die Variable $nr initialisiert. Diese Variable wird erzeugt aus dem Startwert, erhöht um 1. Da die Zählung der Datensätze bei 0 beginnt, muss für den ersten Datensatz folgerichtig eine 1 ausgegeben werden.

      Den Startwert verändern Und nun zur if-Abfrage, denn diese ist besonders wichtig für die dynamische Ausgabe der Datensätze. Diese if-Abfrage verändert schließlich den in der Variablen $start gespeicherten Startwert. Wenn der Nutzer die nächsten vier Datensätze sehen möchte, muss der Startwert auf 4 gesetzt werden. Wie erreichen wir das? Wir übergeben den Startwert mit der GETMethode. Wir hängen ihn an die URL an, und zwar nach folgendem Muster: Dateiname?start=4

      Bei unserem Gästebuch sieht das so aus: guestbook.php?start=4 Es wird also ein Parameter namens start per GET übergeben. Die erste if-Abfrage prüft also, ob dieser Parameter vorhanden ist: if (isset($_GET["start"])) {

      Dann muss aus Sicherheitsgründen jedoch noch ein zweiter if-Test gefahren werden! Wir prüfen danach mit einem regulären Ausdruck, ob es sich wirklich um einen Zahlwert handelt. Schließlich lassen sich URL-Parameter von Witzbolden schnell mal verändern. Da derart gefälschte Werte keinesfalls vom Skript weiterverarbeitet werden dürfen, setzt unser »Filter« den Wert von $start bei Manipulationsversuchen auf 0. Natürlich wäre auch ein Skriptabbruch mit die() denkbar. Aber in diesem Fall genügt es, bei Manipulationsversuchen einen Standardwert zu setzen. Nur wenn der aus $_GET["start"] übernommene Wert koscher ist, greift der else-Zweig. Dort wird dann endlich der Wert des Parameters ausgelesen und in $start abgelegt: $start = $_GET["start"];

      Push it to the LIMITs Weiter geht’s im Text. Die eben mühselig festgelegten Variablen nützen dir überhaupt nichts, wenn du sie nicht an den richtigen Stellen einbaust! Wage dich zuerst an die SQL-Abfrage $sql2. Ändere diese Zeile: $sql2 = "SELECT * FROM guestbook WHERE Zeigen = 1 ORDER BY id DESC LIMIT 0, 4";

      355

      Kapitel

      14

      Gästebuch de luxe als Datenbanktabelle wie folgt: $sql2 = "SELECT * FROM guestbook WHERE Zeigen = 1 ORDER BY id DESC LIMIT $start, $step";

      Die SQL-Anweisung LIMIT kennt zwei Parameter. Die erste Ziffer gibt an, ab welchem Datensatz die Daten ausgegeben werden. Die zweite Ziffer legt die Zahl der gewünschten Datensätze fest. Raffiniert, nicht wahr?

      Wo bleibt die Nummerierung? Na klar, du musst natürlich auch die Nummerierung anpassen. Ändere also noch folgende Zeile: echo "

      <strong>1. " .

      in echo "

      <strong>$nr. " .

      Außerdem musst du kurz vor dem Ende der while-Schleife darauf achten, dass die Variable $nr um eins erhöht wird. Füge also über dieser Zeile } // while Ende

      folgende ganz kurze Zeile ein: $nr++;

      Jetzt sieht die while-Schleife insgesamt so aus. Alle »Umbaumaßnahmen« habe ich hervorgehoben:

      356

      while($row = mysqli_fetch_assoc($result2)) { echo "

      <strong>$nr. " . htmlspecialchars($row["Name"]) . " "; if (!empty($row["Home"])) { echo "(" . htmlspecialchars($row["Home"]) . ")"; } echo "
      --> schrieb am " . "<strong>" . $row["Datum"] . ":

      " . "

      " . nl2br(htmlspecialchars($row["Kommentar"])) . "


      \n"; $nr++; } // while Ende

      Links für die seitenweise Ausgabe Verschrieben? Kein Problem! Den bisherigen Stand findest du auch in der Datei guestbook7.php! Ausprobieren lautet die Devise, ausprobieren! Zum einen wirst du merken, dass die Datensätze nun automatisch durchgezählt werden. Zum anderen solltest du auch versuchen, die nächsten vier Datensätze auszugeben. Tippe statt guestbook.php einfach guestbook.php?start=3 und beobachte die Datenausgabe. Es funktioniert natürlich nur, wenn du schon mindestens vier Datensätze eingetragen hast!

      Ein Startwert von 3 blendet als obersten Eintrag den vierten Gästebucheintrag ein.

      Links für die seitenweise Ausgabe Du bist schon weit gekommen, aber noch nicht fertig! Schließlich kannst du vom Nutzer kaum erwarten, dass sie oder er jedes mal die Zeichenfolge ?start=4 oder ?start=8 an die Webadresse hängt. Das ist nicht sonderlich komfortabel, das musst du zugeben. Eine schicke Linkleiste muss her, und zwar nach dem Muster [1-4] [5-8] [9] usw. Wenn sie oder er z. B. auf [5-8] klickt, wird die Seite noch einmal aufgerufen. Diesmal jedoch mit dem Anhängsel ?start=4! Auf diese Weise können die entsprechenden Datensätze eingeblendet werden. Kein Problem? Mit einer Schleife lässt sich das ganz einfach lösen? Einverstanden, hier sind die Lösungen: 357

      Kapitel

      14

      Gästebuch de luxe als Datenbanktabelle

      For-Schleife, die erste! Schau dir zuerst unsere einfache Variante an. Sie funktioniert, ist aber noch nicht ganz perfekt. Ergänze dafür einfach den entsprechenden Code. Setze ihn zwischen diese beiden Zeilen: $result2 = mysqli_query($db, $sql2); Neuen Code hier einfügen; echo "

      Bisherige Einträge

      ";

      Und so sieht der entsprechende Code nun aus: for ($i = 0; $zeilen > $i; $i = $i + $step) { $anf = $i + 1; $end = $i + $step; echo "[ $anf-$end ] "; }

      Ich arbeite mit einer for()-Schleife. Die Zählvariable $i wird mit 0 initialisiert, $i = 0. Diese Zählvariable soll nach jedem Durchgang um $step erhöht werden ($i = $i + $step), also im Beispiel um 4. Die Bedingung lautet $zeilen > $i, die Zählvariable $i muss kleiner bleiben als die Gesamtzahl der Zeilen unserer Datenbanktabelle ($zeilen). Mit anderen Worten: Erst wenn es 5 Gästebucheinträge gibt, wird die Schleife ein zweites Mal durchlaufen! Innerhalb der Schleife werden die Variablen $anf und $end initialisiert und nach Durchlaufen der Schleife natürlich aktualisiert. Das Ausgeben des Hyperlinks selber erfolgt im »echo-Teil«. Hier entsteht ein »Verweis auf sich selbst« mit dem »Anhängsel« ?start=$i. Die Zählvariable $i sorgt also dafür, dass hier dynamisch der richtige Wert steht. Schließlich ist $i bei ersten Durchlauf der Schleife noch 0. Beim zweiten Durchlauf beträgt der Wert 4, dann 8 usw.. Die eckigen Klammern und das zusätzliche Leerzeichen wurden lediglich aus optischen Gründen eingefügt. Wenn dein Gästebuch reich gefüllt ist, werden schließlich unzählige dieser Links nebeneinander aufgereiht. Was glaubst du eigentlich, warum ich die Variablen in dieser Passage $anf-$end einfach so aneinanderreihe? Woher weiß der PHP-Interpreter, wo die Variable $i aufhört? Warum gibt es ebenfalls keine Probleme bei diesem $anf$end-Gebilde? Ganz einfach! Die Zeichen >, <, ?, =, \ oder der Bindestrich – dürfen in Variablen nicht vorkommen. Sie sind das Stopp-Signal. 358

      Links für die seitenweise Ausgabe Diese Version findest du in der Datei guestbook8.php.

      Die zweite Version der for-Schleife Probiere es aus! Es funktioniert. Allerdings besitzt diese Version noch einige Schönheitsfehler. Einen davon zeige ich dir in der nächsten Abbildung.

      Zwar sind es nur sieben Einträge, die Links suggerieren allerdings acht!

      Ganz unbeeindruckt von der tatsächlichen Zahl der Gästebucheinträge zeigt das Skript immer [1-4] oder [1-4] [5-8] oder [1-4] [5-8] [9-12] usw. usf. – je nachdem, wie voll dein Gästebuch ist. Eine etwas feiner abgestimmte Anzeige nach dem Motto [1-2] oder [1-4] [5] oder [1-4] [5-7] erreichst du dagegen mit folgender, erweiterter Schleifenkonstruktion: for ($i = 0; $zeilen > $i; $i = $i + $step) { $anf = $i + 1; $end = $i + $step; if ($end > $zeilen) { $end = $zeilen; } if ($anf == $end) { echo "[ $end ] "; } else { echo "[ $anf-$end ] "; } }

      Hinzugekommen sind zwei if-Abfragen innerhalb der Schleife. Diese sorgen stets für die richtige Feinabstimmung. Nehmen wir gleich das erste if: Wenn der Wert von $end die tatsächliche Anzahl der Zeilen überschreitet,

      359

      Kapitel

      Gästebuch de luxe als Datenbanktabelle

      14

      wird der Variablen $end kurzerhand der wahrheitsgetreue Wert aus $zeilen verpasst. Das sorgt für eine Anzeige wie [1-3] statt [1-4]. Das zweite if beseitigt einen weiteren Schönheitsfehler. Angenommen, es gibt genau fünf Gästebucheinträge. Ohne dieses if würde die Anzeige wie folgt aussehen: [1-4] [5-5]. Hier entspricht der Anfangswert $anf also dem Endwert $end! Doch zwei gleiche Werte sehen recht ungeschickt aus. In diesem Fall genügt die Ausgabe eines Wertes. Das zweite if mit elseZweig führt also zu der Anzeige [1-4] [5] bei fünf Gästebucheinträgen.

      Schönheitsfehler beseitigt – dein Gästebuch ist damit im Prinzip schon fertig!

      Schwirrt der jetzt der Kopf? Du findest den aktuellen Stand auch in der Datei guestbook9.php!

      Adminbereich für den Gästebucheigner? Du möchtest Einträge löschen? Oder neu eingetragene Datensätze freischalten? Das erledigst du bequem und komfortabel mit phpMyAdmin! Schließlich bietet dir dieses Tool den perfekten Überblick über den Inhalt deiner Datenbanktabellen.

      360

      Natürlich ginge es noch komfortabler. Ich denke an einen Login-Bereich für den Administrator. Logge dich direkt in dein Gästebuch ein. Schalte Einträge von hier aus frei oder lösche sie direkt. Das nötige Know-how vermittle ich dir im Nachfolgeband »PHP und MySQL Praxisbuch für Kids«. Dort verwendest du Cookies im Zusammenhang mit der für diesen Zweck bestens geeigneten Session-Technologie. Ich zeige dir das Prinzip an mehreren Praxisbeispielen – vom Fotoweblog bis hin zum ausgewachsenen Content-Ma-

      Schlussbemerkung nagement-System. Erste Anregungen bekommst du aber auch schon im nächsten Kapitel. Dort verwendest du die Cookies für einen Einloggbereich.

      Dank phpMyAdmin wird das Bearbeiten und Löschen der Beiträge zum Kinderspiel.

      Schlussbemerkung Was für ein Projekt! Konntest du Schritt für Schritt folgen? Wenn ja, beglückwünsche ich dich dazu. Wenn nicht, lass’ den Kopf nicht hängen und versuche es noch einmal. Und auch wenn du nur einen »Teilabschnitt« bewältigst hast, ist das schon ein kleiner Erfolg! Und bilde dir nur nicht ein, ich hätte das Ding an einem Nachmittag »zusammengehustet«. Habe ich nicht! Manchmal grübele ich Tage an Skripten wie diesem, und irgendwann mitten beim Spazierengehen fällt mir noch eine Lösung ein! Apropos Spazierengehen – das wäre jetzt wirklich eine gute Idee! Denn danach habe ich noch ein paar Fragen an dich. Und ein paar Aufgaben.

      Zusammenfassung 0 Du weißt, wie eine Gästebuch-Datenbanktabelle aussehen muss und kannst sie in die Praxis umsetzen. 0 Du nutzt den SQL-Befehl LIMIT, wenn du nur eine bestimmte Anzahl an Datensätzen ausgeben möchtest. 0 Du weißt, dass du ein umfangreiches Projekt stets in Teilschritten umsetzen solltest. Prüfe den Code nach jedem neuen Teilschritt. Erstelle von jedem »Modul« eine Sicherheitskopie. 361

      Kapitel

      14

      Gästebuch de luxe als Datenbanktabelle 0 Du verwendest die Funktion include(), mit der du Teile des Codes extern auslagerst. Im Beispiel sind es die Zugangsdaten für deine SQLDatenbank. Lege sie in einer Datei namens zugriff.inc.php ab. 0 Du nutzt die Technik, einer URL einen zusätzlichen Parameter zu übergeben. Wenn du z. B. ?start=0 an die URL anhängst, erhältst du die Variable $_GET["start"] und kannst den entsprechenden Wert im Skript auslesen und darauf reagieren. 0 Auf diese Weise realisierst du das seitenweise Abrufen der Gästebucheinträge. Du übergibst den Startwert, der dem Datensatz entspricht, welchen du einblenden möchtest.

      Ein paar Fragen … 1. Warum sollte ausgelagerter Code auf .php enden und nicht z. B. auf .txt? 2. Warum sollte man die Zugriffsdaten für die SQL-Datenbank in einer include-Datei auslagern? Welche Vorteile bringt das? 3. Mit welchem SQL-Befehl sorgst du für eine absteigende Anzeige? 4. Mit welchem SQL-Befehl kannst du die Ausgabe der Datensätze »limitieren«?

      … und ein paar Aufgaben 1. Klar, das Gästebuch ist noch nicht perfekt. Sorge zuallererst dafür, dass die Daten nach Absenden nicht aus den Formularfeldern gelöscht werden. Das ist vor allem dann ärgerlich, wenn der Nutzer ein Feld vergessen hat. Wie das geht, habe ich dir ja schon in Kapitel 8 gezeigt. 2. Gib eine Mindestlänge für die Felder Name und Kommentar vor. Der Name soll mindestens 3 und der Kommentar mindestens 10 Zeichen lang sein. Mache den Nutzer im Zweifelsfall darauf aufmerksam, dass die entsprechende Eingabe nicht lang genug ist. 3. Für Profis: Baue das Skript so um, dass beim Anzeigen der Homepage automatisch ein Hyperlink erzeugt wird. Die Zieladresse soll sich in einem neuen Browserfenster öffnen.

      362

      4. Die Schwierigkeit bei diesen Links besteht darin, den Nutzer zu zwingen, seine Adresse mit http:// einzugeben. Überprüfe also auch das Formularfeld für die Homepage. Der Test soll jedoch erst anschlagen,

      … und ein paar Aufgaben wenn das Home-Feld nicht leer ist. Das Feld ist schließlich freiwillig! Dann jedoch soll geprüft werden, ob die Eingabe am Anfang http:// enthält und ob sie keine Umlaute und Sonderzeichen besitzt. (Die seltenen Umlautadressen wollen wir im Beispiel nicht zulassen!) Folgender regulärer Ausdruck prüft, ob eine Zeichenfolge mit den eben formulierten Bedingungen übereinstimmt: "|^http://[a-zA-Z0-9-_.]+$|"

      Als Begrenzer kommen diesmal übrigens senkrechte Striche zum Einsatz. Der Grund: Das http:// besitzt schon zwei Schrägstriche. Teste auf Übereinstimmung mit diesem Suchmuster. Gib bei Misserfolg folgenden Text aus: Deine Webadresse ist nicht korrekt! Bitte vergiss nicht das http:// am Anfang und vermeide Umlaute und Sonderzeichen! 5. Sorge dafür, dass dir das Gästebuch-Skript nach jedem Eintrag eine E-Mail schreibt. Diese E-Mail soll dir auch das Eintragsdatum, den Namen, ggf. die Homepage und den Kommentar des Nutzers zuschicken. Orientiere dich an der Abbildung. Tipp: Die Mail muss verschickt werden, wenn das Eintragen erfolgreich war.

      Hinter dieser Aufgabe steckt eine zusätzliche Schwierigkeit. Es kann Probleme geben beim Versenden der E-Mail, wenn die Seite als UTF-8 kodiert ist. Wir haben uns darüber ja schon im Kapitel 8 unterhalten. Kodiere die Seite also als ISO-8859-1. Sorge außerdem dafür, dass der Zeichensatz der Datenbankverbindung ebenfalls ISO-8859-1 lautet. (Dafür musst du lediglich eine Zeile in der zugriff.inc.php entfernen!) 6. Verbessere den CAPTCHA-Test. Der Nutzer soll vor der berechneten Zahl fünf Sternchen und danach eine Raute # und eine Tilde ~ tippen. Jeweils ohne Leerzeichen. Das sieht im Zweifelsfall so aus: *****1998#~

      363

      15 Weblog für Kids: »Das Mini-CMS« Hast du Lust auf ein eigenes Weblog? Wolltest du immer schon wissen, wie man ein kleines News-System programmiert? Dann bist du in diesem Kapitel genau richtig! Ich zeige dir, wie du ein attraktives und einfach zu handhabendes »Web-Tagebuch« erstellst. Auch wenn du kein »Blogger« bist, sollst du auf deine Kosten kommen. Dann nennst du dein Projekt einfach CMS wie Content Management System. Das Beispiel lässt sich für viele Zwecke einsetzen. Denn auf den Inhalt kommt es an, auf den Content. In diesem Kapitel zeige ich dir, wie du $ das Mini-CMS planst und die entsprechende Datenbanktabelle erstellst $ deine Seite mit HTML und CSS attraktiv gestaltest $ mit der »Heredoc-Syntax« HTML noch einfacher in PHP eingliederst $ einen per Cookie gesicherten Passwort-Zugang erstellst $ die Anzeige der Einträge auf eine bestimmte Länge kürzt $ einen Link zu Archiv-Beiträgen angibst Bei diesem Projekt greife ich unter anderem auf die Erfahrungen aus dem Gästebuchprojekt von Kapitel 14 zurück. Aber auch die Cookies rufen wir uns in Erinnerung. Ganz wichtig: Auch hier erstellst du den Code wieder Schritt für Schritt. Auch hier steht Projektarbeit im Vordergrund! 365

      Kapitel

      15

      Weblog für Kids: »Das Mini-CMS«

      Pflichtenheft: Zuerst planst du das Projekt Wie immer bei »großen Projekten« muss geplant werden. Damit du weißt um was es geht, präsentiere ich dir das fertige Ergebnis in einer Abbildung.

      Content managen: Erst nach Klick auf ALLES LESEN erscheint der komplette Eintrag.

      Anforderungen an das System Unser System soll folgende Anforderungen erfüllen: 0 Anzeigen der aktuellen Einträge zuoberst, »Archiv-Link« für ältere Einträge. 0 Kürzen der Anzeige, wenn eine bestimmte Zeichenzahl überschritten wird. In diesem Fall wird zusätzlich ein Link bereitgestellt, über den der komplette Beitrag aufgerufen werden kann. 0 Anbringen eines ZURÜCK-Links, damit man vom kompletten Beitrag wieder zurück zur Hauptseite navigieren kann. 0 Anbringen eines HOME-Links auf jeder Seite. 366

      0 Notieren eines NACH OBEN-Links, der vom Seitenende zurück zum Seitenanfang führt.

      Pflichtenheft: Zuerst planst du das Projekt 0 Bequeme Eingabe der Beiträge durch ein per Passwort geschütztes Eingabeformular. Unauffälliges Login am Seitenfuß. 0 Zulassen von HTML-Code im Beschreibungstext, damit z. B. auch Grafiken eingefügt werden können. 0 Nicht zuletzt schickes Aussehen mit Rahmen, Hintergrundgrafik und fester Breite. Natürlich spielt auch bei diesem Projekt die Sicherheit eine große Rolle. Zum Glück ist ein Weblog längst nicht so kritisch wie ein Gästebuch. Vor allem beim Eingabeformular können wir den Aufwand begrenzen! Im Idealfalle bist du der alleinige Urheber der Einträge. Oder du beziehst ein paar engere Freunde in dein Tagebuchprojekt mit ein. Die Funktion htmlspecialchars() zum Unterdrücken von HTML-Code benötigst du in diesem Fall ebenso wenig wie eine Reload-Sperre. Schließlich sollen HTML-Einträge erlaubt sein. Schon deshalb wäre htmlspecialchars() hinderlich, da diese Funktion alle HTML-Tags schließlich »entschärft«. (Wenn der Tagebuchschreiber jedoch ausnahmsweise HTML-Tags darstellen möchte, muss sie oder er die spitzen Klammern umschreiben; < wird z. B. zu $lt; und > zu >.)

      Und wieder grüßt die Datenbanktabelle Auf los geht’s los! Die Voraussetzungen für unsere Datenbanktabelle sind ganz ähnlich wie beim Gästebuch. Für die Tabelle schlage ich den Namen cms vor. Als Feldnamen verwendest du id (Primärschlüssel), Name (Name des Weblogbesitzers), Headline (für die Überschrift), Datum (automatischer Datumsstempel) und Eintrag für den eigentlichen Text. Statt ausschweifender »Felddatentyp-Diskussionen« zeige ich dir lieber gleich den entsprechenden SQL-Code. Richte die Datenbanktabelle mit phpMyAdmin ein: CREATE TABLE cms ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, Name VARCHAR(35), Headline VARCHAR(80), Datum VARCHAR(30), Eintrag TEXT ) DEFAULT CHARACTER SET utf8;

      367

      Kapitel

      Weblog für Kids: »Das Mini-CMS«

      15

      Auch hier bitte ich dich, schon im Vorfeld einen oder zwei Einträge zu erstellen. Genau wie beim Gästebuch erwarte ich für das Datum das Format: 0 24.04.2010, 16:00 Uhr Denke dir außerdem für jeden Eintrag eine sinnvolle Überschrift aus. Verwende bei mindestens einem Eintrag ruhig einen etwas längeren Text. Du kannst dabei sogar – wenn du möchtest – mit HTML-Code arbeiten. Dadurch lassen sich beispielsweise Aufzählungen erzeugen, Passagen hervorheben oder sogar Grafiken einfügen. (Wenn du Grafiken einfügst, fügst du natürlich nur den Verweis auf die Grafik ein. Die Abbildung lädst du dann separat mit auf den Server. Es ist nicht sinnvoll, Abbildungen in Datenbanktabellen zu sichern!) An dieser Stelle ein ganz wichtiger Tipp! Erstelle für dieses Projekt einen separaten Ordner. Ich schlage den Namen cms vor. Lege diesen Ordner unter dem Ordner htdocs ab. Für diesen separaten Ordner gibt es mehrere Gründe: Zum einen wird es bei einigen der Dokumente Namensgleichheit mit schon erstellten Dateien geben. Das muss vermieden werden, damit die alten Dateien nicht aus Versehen überschrieben werden. Zum anderen soll die Startdatei des Blogs index.php heißen. Der Trick dabei: Der Apache-Webserver ist so eingestellt, dass eine Datei namens index.php (ebenso wie index.html) automatisch als Startdatei aufgerufen wird. Du musst nur den jeweiligen Ordner aufrufen. Du tippst im Beispiel also lediglich: 0 http://localhost/cms und schon erscheint dein Weblog in Gestalt der index.php vor dir!

      Schickes Design: Die Ausgabe aller Daten Als nächstes bereitest du die Seite so weit vor, dass die Daten ausgegeben werden. Und zwar so attraktiv wie möglich! Ich zeige dir den ersten Stand unserer index.php vorab. Danach besprechen wir alle Einzelheiten ganz in Ruhe.

      368

      Schickes Design: Die Ausgabe aller Daten

      Der Quellcode im Überblick Wenn du keine Lust zum Abtippen hast, kannst du dir diese Version auch von der CD »holen«. Sie steckt im Pfad kapitel15/cms_version1. Unser Webtagebuch <meta http-equiv="content-type" content="text/html; charset=utf-8">

      Unser Webtagebuch:

      [ Home ]
      Anzahl der Einträge: $zeilen

      \n";

      369

      Kapitel

      15

      Weblog für Kids: »Das Mini-CMS« // while-Schleife Anfang while ($row = @mysqli_fetch_assoc($result2)) { $Eintrag = nl2br($row["Eintrag"]); // Einträge anzeigen echo "

      $row[Headline]

      \n" . "

      $Eintrag

      " . "
      <small>eingetragen von $row[Name] " . "am <strong>$row[Datum]


      \n"; } // while-Ende // Link zu älteren Einträgen einblenden $start = $start + $step; echo "

      "; if ($start < $zeilen) { // if-Anfang echo "[ << Ältere Einträge ]"; } echo "[ nach oben ]

      \n"; mysqli_close($db); ?>


      Hier noch ein schneller Tipp zur Notation! Viele Autoren gliedern ihren Quellcode durch Einrückungen. Untergeordnete Strukturen, z. B. der Titel oder untergeordnete if-Abfragen usw. werden dabei durch Druck auf die [ÿ]-Taste oder mit Leerzeichen eingerückt. (Ich empfehle Leerzeichen!) Dadurch wird der Code besser lesbar, besser verständlich und klarer gegliedert. Auf die Programmausführung hat das jedoch keine Auswirkung. Auch der Autor dieses Buches verwendet diese Technik. Er gliedert zusätzlich noch durch das Einfügen von Leerzeilen vor besonders wichtigen Passagen. Denn auch leere Zeilen stören den Programmablauf nicht und sorgen ebenfalls für einen besseren Überblick. Wie man PHP-Code nun am besten einrückt, verraten wir dir natürlich auch. Schaue auf die CD, in den Pfad dokumente\code_einrueckung. Lies die Datei code_einrueckung.pdf. Dort findest du die wichtigsten Regeln für das Schreiben von übersichtlichem PHP-Code. Der Autor folgt dabei dem sogenannten PEAR-Standard, den er übrigens im Nachfolgebuch ausführlich erläutert. 370

      Schickes Design: Die Ausgabe aller Daten

      Das Auge isst mit: Gestalten mit Style Sheets Zuerst fangen wir ausnahmsweise nicht mit Programmierung an. Es geht um die Gestaltung! Schaue dazu in die Zeile oberhalb des Ausschalttags. Hier bindest du eine externe Style-Sheet-Datei namens weblog.css ein:

      Im Prinzip handelt es sich ja um unsere phpkid.css. Allerdings habe ich sie weblog.css genannt, erweitert und im Unterordner css abgelegt. Und nun schaue doch einmal in diese CSS-Datei weblog.css hinein! Hintergrundgrafik einbinden Zuerst habe ich die Stilregel für body erweitert, also die Gestaltungsvorschrift für das gesamte Dokument: body { font-family: Verdana, Arial, Helvetica, sans-serif; background-image: url('bgyellow.gif'); }

      Neu hinzugekommen ist die zweite Zeile. Diese bindet eine Hintergrundgrafik namens bgyellow.gif in die Seite ein. Diese Grafik erzeugt das durchgehende Linienmuster. Du findest die Grafik übrigens auf der CD zum Buch. Sie liegt im Ordner css. Feste Breite, Rahmen und Innenabstand Das sieht doch bis hierhin schon einmal nicht schlecht aus, oder? Aber das ist noch nicht alles. Ich arbeite mit einem weiteren Gestaltungstrick. Ich kleide den gesamten Inhalt – wie schon beim Gästebuch – in einen DIVContainer ein. Das einleitende
      sieht so aus:
      . Es besitzt also eine id und auf die kann ich mich in der CSS-Datei beziehen. Und zwar so: /* DIV-Container mit der id wrapper gestalten */ #wrapper { width: 600px; /* Breite 600 Pixel */ border: solid 1px; /* dünner Rahmen drumherum */ background-color: white; /* Hintergrundfarbe weiß */ padding: 10px; /* Innenabstand 10 Pixel */ }

      371

      Kapitel

      15

      Weblog für Kids: »Das Mini-CMS« Diesmal begnüge ich mich jedoch nicht mit der Angabe der Breite. Mit Hilfe von CSS verpasse ich meinem Weblog einen durchgehenden schwarzen Rand und die Hintergrundfarbe Weiß. Dadurch hebt sich der eigentliche »Schreibbereich« von der Hintergrundgrafik ab. Damit du diese Stilregel besser verstehst, habe ich alle Erklärungen in Kommentare eingebunden: /* */. Mehr zu den tollen Möglichkeiten von CSS erfährst du – wie schon erwähnt – in »CSS für Kids« von David Sigos.

      Sinnvolle Ordnerstruktur: Die index.php liegt im Ordner cms, die CSS-Datei und die Hilfsgrafik wurden in den Ordner css ausgelagert. Der Ordner edit enthält die gut geschützten Zugangsdaten.

      Schaue es dir an! Damit sieht dein Weblog doch zumindest von der Optik her schon ganz prima aus! Und eine exakte Breite besitzt es außerdem. Das ist auch deshalb wichtig, damit die Einträge nicht ins Endlose quillen.

      Datenbankabfrage: Der MySQLTeil im Überblick Widmen wir uns nun dem Rest des Dokumentes. Gleich schaust du dir die Datenbankabfrage an. Es ist gar nicht schwer, denn die meisten Details kennst du schon. Doch zuvor gucken wir auf die Zeilen, die sich oberhalb dieser Abfrage befinden. 372

      Blättere beim Lesen immer wieder zu meinem Beispiel-Quellcode zurück!

      Datenbankabfrage: Der MySQL-Teil im Überblick

      Zugriffsdaten und Administrationsdatei Ganz oben binde ich per include("edit/zugriff.inc.php"); die ausgelagerten Zugangsdaten für meine Datenbank ein. Diesmal liegt die zugriff.inc.php im Unterordner edit. Diesen Ordner habe ich zusätzlich mit einer .htaccess-Datei vor Zugriffen von außen geschützt. Safety first – Sicherheit geht eben vor! (Wenn dein Hoster dabei mitspielt.) Und so sieht die aufgemotzte zugriff.inc.php aus:

      Neu hinzugekommen sind die Variablen $user und $pass. Dort sichere ich den Nutzernamen und das Passwort für deinen Zugriff auf unser Weblog. Wähle vor allem dein Passwort mit Bedacht! Das Passwort habe ich möglichst sicher gewählt – ich empfehle eine Kombination von Buchstaben und Zahlen mit gemischter Groß- und Kleinschreibung. Es gilt die Regel: möglichst lang, aber gut zu merken. Auch die nächsten drei PHP-Zeilen zählen zu den Vorbereitungen für einen späteren Projektstand. Hier binden wir ein weiteres Modul ein.

      Richte diese Datei namens admin.inc.php schon einmal ein und lege sie in den gleichen Ordner. Notiere dort lediglich Folgendes – der eigentliche Inhalt kommt später.

      Später wird diese Datei den Code für das Eingabeformular aufnehmen.

      373

      Kapitel

      15

      Weblog für Kids: »Das Mini-CMS«

      Home-Link Und nun schaue dir folgende Zeile an – sie beherbergt den Home-Link:
      [ Home ]


      Dieser Link wird links oben auf der Seite platziert und erscheint damit auf jeder Seite. Dadurch kann der Besucher jederzeit die Startseite aufrufen (index.php) und sieht so wieder die neusten Einträge.

      Die Parameter $start und $step Die darauffolgenden Zeilen haben wir vom Prinzip her schon beim Gästebuch von Kapitel 14 besprochen. Der Wert $start dient zum Festlegen des ersten anzuzeigenden Datensatzes. Dieser Wert wird mit 0 initialisiert. Die Variable $step nimmt die Zahl der gleichzeitig anzuzeigenden Einträge entgegen. Im Beispiel habe ich mich für 2 entschieden. Der Wert $start wird nach Klick auf einen Link namens Ältere Einträge stets um den Wert $step erhöht, im Beispiel also um 2. Diese »Dynamik« erfolgt – du ahnst es schon – wieder durch die Übergabe eines URLParameters. Der Wert wird durch ?start=Zahl übergeben und mit $_GET["start"] ausgelesen. Auch hier gibt es wieder den obligatorischen Check, ob es sich um eine Zahl handelt. Dafür dient der ebenfalls schon besprochene reguläre Ausdruck. Aus ursprünglich 0 wird nach Klick auf den Link eine 2. Auf diese Weise können die 2 nächstälteren Datensätze eingeblendet werden. Alles funktionier vom Prinzip her also genauso wie beim Gästebuch aus Kapitel 14.

      SQL-Abfragen Danach kommen die SQL-Abfragen. Es sind ebenfalls sinngemäß die gleichen wie beim Gästebuch. $sql1 = "SELECT * FROM cms"; $sql2 = "SELECT * FROM cms ORDER BY id DESC LIMIT $start, $step";

      Auch hier ermittle ich mit der ersten Abfrage (Variable $sql1) die Anzahl aller Datensätze. Die zweite Abfrage jedoch ($sql2) liest beim ersten Aufruf nur die ersten 2 Datensätze ein. Die 2 – das ist schließlich der voreingestellte Wert aus $step. 374

      Darunter gebe ich schon einmal die Gesamtzahl der Einträge aus. Das Ganze wird wieder in einer Variablen namens $zeilen gespeichert. Diese Vari-

      News von Gestern? Ältere Einträge anzeigen! able werden wir für unsere Navigationsleiste noch benötigen. Die eigentliche Ausgabe der Daten erfolgt dann innerhalb unserer berühmten whileSchleife. Das Prinzip ist das gleiche wie beim Gästebuch: // while-Schleife Anfang while ($row = @mysqli_fetch_assoc($result2)) { $Eintrag = nl2br($row["Eintrag"]); // Einträge anzeigen echo "

      $row[Headline]

      \n" . "

      $Eintrag

      " . "
      <small>eingetragen von $row[Name] " . "am <strong>$row[Datum]


      \n"; } // while-Ende

      Zuerst wird die Überschrift ausgegeben, dann der eigentliche Text des Eintrags. Name und Datum wiederum werden diesmal unter dem Eintrag angezeigt, und zwar in kleiner Schrift. Dafür sorgt das Tag-Paar <small>.

      News von Gestern? Ältere Einträge anzeigen! Schaue nun zum Code-Abschnitt unterhalb von Link zu älteren Einträgen einblenden. Dieser spezielle Link erscheint immer dann, wenn weitere Einträge »im Archiv schlummern«. Durch Klick auf diesen Link holst du die – im Beispiel sind es zwei – jeweils nächstälteren Beiträge »aus dem Archiv«. // Link zu älteren Einträgen einblenden $start = $start + $step; echo "

      "; if ($start < $zeilen) { // if-Anfang echo "[ << Ältere Einträge ]"; } echo "[ nach oben ]

      \n";

      Die erste Programmzeile addiert zum Startwert $start erst einmal $step hinzu (im Beispiel wird 0 zu 2). Die zweite prüft nun, ob dieser neue Startwert kleiner ist als die Gesamtzahl der Einträge ($zeilen). Ist die Bedingung wahr? Gibt es also weitere Einträge, die angezeigt werden müssen? Dann wird der Link Ältere Einträge erzeugt, der die Seite neu aufruft und die nächstälteren Einträge ausgibt. Damit aber der neue Startwert bei der

      375

      Kapitel

      15

      Weblog für Kids: »Das Mini-CMS« nächsten Abfrage übermittelt wird, wird der Startwert als Parameter angehängt. Wenn der Nutzer also die nächsten zwei Werte anzeigen will, ruft der Link folgende Adresse auf: index.php?start=2

      Beim darauffolgenden Mal (falls so viele Einträge vorhanden sind), sieht der Link dann so aus: index.php?start=4

      Die nächste Zeile ist zwar nicht unbedingt nötig. Doch ich nutze gleich »die Gunst der Stunde« und füge einen Verweis »nach oben« ein. echo "[ nach oben ]

      \n";

      Wenn der Surfer auf diesen Link klickt, landet sie oder er wieder ganz oben auf der Seite. Dafür sorgt #wrapper, der interne Verweis auf dem
      Container mit der id wrapper. Probiere es aus!

      Mit Hilfe des Parameters start werden ältere Einträge eingeblendet.

      Blickst du durch? Wenn du beim Gästebuch mitgekommen bist, dürfte dir dieser Code – zumindest bis hierhin – nicht mehr so große Schwierigkeiten bereiten. (Einfach ist es aber trotzdem nicht, das gebe ich zu.) Was bedeuten die Zeichen << vor dem Text Ältere Einträge? Das ist reine Optik! Mit diesen sogenannten Entitäten erzeugst du zwei Zeichen »kleiner als«: <<, also zwei kleine Pfeile.

      376

      Damit ist das Basis-Weblog fertig! Wenn du möchtest, kannst du das Projekt an dieser Stelle abbrechen. Neue Beiträge gibst du einfach über phpMyAdmin ein. Das Ergebnis bis hierhin findest du – wie schon erwähnt – im Ordner cms_version1.

      Passwortschutz mit Cookie

      Passwortschutz mit Cookie Du willst weitermachen? Immer zu, es gibt viel zu tun! Im nächsten Schritt erstellst du den Passwortschutz, also den »Login-Bereich«. Im Beispiel soll ein Nutzer namens Hanno »eintragsberechtigt« sein. Das Passwort lautet dabei jrZuRdx_Zt5l. Wir hatten beides ja schon einige Seiten zuvor in der Datei zugriff.inc.php notiert. Für das Einloggen verwendest du ein Login-Formular mit zwei Formularfeldern. Es soll aber nicht sofort ins Auge fallen. Aus diesem Grund habe ich es dezent mit CSS formatiert. Die Formularfelder besitzen dünne, hellgraue Rahmenlinien und einen transparenten Hintergrund. Sie sind kaum zu erkennen. Der Submit-Button ist einfach nur ein Button ohne Beschriftung. Die Schriftgröße habe ich ebenfalls »runtergeregelt«. Schaue in die dritte Stilregel der Datei weblog.css – in die Regel, die mit #logform input beginnt. Die id des Formulars heißt logform.

      Das Login-Formular wird dezent am Fuß der Seite versteckt.

      Du bist mit CSS noch nicht so vertraut? Dann verweise ich erneut auf das schon erwähnte CSS-Buch aus unserer Kids-Buchreihe.

      Der Quellcode für das Formular Und hier zeige ich dir den Quellcode für das Formular. Notiere den folgenden Code zwischen dem letzten ausschaltenden
      -Tag und dem abschaltenden -Tag. Also ganz am Ende der Seite:


      377

      Kapitel

      15

      Weblog für Kids: »Das Mini-CMS« Das Formular stellt für dich inzwischen keine Hürde mehr da. Es besitzt eine id namens logform. Die ist aber nur dazu da, damit das Formular per CSS angesprochen und gestaltet werden kann. Ansonsten gibt es zwei Felder namens usr und pwd. Dort trägst du deine Kenndaten ein. Daraus werden nach Absenden die Variablen $_POST["usr"] und $_POST["pwd"] und deren Inhalt kann man wunderbar auswerten. Doch wo und wie?

      Ein Cookie als Merkwimpel Wir werten diese beiden Variablen am Anfang des Skriptes aus! Wenn die Daten korrekt sind, speichern wir den »Eingeloggt-Zustand« in einem Cookie. Das Cookie dient dann praktisch als »Merkwimpelchen«. Nur bei Vorhandensein dieses Cookies erscheint später das Eingabeformular. Nur wenn das Cookie existiert, werden die Daten in die Datenbanktabelle geschrieben. Und damit das Cookie nicht ausspioniert werden kann, bleibt es ein Sitzungscookie ohne Zeitangabe. Alles im Interesse der Sicherheit! Das Ziel ist klar, doch nun zum Weg! Schreibe den Code zum Erzeugen des Cookies. Notiere die Zeilen ganz oben im allerersten -Bereich. Setze sie ein unterhalb von include("edit/zugriff.inc.php"); ... und oberhalb von ?>. Und so sehen diese Zeilen aus: if (!empty($_POST["usr"]) && !empty($_POST["pwd"])) { if ($_POST["usr"] == $user && $_POST["pwd"] == $pass) { // Nutzer hat sich eingeloggt? Cookie erzeugen! setcookie("wlog", "we37jXp"); echo "

      [ Daten eintragen ]

      "; } }

      So kryptisch diese Zeilen auf den ersten Blick auch aussehen – sie sollten dir einleuchten. Wir prüfen, ob $_POST["usr"] und $_POST["pwd"] nicht leer sind. Ein zweiter if-Block testet auf Übereinstimmung mit Nutzernamen ($user) und Passwort ($pass) aus der zugriff.inc.php. (Daher haben wir die zugriff.inc.php auch ganz zuoberst eingebunden – damit diese Variablenwerte an dieser Stelle schon zur Verfügung stehen!) Bei Übereinstimmung setzt das Skript ein Sitzungscookie mit dem Namen wlog und dem Wert we37jXp. Warum steht der Cookie-Code eigentlich

      ganz oben? Weil ein Cookie am Seitenanfang gesetzt werden muss. Vergleiche mit dem Cookie-Kapitel 9, wenn dir das noch unklar ist! 378

      Du findest den Sachstand übrigens im Ordner cms_version2.

      So bindest du die Beiträge ein

      So bindest du die Beiträge ein Als Nächstes benötigen wir das Formular zum Eintragen der Daten. Und dabei mache ich dich noch auf ein Detail der eben erwähnten CookieZeilen aufmerksam. Es handelt sich um diesen Link: echo "

      [ Daten eintragen ]

      ";

      Er erscheint nach erfolgreichem Einloggen und sieht so aus:

      Der Link übergibt einen URL-Parameter namens form mit dem Wert 1.

      Besonders spannend ist der URL-Parameter form=1. Den lesen wir gleich aus und reagieren darauf. Und zwar mit Einblenden des Eingabe-Formulars. Dabei wird allerdings auch unser Cookie ein Wörtchen mitzureden haben. Sonst hätte das mit Sicherheit rein gar nichts zu tun! Und wo wird das Formular aufgebaut? Na in der admin.inc.php, die du schon als leere Datei vorbereitet hast!

      Quellcode der admin.inc.php Zuerst zeige ich dir den Quelltext der admin.inc.php auf einen Blick. Wenn du möchtest, kannst du gleich lostippen. Diese merkwürdige Syntax mit <<< besprechen wir danach ganz ausführlich. Hallo {$user}, nimm deinen Eintrag vor!

      <strong>Headline:


      379

      Kapitel

      15

      Weblog für Kids: »Das Mini-CMS«
      Text (<small>HTML möglich):

      FORMULARBEREICH; } // Eintrag der Daten if (isset($_COOKIE["wlog"]) && $_COOKIE["wlog"] == "we37jXp" && !empty($_POST["Headline"]) && !empty($_POST["Eintrag"])) { $Name = mysqli_real_escape_string($db, $_POST["Name"]); $Headline = mysqli_real_escape_string($db, $_POST["Headline"]); $Eintrag = mysqli_real_escape_string($db, $_POST["Eintrag"]); $datum = date("d.m.Y, H:i") . " Uhr"; $sql = "INSERT INTO cms " . "VALUES ('', '$Name', '$Headline', '$datum', '$Eintrag')"; mysqli_query($db, $sql); echo "

      [ Ausloggen ]

      "; } ?>

      Die erste if-Abfrage Die erste lange Zeile ist gar nicht so schwer wie sie aussieht. Hier wird die Variable $_GET["form"] auf Existenz geprüft – also der eben besprochene URL-Parameter. Und die existiert nur, wenn der Nutzer auf Daten eintragen geklickt hatte. Das ist aber nur der Einstieg. Auch unser eben gesetztes Cookie muss existieren und den richtigen Wert besitzen. Erst dadurch erreichen wir die bei solchen Projekten dringend notwendige Sicherheit!

      HTML in PHP mit heredoc Doch was kommt danach? Was ist das für ein merkwürdiges Gebilde? echo <<
      380

      Das ist eine ganz raffinierte Geschichte! Es handelt sich um den sogenannten heredoc-Operator, der hier eingeleitet wird. Danach kannst du ganz gewöhnlichen HTML-Code notieren, und das innerhalb von PHP!

      HTML in PHP mit heredoc Diesen Operator schaltest du ein und nach »getaner Arbeit« wieder aus. Dafür nutzt du das gleiche Schlüsselwort, das du auch beim Einschalten verwendet hast. Im Beispiel habe ich mir den Namen FORMULARBEREICH ausgedacht. Die Ausschalt-Zeile muss deshalb auch FORMULARBEREICH; lauten. Die gesamte heredoc-Syntax sieht im Beispiel also so aus: echo <<
      Das Kunstwort heredoc ist die Abkürzung für »Here Document«, »Hier beginnt das Dokument«. Im Klartext: Du kannst innerhalb dieses heredoc-Paares ganz normalen HTML-Quellcode schreiben. Das erspart das echo vor jeder Zeile! Es genügt, wenn du in der einleitenden Zeile echo <<
      Zugriff auf Variablen innerhalb von heredoc Wie kannst du innerhalb von heredoc auf PHP-Variablen zugreifen? Schließlich arbeitest du mit einem »lupenreinen HTML-Bereich«? Wie gewohnt! Betrachte den heredoc-Bereich einfach als langen String, der fast so reagiert, als stände er innerhalb von doppelten Anführungszeichen. Fazit: Notiere die Variable einfach da, wo du möchtest! (Du darfst sie sogar in einfache oder doppelte Gänsefüßchen einkleiden!) 381

      Kapitel

      15

      Weblog für Kids: »Das Mini-CMS«

      Hallo $user, nimm deinen Eintrag vor!



      In dieser Zeile wird der Name aus der Variablen $user ausgelesen und in einen »freundlichen« Begrüßungs-Satz geschrieben:

      Freundliche Begrüßung: Auch innerhalb von heredoc werden Variablen interpretiert!

      Und hier wird derselbe User in ein verstecktes Formularfeld geschrieben. Das beste: Ich kann dabei doppelte (oder einfache) Gänsefüßchen verwenden, ohne diese vorher mit hässlichen Backslashs entwerten zu müssen. Den Variablen macht das alles ebenfalls nichts aus:

      Der Sinn der Sache: Der Tagebuchschreiber muss nicht noch einmal seinen Namen eingeben. Der Name wird einfach im Formularfeld »zwischengespeichert« und danach trotzdem in die Datenbanktabelle eingetragen.

      Die Syntax zum Eintragen Du hast den Tagebucheintrag in das Formular eingegeben? Dann müssen die Daten natürlich noch abgeschickt werden. Schließlich sollen sie im Endeffekt in der Datenbanktabelle landen. Das gelingt durch Klick auf die Schaltfläche Eintrag abschicken. Damit wird das Dokument erneut aufgerufen. Für die Eingabe selbst sorgt nun der zweite Teil der Datei admin.inc.php. Dieser Teil wird schließlich nur ausgeführt, wenn die beiden Variablen $_POST["Headline"] und $_POST["Eintrag"] nicht leer sind. Also immer nur dann, wenn ein Tagebuchschreiber auch etwas in die Formularfelder eingetragen hat. Zuvor jedoch erfolgt die Prüfung, ob das besagte Cookie existiert.

      382

      // Eintrag der Daten if (isset($_COOKIE["wlog"]) && $_COOKIE["wlog"] == "we37jXp" && !empty($_POST["Headline"]) && !empty($_POST["Eintrag"])) {

      Mehr gefällig? Hier klicken! Damit ist auch dieser Bereich bestens abgesichert. Die folgenden Zeilen sorgen mit Hilfe der entsprechenden SQL-Anweisung für den Eintrag in die Datenbanktabelle cms. Nicht ohne die Werte vorher zu »escapen«. (Über die Wichtigkeit von mysqli_real_escape_string() haben wir uns im vorigen Kapitel ja lang und breit unterhalten.) Um das Skript nicht weiter zu verkomplizieren, verzichte ich auf weitere Überprüfungen der Werte. Mindestlänge, Übereinstimmung mit einem Suchmuster – all das ist bei diesem Formular nicht nötig. Schließlich bist du der einzige Nutzer und kommst erst nach dem Einloggen an das Formular. Und welchen Sinn würde es ergeben, dein eigenes Weblog zu hacken? Doch wozu ist diese Zeile von Nutzen? echo "

      [ Ausloggen ]

      ";

      Das ist eine Art Sicherheitsabfrage! Denn auch du als »geübter und eingeweihter Nutzer« könntest aus Versehen auf den AKTUALISIEREN-Schaltknopf klicken. Ein Doppeleintrag wäre die Folge! Durch die groß dargestellte Zeile Ausloggen wird dieses »Verlangen« jedoch unterbunden. Wer einmal der »Verführung« dieses Ausloggen-Links nachgegeben hat, sieht wieder die »Ursprungsfassung« der Gästebuchseite. Die Reload-Gefahr ist gebannt! Diese Fassung des Weblogs findest du im Ordner cms_version3.

      Mehr gefällig? Hier klicken! Fast fertig! Das Weblog ist aber noch nicht ganz perfekt! Angenommen, die Tagebuchschreiber gehören zur Spezies der »ausufernden Poeten«. Laber, laber, laber – du weißt schon. Das tut vielleicht dir als Schreiber gut, da du dir deinen ganzen Kummer endlich mal von der Seele schreiben kannst. Doch ob das jeden Leser interessiert? Soll der Leser gleich am Anfang mit der vollen »Breitseite« des gesamten langen Artikel-Eintrags »erschlagen werden«? Nein! Ein paar Sätze als Anreißer müssen genügen! Das bewahrt die Übersicht. So kann der Betrachter vorher anhand der ersten Sätze besser entscheiden, welche Beiträge wirklich lesenswert sind. Deshalb habe ich zum krönenden Abschluss eine besondere Raffinesse eingebaut. Arbeite mit einer automatischen Begrenzung der Artikellänge! 383

      Kapitel

      Weblog für Kids: »Das Mini-CMS«

      15

      Nach 250 Zeichen wird der Text automatisch abgeschnitten.

      Erst nach Klick auf den Link Alles lesen wird der gesamte Beitrag aufgerufen! Dieser kann dann in voller Pracht dargestellt werden. Zuerst zeige ich dir, welche Änderungen ich im Quellcode der Datei index.php vorgenommen habe. Wir beginnen mit dem »Abschneiden« des Resteintrags.

      Der Quellcode im Überblick Schaue in deine index.php. Bearbeite zuerst den Ausgabeteil innerhalb der while-Schleife. Der ursprüngliche Bereich sieht folgendermaßen aus: // while-Schleife Anfang while ($row = @mysqli_fetch_assoc($result2)) { $Eintrag = nl2br($row["Eintrag"]); // Einträge anzeigen echo "

      $row[Headline]

      \n" . "

      $Eintrag

      " . "
      <small>eingetragen von $row[Name] " . "am <strong>$row[Datum]


      \n"; } // while-Ende

      Und nun siehst du den gleichen Bereich mit den eingebauten Änderungen. // while-Schleife Anfang while ($row = @mysqli_fetch_assoc($result2)) { $Eintrag = nl2br($row["Eintrag"]); // Eintragslänge kürzen if (strlen($Eintrag) > 250) { $Eintrag = substr($Eintrag, 0, 250); $Eintrag .= "...
      ";

      384

      Die Funktionen strlen() und substring() $Eintrag .= "[ " . "Alles lesen ]"; } // Einträge anzeigen echo "

      $row[Headline]

      \n" . "

      $Eintrag

      " . "
      <small>eingetragen von $row[Name] " . "am <strong>$row[Datum]


      \n"; } // while Ende

      Versuche, die Änderungen so nachzuvollziehen. Versuche es! Du kannst dafür auch die Datei index.php aus dem Ordner cms_version4 öffnen. Dort habe ich exakt diese Änderungen für dich schon eingebaut.

      Die Funktionen strlen() und substring() Nehmen wir den neuen Quellcode nun etwas genauer unter die Lupe. Dabei spielen zwei ganz interessante Funktionen eine wichtige Hauptrolle. Doch ehe diese neuen Funktionen die Bühne betreten, beginnt unser Abschnitt mit einer Ouvertüre, der Einleitung. Denn zuerst fange ich den Haupt-Eintrag aus der Datenbank in einer Variablen namens $Eintrag auf. Das erleichtert die Übersicht! Außerdem kann ich auf diese Weise gleich die Zeilenumbrüche mit sichern. Dafür sorgt wieder die Funktion nl2br(). $Eintrag = nl2br($row["Eintrag"]);

      Nach diesem Vorspiel hat nun endlich die Funktion strlen() ihren großen Auftritt. Diese Funktion macht dabei nichts weiter als die Länge einer Zeichenkette zu ermitteln. Die Syntax sieht so aus: strlen("String")

      Diese Funktion gibt die Länge eines Strings zurück. Dabei werden übrigens auch Leerzeichen mitgezählt. Du kannst den String direkt innerhalb der runden Klammern notieren. Viel häufiger wirst du jedoch eine Variable zum Prüfen übergeben. Und genau das macht die Funktion auch in unserem Skript: strlen($Eintrag). 385

      Kapitel

      15

      Weblog für Kids: »Das Mini-CMS« In der Zeile if (strlen($Eintrag) > 250) { wird geprüft, ob der Eintrag größer als 250 Zeichen ist. Nur dann soll schließlich die Kürzung erfolgen. Beim Kürzen selbst erscheint eine weitere String-Funktion »auf der Bühne«, und zwar die Funktion substr(). Diese schneidet gnadenlos ganze Stücke aus »unschuldigen Strings«. Es ist eine Funktion mit drei Argumenten. Die Syntax sieht folgendermaßen aus: substr("String", Startposition, Länge)

      Gestartet wird beim Zählen wieder bei der 0 – die Arrays lassen grüßen. Der erste Buchstabe eines Strings entspricht dabei der 0. Du möchtest aus der Variablen $Eintrag die Zeichen zwischen 0 und 250 ausschneiden? Dann sieht die Funktion so aus: substr($Eintrag, 0, 250)

      Und schon ergibt die folgende Zeile einen Sinn: $Eintrag = substr($Eintrag, 0, 250);

      Aus der Variablen $Eintrag schnippelst du die ersten 250 Zeichen heraus und speicherst diese neue, verkürzte Zeichenfolge wieder in der Variablen $Eintrag. So einfach ist das! Jetzt folgt nur noch etwas Kosmetik, »etwas Schminke«, um in der Bühnensprache zu bleiben: Die folgende Zeile hängt ein paar Punkte an den verkürzten Eintrag an und setzt danach einen Zeilenumbruch, ein »break«. Alles aus optischen Gründen, damit der Eintrag nicht so abgehackt wirkt: $Eintrag.="...
      "; Die nächsten beiden Zeilen erzeugen den Link Alles lesen. Dabei wird wieder zum einen die Hauptseite aufgerufen, die index.php. Diesmal hängt jedoch der zusätzliche Parameter id mit der entsprechenden id des Weblog-Eintrags am Seitennamen dran: $Eintrag .= "[ " . "Alles lesen ]";

      Du ahnst sicher wieder, dass hier eine neue »GET-Variable« im Spiel ist!

      386

      Die Funktionen strlen() und substring()

      Variablenübergabe: Dieser Wert kann mit $_GET["id"] ausgelesen werden.

      Die restlichen Zeilen geben den Weblog-Eintrag aus. Dabei wird natürlich die neue Variable $Eintrag verwendet: "

      $Eintrag

      " .

      Probiere es aus. Zur Erinnerung: Du findest den aktuellen Stand auch im Ordner cms_version4. Fehlt da etwa noch etwas?

      Die letzte SQL-Abfrage erstellen Tatsache, der Text wird gekürzt angezeigt. Die Pünktchen erscheinen. Auch der Link Alles lesen ist da. Alles tutti paletti? Mitnichten! Denn nach Klick auf den Link Alles lesen passiert … erst einmal überhaupt nichts! Logisch! Es fehlt schließlich der letzte Teil des Skriptes. Es fehlt der Teil, der den passenden Eintrag zur id ausgibt. Also unseren kompletten, ungekürzten Beitrag! Na dann ran an die Buletten! Füge zwischen diesen Passagen: if (isset($_GET["start"])) { if (preg_match($muster, $_GET["start"]) == 0) { $start = 0; // Bei Manipulation Rückfall auf 0 } else { $start = $_GET["start"]; } } hier neuen Code einfügen ... $sql1 = "SELECT * FROM cms";

      folgenden Abschnitt ein: if (isset($_GET["id"])) { if (preg_match($muster, $_GET["id"]) == 0) { die("

      Abbruch wegen Manipulation!

      "); } else { $id = $_GET["id"]; }

      387

      Kapitel

      15

      Weblog für Kids: »Das Mini-CMS« $sql = "SELECT * FROM cms WHERE id=$id"; $result = mysqli_query($db, $sql); $row = @mysqli_fetch_assoc($result); echo "

      $row[Headline]

      \n" . "

      " . nl2br($row["Eintrag"]) . "

      " . "
      <small>eingetragen von $row[Name] am " . "<strong>$row[Datum]

      \n"; echo "[ Zurück ]"; } else {

      Vergiss nicht, den zusätzlichen else-Zweig wieder zu schließen. Setze deshalb über der Zeile mysqli_close($db);

      eine schließende geschweifte Klammer: } mysqli_close($db);

      Alles klar? Den entsprechenden SQL-Teil müsstest du dir inzwischen gut erschließen können: $sql = "SELECT * FROM cms WHERE id=$id";

      Ich arbeite mit einer WHERE-Klausel. Dabei gebe ich nur den Datensatz aus, der der jeweiligen id entspricht. Und auch die folgenden Zeilen sind inzwischen hoffentlich klar. Doch was verbirgt sich hinter dieser Zeile? echo "[ Zurück ]";

      Hier arbeitet der Autor mit einem Trick, um das Skript nicht noch weiter zu verkomplizieren. Ein einfacher JavaScript-Link führt wieder zurück zur vorigen Seite. Dafür sorgt javascript:history.back(). Das Schlüsselwort javascript: besagt, dass eine JavaScript-Anweisung folgt. Die eigentliche Anweisung steckt in history.back(), also in »gehe einen Schritt in der History zurück«. Das entspricht dem Klick auf den BACKButton. Wenn du diesen Code hinter dem Attribut href notierst, führt dich das wieder zurück zu der Seite, die du vorher auf deinem Bildschirm hattest. Simpel und wirkungsvoll zugleich! 388

      Schlussbemerkung

      Nach Klick auf Zurück landet der Besucher wieder auf der vorherigen Seite.

      Diese Version des Skriptes findest du im Ordner cms_version5 auf der Buch-CD. Ich habe zusätzlich die Einrückung noch etwas angepasst. Denn auch der Inhalt eines else-Zweiges sollte schließlich etwas eingerückt werden.

      Schlussbemerkung Du hast es geschafft! In diesem Kapitel hast du ein richtiggehendes Weblog programmiert. Damit bist du fast ohne es zu merken in die Geheimnisse von »Content Management« eingedrungen. Du kannst »Inhalte managen«. Du gibst Artikel (Tagebucheinträge usw.) ein, bewahrst diese in einer Datenbank auf und sorgst für die attraktive Ausgabe.

      Zusammenfassung 0 Du weißt, wie du eine Seite mit Style Sheets attraktiv gestalten kannst. Du arbeitest mit Rahmeneffekten und Farben. 0 Du kennst den Operator heredoc, mit dem du auf simple Weise HTMLAbschnitte in PHP einbindest. 0 Du weißt, dass du innerhalb von heredoc wie gewohnt auf PHPVariablen zugreifen kannst.

      389

      Kapitel

      Weblog für Kids: »Das Mini-CMS«

      15

      0 Du kennst die Funktion strlen("String") zur Ermittlung der Länge eines Strings. 0 Du verwendest die Funktion substring("String", Startposition, Länge), mit dem du einen bestimmten Teilbereich eines Strings ausgeben kannst. 0 Du kennst die JavaScript-Anweisung history.back(), die den Besucher zurück zur vorher besuchten Seite führt.

      Ein paar Fragen … 1. Was bedeutet das Wort Content? 2. Welche Funktion ermittelt die Länge eines Strings? 3. Aus welcher Programmiersprache stammt denn die Anweisung history.back() und was bewirkt sie?

      … und ein paar Aufgaben 1. Bisher wird das Einlogg-Cookie nicht gelöscht. Das ist im Prinzip nicht schlimm, denn es verfällt nach dem Schließen des Browserfensters. Trotzdem möchtest du mehr Sicherheit. Richte es also so ein, dass das Cookie nach Absenden der Daten gleich mit gelöscht wird. Tipp: Das tust du unterhalb der Stelle, an der du das Cookie setzt. 2. Wir haben zwar mit mysqli_real_escape_string() dafür gesorgt, dass die Daten vor dem Eintrag in die Datenbanktabelle »escaped« werden. Wir haben jedoch keine Rücksicht auf rückständige Webhoster genommen, bei denen »magic quotes« noch eingeschaltet ist. Baue eine zusätzliche Routine ein, die diesen Schalter abfragt und im Zweifelsfall ein doppeltes Escapen (führt zur Anzeige von Backslashs vor Anführungszeichen) verhindert. 3. Noch eine schwere Aufgabe! Schaue nach unten im Weblog: Füge in den Bereich zum Blättern zu älteren Einträgen einen weiteren Link ein, mit dem du auch wieder nach vorne blättern kannst! Überlege, wie der entsprechende GET-Wert aussehen muss und welche Bedingungen du formulieren musst. Tipp: Es ist nicht so kompliziert wie beim Link zu den älteren Einträgen! Wenn du’s schaffst, bist du schon sehr gut. 390

      16 Aktivitäten verwalten: Wer kommt mit ins Kino? Wer kommt mit ins Kino? Nehmen wir als Beispiel einen Filmklub! Nehmen wir weiterhin an, dass du für die Organisation verantwortlich bist. Du schlägst die Termine vor. Du nimmst die Kartenwünsche deiner Kumpels und Teammitglieder entgegen. Du besorgst zum Schluss die Karten und alle sind glücklich und zufrieden. Wirklich alle? Du auch? Das Besorgen der Tickets selber ist sicher das kleinere Problem. Doch die Vorarbeit? Die ist sehr undankbar! Deine Kumpels bestürmen dich: »Hast du mich schon aufgeschrieben?« »Ich will auch ein Ticket.« »Denke an die Karte für meine Freundin.« »Wann findet der nächste Kinotreff noch mal statt?« Dieser Verwaltungskram nervt! Und am Ende stehst du mit den zu viel gekauften Eintrittskarten da und bleibst auf dem Geld sitzen. Schluss mit den Strichlisten, Schluss mit der Zettelwirtschaft! Self Service lautet die Devise. Wozu gibt es schließlich Webformulare und Datenbanken? In diesem Kapitel zeige ich dir, wie du $ Informationen auf mehrere Tabellen aufteilst $ die Adressliste alias Kundendatei einbindest $ eine Tabelle für die Veranstaltungen schreibst $ die Bestellwünsche in einer weiteren Tabelle festhältst $ mehrere Tabellen miteinander verbindest $ Daten aus mehreren Tabellen gleichzeitig abfragst

      391

      Kapitel

      Aktivitäten verwalten: Wer kommt mit ins Kino?

      16

      Das Adressbuch bekommt Gesellschaft Du musst zufällig gerade keine Kinonachmittage organisieren? Das macht nichts. Du kannst das Beispiel auch als Anmeldeformular für einen Vortrag, für die Disko oder selbst als Basis-Skript für einen Online-Shop verwenden. Die Teammitglieder sind deine Kunden. Die Veranstaltungen werden zu den Produkten. Wie auch immer – im Endeffekt entsteht ein kleines Bestellsystem, welches du beliebig ausbauen kannst. Um deine »Kunden« musst du dich in unserem Fall nicht mehr kümmern. Die liegen schon fest. Das sind die Klassenkameraden, Teammitglieder oder Vereinskumpels. Also diejenigen, die wir in Kapitel 13 schon in unsere Tabelle adressen eingetragen haben. Okay, das war jetzt eine ganz unmissverständliche Aufforderung, schnell noch einmal in Kapitel 13 nachzuschlagen!

      Adresstabelle und Kundennummer Hier zeige ich dir fix noch einmal die Grundstrukur der Datenbanktabelle adressen. Du siehst die Feldnamen und die ersten beiden Datensätze. id 1

      Vorname Name Hans Meier

      Str Waldweg 7

      2

      Martina

      Waldweg 2

      Weber

      PLZ Ort Tel EMail WWW Notizen 12345 Neustadt 234567 hans@lexi. www.lexi. de de 12345 Neustadt 234568 martina mag @lexi.de Kaugummis

      Besonders wichtig ist hierbei die Spalte id, also die eindeutige Kennung jedes Datensatzes. Zur Erinnerung: Dieses Datenfeld wird als Primärschlüssel bezeichnet. Diese eindeutige Kennung teilst du deinen Klassenkameraden bzw. Kumpels mit. Betrachte diese Nummer als eine Art »Nutzer-ID« bzw. »Kundennummer« – wie dir gerade zumute ist. Nur wer seine NutzerID kennt, kann sich auch für Veranstaltungen vormerken lassen bzw. Produkte bestellen. Und wer noch nicht in deiner Tabelle steht, sollte von dir schleunigst nachgetragen werden! Tipp für die Weiterentwicklung: Du kannst das Adressen-Beispiel aus Kapitel 13 auch so umändern, dass es als Anmeldeformular für Neukunden dient. Jedem Kunden wird nach Registrierung (= Eintrag in die Datenbank) seine Kundennummer (eben diese id) eingeblendet. 392

      Das Adressbuch bekommt Gesellschaft

      Datenbanktabelle mit den Veranstaltungen Die Datenbanktabelle steht. Als nächstes benötigst du nun eine Tabelle, in die du die Veranstaltungen einträgst. Also die Kinofilme, Vereinsnachmittage, Klassenfahrten oder was auch immer. Du möchtest schließlich die Aktivitäten präsentieren, deine »Produkte«. Schau dir meinen Vorschlag an. Im Beispiel handelt es sich zwar »nur« um die »Produktpräsentation« eines Filmklubs. Wie du siehst, habe ich die Struktur jedoch so gehalten, dass du sie leicht an deine Bedürfnisse anpassen kannst. id Titel Untertitel 1 Film- bzw. Produkttitel, Hier kann eine kurze max. 100 Zeichen Beschreibung hin (max. 200 Zeichen)

      Beschreibung Dieser Platz ist für eine ausführliche Beschreibung vorgesehen.

      Preis Zahlenwert, auch mit Nachkommastellen, z. B. 4

      Für diese Datenbanktabelle schlage ich den Namen produkte vor. Die Wahl der Felder ist selbsterklärend. Auch bei dieser Tabelle gibt es wieder das obligatorische Schlüsselfeld für die eindeutige Kennung. Es heißt hier ebenfalls id. Weiterhin plane ich ein Feld für den Titel und eins für den Untertitel. Das verleiht mir mehr Flexibilität. Die Beschreibung darf natürlich nicht fehlen, sie bekommt den größten Platz. Und da Kinokarten in der Regel etwas kosten, gibt es schließlich ein Feld für den Preis. Das war’s dann auch schon.

      Die Struktur der Datenbanktabelle produkte Halt, halt! Bisher habe ich dir zwar die Struktur der Tabelle erläutert. Aber ehe du die Datensätze eintragen kannst, musst du die Tabelle erst einrichten. Rufe phpMyAdmin auf, wie in den vorigen Kapiteln besprochen. Erzeuge die Datenbanktabelle produkte. Bei dieser Gelegenheit entscheidest du dich gleich für die richtigen Felddatentypen. Und mit diesen Befehlen erstellst du nun die Datenbanktabelle: CREATE TABLE produkte ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, Titel VARCHAR(100), Untertitel VARCHAR(200), Beschreibung TEXT, Preis FLOAT ) DEFAULT CHARACTER SET utf8;

      393

      Kapitel

      16

      Aktivitäten verwalten: Wer kommt mit ins Kino? Die Felddatentypen sind dir geläufig? Ich verwende INT, VARCHAR und TEXT. Für den Preis empfehle ich außerdem den Datentyp FLOAT. Dieser erlaubt eine Kommazahl mit ausreichender Genauigkeit.

      Der SQL-Befehl wurde erfolgreich ausgeführt – die Tabelle existiert!

      Ein paar Vorschläge für die Datenbanktabelle Und nun trägst du mit phpMyAdmin die »Produkte« in deine Filmtabelle ein. Datum und Uhrzeit habe ich gleich mit in das Titelfeld hineingeschrieben, um ein eigenes Feld zu sparen. Wir wollen es nicht unnötig verkomplizieren. Wenn du dir unsicher bist, übernimmst du meine Daten exakt genau so. Du findest sie auch auf CD: Schaue in die Datei filmklub.rtf unter beispiele/kapitel16. Die etwas Mutigeren können natürlich eigene Beispiele wählen. Vielleicht leitest du ja keinen Filmklub, sondern den Handballverein?

      394

      id Titel 1 Momo, 12. Mai, 17:00 Uhr

      Untertitel Spielfilm nach dem Roman von Michael Ende, mit Mario Adorf und Radost Bokel, Deutschland 1986

      2

      Moritz in der Litfaßsäule, 25. Mai, 17:00 Uhr

      Spielfilm nach dem Roman von Christa Kozik, Deutschland 1983

      3

      Gritta von RatMärchenfilm mit tenzuhausbeiuns, Nadja Klier und 1. Juni, 20:00 Uhr Hermann Beyer, Deutschland 1984

      Beschreibung Momo lebt in einem alten Amphitheater und ist bei den Bewohnern der Stadt sehr beliebt. Doch dann treffen die grauen Herren in der Stadt ein und stehlen die Zeit. Wie ein kleiner Junge vor der Welt der Erwachsenen flieht und in einer Litfaßsäule auf eine sprechende Katze trifft. Liebenswerte, sehr aufwendige Verfilmung des Märchenromans von Bettina und Gisela von Arnim.

      Preis 4

      3

      3

      Ist das noch normal? Daten aufteilen!

      Trage die Daten mit phpMyAdmin in die Datenbanktabelle ein.

      Ist das noch normal? Daten aufteilen! Halten wir fest: Für dein Bestellsystem stehen dir bisher folgende Datenbanktabellen zur Verfügung: 0 adressen (deine Kundenliste) 0 produkte (die Produkttabelle) Das ist schon einmal sehr sinnvoll. Damit trennst du Kunden und Produkte auf ideale Weise voneinander und schaffst dadurch eine klare Struktur. Auch die Idee, die id der Tabelle adressen praktisch als Kundennummer zu verwenden, ist so einfach wie genial. Ähnlich halten wir es mit den Filmveranstaltungen. Auch hier wird die id zur Kennung, zu einer Art Produktnummer.

      Daten in Teiltabelle zerlegen Und genau an dieser Stelle fängt Datenbankdesign endlich an, so richtig spannend zu werden: Du arbeitest nicht nur mit einer, sondern gleich mit mehreren Teiltabellen. Warum? Auf diese Weise sicherst du, dass alle diese Daten nur einmal erfasst werden müssen. Nehmen wir einmal die Adressen. Stell dir vor, es gäbe diese zentrale Adresstabelle nicht. Stell dir weiterhin vor, die Kunden müssten ihre Adresse bei jeder Bestellung neu eingeben. Was da für ein Chaos entsteht! Dadurch bekommst du lange und unübersichtliche Listen. Vielbesteller z. B. sind ganz oft in der Liste enthalten – jedes Mal mit einer neuen id. Wo bleibt da die eindeutige

      395

      Kapitel

      16

      Aktivitäten verwalten: Wer kommt mit ins Kino? Kennung? Aber es kommt noch schlimmer! Denke auch an Verschreiber. Der Kunde schreibt bei der zehnten Bestellung den Nachnamen in der Eile aus Versehen klein? Schon ein falsches Zeichen sorgt schlimmstenfalls für kunterbunte Verwechslungen mit anderen Personen! Wie bitte, ich soll hier nicht schwarz malen? Die Gefahr besteht bei deiner »Hand voll« Teammitglieder nicht? Bei Datenbanken musst du stets das »große Ganze« vor Augen behalten! Welcher Betreiber eines großen Onlineshops kennt schon alle seine Kunden persönlich? Bei hunderten oder tausenden von Adressen führt schon die kleinste Unstimmigkeit zum kompletten Chaos! Merke: Bei großen Datenbankprojekten wird man stets mit mehreren Teiltabellen arbeiten. Dadurch erspart man sich die unsinnige Mehrfacherfassung von Daten. Auf diese Weise können Fehlerquellen von vornherein ausgeschlossen werden. Eine Adresse lässt sich leichter »updaten«, wenn sie genau einmal statt zehnmal in deiner Datenbank auftaucht. Produktlisten können bequem bearbeitet und erweitert werden, wenn es eine separate Tabelle dafür gibt. Dieser Vorgang des Zerlegens wird auch als Normalisieren bezeichnet. Man redet davon, die Tabelle »in ihre Atome zu zerlegen«. Und diese galten noch bis vor einer Weile – zumindest wollte uns das unser Chemielehrer damals weismachen – als unteilbar.

      Auch die Bestellungen müssen in eine separate Tabelle! Kunden und Produkte sind ja ganz schön und gut. Die haben wir von vornherein in separaten Tabellen gespeichert. Doch was machst du mit den Bestellungen? Auch dafür richtest du natürlich eine separate Liste ein. Diese Tabelle nennst du im Beispiel 0 bestellungen Sie dient im Beispiel einzig und allein dem Zweck, die Bestellungen festzuhalten. Dich interessiert folgendes: 0 Wer hat sich angemeldet (Kunde)? 0 Welches Event/Produkt wurde ausgewählt (Produkt)? 0 Wie oft wurde das Produkt gebucht (Anzahl)? 0 Wann wurde die Bestellung aufgegeben (Datum)? 396

      Ist das noch normal? Daten aufteilen!

      In der Kürze liegt die Würze. Auch in dieser Tabelle speicherst du nur das Nötigste. Es wäre Unsinn, hier noch einmal die gesamten Produktdaten mit Titel, Untertitel und Beschreibung zu notieren. Es wäre quatsch, alle Besteller in voller »Tabellenpracht« noch einmal aufzulisten. Normalisieren (Zerlegen) lautet die Devise! Wozu haben wir denn unsere pfiffigen id-Angaben? Statt alle Produktdaten zu notieren, reicht die id der Datenbanktabelle produkte. Dort sind schließlich alle Details hinterlegt! Auch von den Kundendaten interessiert dich nur die id. Die volle Adresse steckt schließlich in der Tabelle adressen. Hier zeige ich dir nun meinen Entwurf der Tabelle bestellungen. Beachte, dass ich auch dieser Tabelle wieder eine eindeutige Kennung verpasse. Auch hier gibt es also einen eigenen Primärschlüssel namens id: Für die »fremden IDs« habe ich mir dagegen einen anderen Feldnamen ausgedacht, damit es nicht zu Verwechslungen kommt: id 1

      aid pid Feld id aus Tabelle Feld pid aus Tabelle adressen produkte

      Anzahl Ganzzahl

      Datum Datumsstempel kann mit Funktion date() erzeugt werden

      Es handelt sich bei diesen »Fremd-IDs« um die beiden Felder aid (adressen id) und pid (produkte id). Der zusätzliche Buchstabe a bzw. p steht also für die Tabelle adressen bzw. produkte.

      Die Tabelle bestellungen vorbereiten Ran an phpMyAdmin. Mit folgenden SQL-Befehlen bereitest du nun die letzte Tabelle vor. Diese richtest du, wie alle Tabellen, in der Datenbank team ein. CREATE TABLE bestellungen ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, aid INT, pid INT, Anzahl INT, Datum VARCHAR(30) ) DEFAULT CHARACTER SET utf8;

      Diesmal hat der Felddatentyp INT seinen großen Auftritt. Die entsprechenden Schlüsselfelder (der eigene Primärschlüssel bzw. die Schlüsselfelder der anderen Tabellen) sowie die Anzahl sind schließlich Ganzzahlen. 397

      Kapitel

      16

      Aktivitäten verwalten: Wer kommt mit ins Kino? Zur Verdeutlichung habe ich schon zwei Datensätze eingetragen. Das musst du natürlich noch nicht tun. Schließlich weißt du nicht unbedingt vorher, wer sich nun für welchen Film interessiert. id 1 2

      aid 1 2

      pid 1 3

      Anzahl 2 1

      Datum 05.05.2010, 12:15 15.05.2010, 14:22

      Beziehungskiste – So hängen die Daten voneinander ab Mache dir ruhig einmal klar, wie diese drei Tabellen voneinander abhängen. Zur Veranschaulichung habe ich eine kleine Abbildung erstellt: Jede Tabelle hat ihre eigenen Aufgaben.

      Die Datenbanktabelle bestellungen hängt direkt von den Tabellen adressen und produkte ab. Alle Tabellen gehören also zusammen. Der Vorteil liegt auf der Hand: Es werden keine Daten doppelt gesichert. Es gibt genau eine Tabelle für die Kunden, genau eine Tabelle für die Produkte und genau eine Tabelle für die Bestellungen! In diesem Beispiel sprechen Datenbankexperten übrigens von einer 1:nBeziehung. Einem Kunden können n Bestellungen zugeordnet werden. (Möge er möglichst oft deine Kinofilme buchen!) Ein Film bzw. Produkt kann theoretisch unzählige Male gebucht werden. Zumindest gilt das, solange Vorrat bzw. Sitzplätze reichen. 398

      Nicht vergessen: Das Eingabeformular

      Nicht vergessen: Das Eingabeformular Deine drei Tabellen für das Bestellsystem sind fertig. Hervorragend! Es fehlt allerdings noch eine Klitzekleinigkeit. Wie gelangen die Daten in die Tabelle bestellungen? Natürlich durch eine Webseite, auf der du die Veranstaltungen präsentierst. Und durch das entsprechende Eingabeformular. Auch hier heißt es: Planen, planen, nochmals planen. Wie gehen wir vor? Diesmal schlage ich zur Abwechslung eine andere Struktur vor. Du arbeitest nicht mit einer, sondern mit drei PHP-Seiten. Auf der ersten Seite kann der Besucher seine Bestellung aufgeben. Diese Seite nenne ich: 0 index.php Durch diese Benennung erscheint die Seite übrigens wieder genau dann, wenn du den entsprechenden Ordner im Browser aufrufst! Nach Klick auf den Button JETZT ANMELDEN werden die Auswahldaten an eine zweite Seite geschickt namens 0 order.php Dort bestätigt der Kumpel seine Auswahl. Dann muss sie oder er BenutzerID (Kundennummer) und Nachnamen eingeben. Diese Seite schickt alle Daten zum Schluss an eine weitere Seite namens: 0 input.php Hier werden letztendlich die Daten nach erfolgreicher Überprüfung in die Tabelle eingetragen! Soweit die Theorie. Das Ganze setzen wir jetzt gemeinsam in die Praxis um!

      Projektordner und Datei index.php

      >

      Richte dir einen eigenen Projektordner ein namens order. Diesen platzierst du im Beispiel direkt unter dem Ordner C:\xampp\htdocs.

      >

      Kopiere die schon in den vorigen Kapiteln verwendete Datei zugriff.inc.php in einen extra Ordner namens edit. Diesmal benötigst du nur die Zugriffsdaten für MySQL, keinen Benutzernamen und kein Kennwort. Nimm die zugriff.inc.php aus Kapitel 14! 399

      Kapitel

      16

      Aktivitäten verwalten: Wer kommt mit ins Kino?

      >

      Bereite außerdem eine Seite namens index.php vor. Ich empfehle folgendes Grundgerüst:

      Veranstaltungen des Filmklubs <meta http-equiv="content-type" content= "text/html; charset=utf-8">

      Kommst du mit ins Kino?

      Bitte entscheide dich für die gewünschte Veranstaltung und wähle die Anzahl der Karten! Halte außerdem deine Benutzer-ID bereit!

      ... Hier kommt der PHP-Teil hin!


      Wie du bemerkst, lehne ich mich an das bewährte Layout des Content Management Systems aus dem vorigen Kapitel an. Auch hier arbeite ich mit einer externen CSS-Datei, die wieder im Unterordner css liegt. Sie heißt diesmal order.css. Es handelt sich dabei um eine abgespeckte Variante der weblog.css aus dem vorigen Kapitel. Wir geben hier die exakte Breite des DIVs vor – wieder mithilfe der id wrapper. Auf die Hintergrundgrafik habe ich jedoch verzichtet. Schaue einfach mal in die order.css rein! Auch diesmal gehe ich nach der Taktik vor: Schritt für Schritt, Seite für Seite. Und das Testen nicht vergessen!

      Der PHP-Teil im Überblick Auf zum nächsten Schritt. Füge nun den PHP-Teil ein. Hier zeige ich dir meinen Vorschlag. Diesen findest du natürlich – wie auch das gesamte Projekt – im entsprechenden Kapitel-Ordner auf der CD. Inzwischen dürfte es dir nicht mehr schwer fallen, den Code zu durchschauen. Wie schon bei den vorhergehenden MySQL-Beispielen werden die Einträge aus der Datenbank ausgelesen und optisch präsentiert. 400

      Nicht vergessen: Das Eingabeformular

      Aus Bequemlichkeit arbeiten wir dabei wieder mit der heredoc-Syntax. Erinnerst du dich? Im vorigen Kapitel habe ich dich darüber aufgeklärt. Der Heredoc-Bereich wird mit echo <<$zeilen Einträge:

      \n"; // WHILE AUF while ($row = @mysqli_fetch_assoc($result)) { // HEREDOC beginnt echo <<{$row["Titel"]}
      <strong>{$row["Untertitel"]}
      {$row["Beschreibung"]}
      Kosten: {$row["Preis"]} Euro
      Anzahl:

      FORMULARBEREICH; // HEREDOC ENDE } // WHILE ZU mysqli_close($db); ?>

      401

      Kapitel

      16

      Aktivitäten verwalten: Wer kommt mit ins Kino? Die Auswahl des Filmes alias Produkts erfolgt durch ein Formular. Das Formular erfasst Anzahl und ID. Die ID und der Titel werden dabei jeweils in ein verstecktes Formularfeld geschrieben:

      Die Filme werden übersichtlich auf der Seite index.php präsentiert.

      Der SUBMIT-Button bekommt ganz absichtlich einen Namen verpasst.

      402

      Diese Anweisung name="sm1" dient vor allem der Wiedererkennung auf der nächsten Seite. Denn nach Klick auf JETZT ANMELDEN reicht das Formular seinen Inhalt schließlich an die Seite order.php weiter. Und diese nächste Seite schauen wir uns nun gemeinsam an!

      Bitte bestätige: Name und Nutzer-ID

      Bitte bestätige: Name und Nutzer-ID Jetzt folgt der nächste Schritt. Richte eine Bestätigungsseite ein! Es geht um die Datei order.php.

      Die Datei order.php Bereite die Seite order.php vor. Diese nimmt, wie schon erwähnt, die ID, die Anzahl und den Titel des Produktes entgegen. Zur Kontrolle blendest du hier die letzteren Angaben noch einmal ein. Der Nutzer bestätigt dann seine Wahl durch Eingabe seiner Benutzer-ID und den Nachnamen.

      Der Benutzer muss sich nun verbindlich anmelden.

      Hier zeige ich dir den gesamten Quellcode zwischen den Tags . Besonders interessant ist wieder der PHP-Teil. "); }

      403

      Kapitel

      16

      Aktivitäten verwalten: Wer kommt mit ins Kino? // Bestätigungsformular erzeugen echo <<Auswahl bitte bestätigen!

      Hallo, du hast dich für folgende Veranstaltung entschieden:

      {$_POST["Anzahl"]} x <strong>{$_POST["Titel"]}

      Bitte bestätige diese Auswahl mit deinen Daten:

      Deine Benutzer-ID: Dein Nachname:

      FORMULARBEREICH; } else { // Surfer kommt zufällig auf die Seite echo "

      Zur Startseite!

      "; } ?>


      Der Quelltext im Überblick Blickst du durch den Code durch? Es gibt weder spektakuläre Besonderheiten noch irgendwelche Neuerungen. Nicht einmal eine SQL-Abfrage, denn die ist auf dieser Zwischenseite nicht nötig. Außerdem habe ich alle wichtigen Abschnitte mit Kommentaren eingeleitet. Probiere das Skript bis hierher ruhig einmal aus. Dir ist doch noch nicht alles klar? Gut, besprechen wir schnell das Wichtigste! Zuerst prüft das Skript, ob das Formular überhaupt abgeschickt wurde. Pfiffigerweise hatten wir dem SUBMIT-Button aus der index.php schließlich den Namen sm1 verpasst. Du fragst diesen Namen ab und reagierst darauf. Der Hauptcode der Seite soll schließlich nur dann ausgeführt werden, wenn das Formular abgeschickt wurde.

      404

      if (isset($_POST["sm1"])) { ...

      Bitte bestätige: Name und Nutzer-ID Doch was passiert, wenn das nicht der Fall ist? Surfer, die die Seite order.php zufällig aufgerufen haben, bekommen dank dieser Abfrage lediglich den else-Zweig zu Gesicht. Sie sehen einen Link, der zurück zur Hauptseite weist. } else { // Surfer kommt zufällig auf die Seite echo "

      Zur Startseite!

      "; }

      Doch nun zum eigentlichen interessantem Teil, zu den Codezeilen, die unterhalb der if-Abfrage folgen.

      Zur Sicherheit: Werte überprüfen Auch hier folgt wieder etwas Sicherheit! Wir überprüfen, ob die Werte für Anzahl und id Zahlen sind. Bei id ist das sicher der Fall. Es sei denn, jemand manipuliert das Formular. Aber bei Anzahl könnte es Probleme geben. Ein Witzbold könnte einen Buchstaben tippen. Das wird mit diesem Test untersucht und unterbunden. Außerdem darf die Anzahl der Karten nicht 0 sein! $muster = "/^[0-9]+$/"; // reg. Ausdruck für Zahlen if (preg_match($muster, $_POST["Anzahl"]) == 0 || preg_match($muster, $_POST["id"]) == 0 || $_POST["Anzahl"] < 1) { die("

      Eingabe " . überprüfen!

      "); }

      Im Zweifelsfall bekommt der Nutzer den Link Eingabe überprüfen zu sehen. Er wird auf die Startseite zurückgeführt und das Skript bricht ab. Bei einem »echten« Onlineshop im Internet würde man jetzt aus Sicherheitsgründen ggf. noch weitere Tests »fahren«. Man würde prüfen, ob die übermittelte id überhaupt in der Datenbanktabelle vorkommt. (Sie kann ja durch Formularmanipulation gefälscht worden sein.) Das gleiche würde man für den übermittelten Titel tun. Denn alle Werte, die von einer Seite an die nächste übergeben werden, können theoretisch von Hackern manipuliert werden. Man würde den »Warenkorb« auch eher in einer Session direkt auf dem Webserver ablegen, um solche Manipulationen auszuschließen. (Sessions besprechen wir übrigens im Nachfolgeband.) Im Beispiel genügen die von uns eingesetzten Tests, um das Skript nicht unnötig zu verkomplizieren. Sie sind schon relativ gut. Ich wollte bei dir jedoch ein erweitertes Sicherheitsbewusstsein wecken!

      405

      Kapitel

      16

      Aktivitäten verwalten: Wer kommt mit ins Kino?

      Der Heredoc-Bereich Schauen wir uns nun die Passage zwischen echo <<

      Die Anweisung onclick="location='index.php'" sorgt dafür, dass bei Klick auf diesen Button wieder die Seite index.php aufgerufen wird!

      Wer kommt mit? Aus zwei mach drei!

      406

      Nun zum Höhepunkt, zur Seite input.php. Hier entsteht – wenn alles glatt gegangen ist – der Datenbankeintrag. Hier wird die Datenbanktabelle bestellung gefüttert. Bei dieser Gelegenheit bauen wir wieder ein paar zusätzliche if-Abfragen ein, damit keine sinnlosen Einträge in der Datenbank landen.

      Wer kommt mit? Aus zwei mach drei!

      Die Datei input.php Zuerst zeige ich dir den Quelltext der input.php. Du siehst den gesamten Bereich zwischen den Tags .

      Eintrag in die Datenbank übertragen

      Eingabe " . "überprüfen!
      "); } include("edit/zugriff.inc.php"); // Adresse anhand der id ermitteln $sql = "SELECT * FROM adressen WHERE id=$_POST[aid]"; $result = mysqli_query($db, $sql); $row = @mysqli_fetch_assoc($result); // Ist der Nachname korrekt? if ($row["Name"] == $_POST["Name"]) { $datum = date("d.m.Y, H:i"); // Datum mit Uhrzeit // Daten eintragen in bestellungen $sql = "INSERT INTO bestellungen VALUES " . "('','$_POST[aid]','$_POST[pid]','$_POST[Anzahl]','$datum')"; mysqli_query($db, $sql); // Erfolgsanzeige if (mysqli_affected_rows($db) > 0) { echo "

      Hallo $row[Vorname] $row[Name]: Eintrag erfolgreich!

      "; } else { echo "

      Hallo $row[Vorname] $row[Name]: Eintrag nicht erfolgreich!

      "; } echo "zurück zur Startseite"; } else { // Keine Übereinstimmung von Nachname und id echo <<Bitte gib die korrekten Daten an!



      407

      Kapitel

      16

      Aktivitäten verwalten: Wer kommt mit ins Kino?
      FORMULARBEREICH; } mysqli_close($db); } else { // mind. ein Feld nicht ausgefüllt echo <<Alle Felder müssen ausgefüllt werden!

      FORMULARBEREICH2; } ?>


      Der Quelltext im Überblick Uff! Lass dich nicht von der langen »Codewüste« beunruhigen. Auch in diesem Skript steckt nichts wirklich Bahnbrechendes! Zuerst prüfen wir, ob der Benutzer auch tatsächlich über das Formular der Seite order.php auf die input.php gelangt ist. Auf der Seite order.php hatten wir zu diesem Zwecke den SUBMIT-Button des Formulars wieder durch einen Namen gekennzeichnet. Diesmal lautete dieser name="sm2". Bei dieser Gelegenheit wird zusätzlich gleich mit getestet, ob die Felder aid und Name nicht leer gelassen wurden. // alle Felder ausgefüllt? if (!empty($_POST["sm2"]) && !empty($_POST["aid"]) && !empty($_POST["Name"])) { ...

      Wenn mindestens eine der Teilbedingungen unwahr ist, wird der Benutzer zurück zur Ausgangsseite geschickt: } else { // mind. ein Feld nicht ausgefüllt ...

      408

      Wer kommt mit? Aus zwei mach drei! Danach prüft wieder unser obligatorischer regulärer Ausdruck auf Fehleingaben und schickt den Benutzer ggf. wieder zur vorherigen Seite zurück. Betroffen sind $_POST["aid"], $_POST["pid"] und $_POST["Anzahl"], alles müssen Zahlwerte sein. Genau diese Werte verarbeiten wir weiter unten in SQL-Abfragen. Dank dieser Überprüfung sparen wir uns auch weitere Escape-Maßnahmen durch mysqli_real_escape_string(). Alle weiteren Abschnitte dazwischen sind durch Kommentare gut dokumentiert. Schau zuerst zum Bereich: // Adresse anhand der id ermitteln

      Hier holst du den kompletten Adressdatensatz aus der Tabelle adressen. Schließlich muss der Nachname »gegengeprüft« werden. // Ist der Nachname korrekt?

      In diesem Abschnitt vergleichst du nun den Namen aus dem Formular mit dem Namen aus der Adresstabelle. Nur bei einer Übereinstimmung geht es weiter, dafür sorgt eine if-Abfrage. Dann wird z. B. das Datum mit Uhrzeit erzeugt und in der Variablen $datum abgespeichert. Diese Angabe benötigen wir schließlich in unserer Datenbank bestellungen. Sollte es hier eine Unstimmigkeit geben, springt das Skript zum elseZweig: // Keine Übereinstimmung von Nachname und id

      Der Nutzer sieht folgendes Bild:

      Nachname und ID stimmen nicht überein? Noch einmal probieren!

      Als nächstes folgt dieser Abschnitt: // Daten eintragen in bestellungen

      Hier werden die Daten endlich in die Tabelle bestellungen eingetragen. Das gelingt wieder mit der Grundsyntax

      409

      Kapitel

      16

      Aktivitäten verwalten: Wer kommt mit ins Kino? INSERT INTO bestellungen () VALUES ()

      Dabei lassen wir die normalerweise folgenden runden Klammern hinter bestellungen einfach wieder weg – ich habe diese Stelle fett hervorgehoben. Da alle Felder betroffen sind, muss man die Feldnamen nicht extra angeben. Du erinnerst dich noch? Nicht weglassen darfst du das runde Klammernpaar für die Werte, die den jeweiligen Feldern zugeordnet werden. Beachte, dass alle Werte in Gänsefüßchen eingekleidet werden müssen. Ich weiß, dass hier eine große Fehlerquelle lauert. Deshalb habe ich es an dieser Stelle wiederholt.

      Abfrage mit Erfolgsanzeige Die eigentliche Abfrage findet hier statt: mysqli_query($db, $sql); // Erfolgsanzeige if (mysqli_affected_rows($db) > 0) { echo "

      Hallo $row[Vorname] $row[Name]: Eintrag erfolgreich!

      "; } else { echo "

      Hallo $row[Vorname] $row[Name]: Eintrag nicht erfolgreich!

      "; }

      Hier kommt wieder mysqli_affected_rows() zum Einsatz und informiert über den erfolgreichen oder erfolglosen Eintrag. Dabei spreche ich den Benutzer gleich noch persönlich an – schließlich stehen die Werte der entsprechenden Datenbankfelder in $row[Vorname] und $row[Name] zur Verfügung.

      Alles klar, der Datenbankeintrag war erfolgreich.

      410

      Und wie vermeidest du Doppeleingaben? Durch einen Unique Index, der sich auf die Felder aid und Datum bezieht. Das wird deine Aufgabe werden – mehr dazu also im Aufgabenbereich auf Seite 418 (letzte Aufgabe)!

      SQL für Profis: Von Joins und Funktionen

      SQL für Profis: Von Joins und Funktionen So weit, so gut: Dein Bestellsystem steht! Die Kunden in spe können ihre Buchungen vornehmen. Du bist ungeduldig und möchtest testen? Gib doch einmal ein paar Bestellungen zum Üben ein! (Du kannst die Tabelle bestellungen nach der Generalprobe einfach wieder löschen und neu anlegen.) Du brauchst lediglich die Liste deiner Teammitglieder, damit du deren ID einsehen kannst. Versetze dich ruhig mal in die Haut von deinen Kumpels und buche mal die eine, mal die andere Veranstaltung.

      Abfrage zur Ermittlung der Bestelldaten Doch wie wertest du die Tabelle aus? »Das ist eine lange Geschichte« – so würde Käptn Blaubär diesen Abschnitt sicher einleiten. Ich versuche, das Ganze etwas kürzer zu fassen: Lerne fortgeschrittenes SQL!

      >

      Öffne phpMyAdmin und rufe die Tabelle bestellungen auf. Klicke auf ANZEIGEN bzw. klicke im linken Bereich auf das kleine Symbol.

      >

      Was siehst du hier? Nicht viel. Sortiere deshalb die Bestellungen nach der pid, nach der Produktkennung. Das gelingt durch Klick auf den entsprechenden Spaltenkopf.

      Trotzdem ist diese Anzeige noch nicht aussagekräftig genug. Dich interessieren vor allem folgende Dinge: 0 Wie viele Bestellungen gibt es pro Film? 0 Wer genau hat was bestellt?

      411

      Kapitel

      16

      Aktivitäten verwalten: Wer kommt mit ins Kino? Außerdem möchtest du statt der Film-ID und Personen-ID sicher gerne Titel und Namen wissen. Denn auch ein noch so guter Organisator hat nicht alle IDs im Kopf. COUNT() – Anzahl der Bestellungen ermitteln Alle diese Probleme lösen wir durch SQL-Abfragen, und zwar direkt in phpMyAdmin. Suche das Feld, in welchem du SQL-Befehle in deiner Datenbank ausführen kannst. Und nun probierst du einfach folgende Anweisung: SELECT COUNT(*) FROM bestellungen WHERE pid=1

      Neu ist hierbei die Funktion COUNT()

      Diese Funktion zählt alle Zeilen. Im Ergebnis wird dir mitgeteilt, wie viele Bestellungen es für den Film mit der id 1 insgesamt gegeben hat. Und tatsächlich gibt diese Befehlskette nun aus, wie viele Schüler den Film schon gebucht haben. SUM() – Summe der Bestellungen Zugegeben, für den Kartenkauf hilft dir diese Funktion nicht weiter. Es kommt durchaus vor, dass der eine oder andere Kunde gleich mehrere Karten bestellt. Schließlich dient unser Feld Anzahl diesem Zweck! Du brauchst eine andere Funktion, die Funktion SUM(). Mit dieser Funktion ermittelst du die Summe eines ausgewählten Bereichs.

      Die Funktion SUM() addiert alle Zahlen eines Feldes.

      Wir wollen die Summe der Anzahl der Bestellungen ermitteln. Und zwar nur für den Film Nr. 1. In diesem Fall schreibst du: 412

      SELECT SUM(Anzahl) FROM bestellungen WHERE pid=1

      SQL für Profis: Von Joins und Funktionen Und schon hast du in Windeseile ermittelt, wie viele Karten du besorgen musst.

      Das Abfrageergebnis besteht lediglich aus einer Zahl.

      Wie gehst du am besten in der Praxis vor? Du gibst deinen Teilnehmern einen Stichtag mit auf den Weg. Am Ende des Stichtages löschst du den entsprechenden Film einfach aus der Datenbank produkte. Dann ist es nicht mehr möglich, weitere Bestellungen anzunehmen. Und niemand kann sich hinterher beschweren!

      Tabellen durch einen Join verbinden Nun interessiert dich jedoch, wer genau hier Karten bestellt hat. Und wie viele dazu! Du willst aber nicht bei jeder aid von Hand in der Adressentabelle nachschauen. Deshalb musst du zwei Tabellen miteinander verbinden – to join, wie die Engländer sagen würden. Im Beispiel verbinden wir die Tabelle produkte mit der Tabelle adressen. Du erstellst also einen Join zwischen deinen Tabellen – und zwar ohne »t« am Ende! Wenn du zwei Tabellen miteinander verbinden möchtest, trennst du sie einfach durch ein Komma voneinander! Das Komma steht für eben diesen Join. Doch wie greifst du dann auf die Felder der einzelnen Tabellen zurück? Es könnte doch zu Missverständnissen kommen? Das gelingt, indem du den Tabellennamen notierst und dann einen Punkt setzt. Erst dann schreibst du den Feldnamen der entsprechenden Tabelle. Möchtest du das Feld Name aus der Tabelle adressen ermitteln? Dann schreibst du adressen.Name statt Name. An das Feld pid aus der Tabelle bestellungen gelangst du über bestellungen.pid! Die folgende Abfrage ermittelt, wer genau nun welche Karten für Film 1 bestellt hat. Dafür musst du mehrere Bedingungen durch AND miteinander kombinieren. 413

      Kapitel

      16

      Aktivitäten verwalten: Wer kommt mit ins Kino?

      SELECT * FROM bestellungen, adressen WHERE bestellungen.pid=1 AND bestellungen.aid=adressen.id

      Diese Befehlsfolge liest sich so: Wähle alle Zeilen aus den Tabellen bestellungen und adressen bei denen gilt: Es handelt sich um Film 1 (bestellungen.pid=1). Außerdem möchtest du aus der Tabelle adressen nur die Datensätze ausgeben, deren id in der Tabelle bestellungen auftaucht (bestellungen.aid=adressen.id). Erst mit dieser Kombination von WHERE-Klauseln sorgst du dafür, dass auch wirklich nur die Kunden aufgelistet werden, die der entsprechenden aid aus bestellungen entsprechen. Zum Ausprobieren kannst du die zweite Bedingung einmal weglassen, also den Abschnitt AND bestellungen.aid=adressen.id. Nanu, was passiert denn jetzt? Du bekommst viel mehr Zeilen zu Gesicht, wobei sich die Zeilen noch dazu dauernd wiederholen! Das liegt daran, dass deine Adressliste sicher recht lang ist. MySQL beschränkt die Anzahl der auszugebenden Adressen nicht mehr, da die zweite einschränkende Bedingung fehlt. Im Gegenteil: Das Programm wiederholt die gefundenen Einträge so lange, bis die Liste »aufgefüllt« ist. Und nun probiere einmal diesen SQL-Befehl: SELECT bestellungen.Anzahl, adressen.Name FROM bestellungen, adressen WHERE bestellungen.pid=1 AND bestellungen.aid=adressen.id

      Richtig, dieses »SQL-Monster« gibt nur die jeweilige Anzahl der Karten aus und ordnet diese der betreffenden Person zu.

      414

      Ideal: So siehst du auf einen Blick, wer wie viel bestellt hat.

      SQL für Profis: Von Joins und Funktionen Du möchtest zusätzlich noch den Namen des Filmes sehen? Dann könntest du eine SQL-Abfrage wie folgt schreiben: SELECT bestellungen.Anzahl, adressen.Name, produkte.Titel FROM bestellungen, adressen, produkte WHERE bestellungen.pid=1 AND bestellungen.aid=adressen.id AND bestellungen.pid=produkte.id

      Damit hast du gleich drei Tabellen auf einmal miteinander verbunden. Ist das nicht der Hammer? Es ist wirklich erstaunlich, wie viel man mit fortgeschrittenen SQL-Befehlen machen kann. Experimentiere ruhig ein wenig mit diesen neuen SQL-Möglichkeiten herum! Verbinde die Tabellen und frage bestimmte Kriterien ab. Nur so bekommst du die nötige Übung. Dabei ist es gar nicht schlimm, wenn bei der Abfrage etwas schief geht. Wie wäre es z. B. mit einer Berechnung des Gesamtpreises der gebuchten Tickets? Oder mit den Kosten, bezogen auf einen Nutzer?

      Ausgabe als PHP-Dokument Sicher möchtest du nicht ewig in phpMyAdmin arbeiten. Erstelle doch einmal eine PHP-Seite, in welche du die entsprechenden SQL-Befehlszeilen einbaust. Mein Vorschlag ermittelt erst einmal Anzahl und Namen der Teilnehmer für den Film mit der id 1: Ich zeige dir – wie immer – nur den Bereich zwischen den Tags . Das Dokument nenne ich im Beispiel summary.php und lege es ebenfalls im Verzeichnis order ab:

      Wer kommt mit?

      "; // while-Schleife Anfang while ($row = mysqli_fetch_assoc($result)) { echo ""; // Zeile erzeugen

      415

      Kapitel

      16

      Aktivitäten verwalten: Wer kommt mit ins Kino? // foreach Anfang: foreach ($row as $key => $value) { echo "$value \n"; } // foreach Ende echo ""; // Zeile schließen } // while Ende echo "\n"; // Tabelle schließen mysqli_close($db); ?>

      Eine einfache Tabelle gibt alle abgefragten Datensätze aus.

      Den PHP-Code kannst du inzwischen sicher gut verstehen. Wenn nicht, blättere zurück zum Kapitel 13. Es ist exakt das gleiche Prinzip, welches wir für die Ausgabe der Adressen verwendet haben.

      Schlussbemerkung Das Kapitel fing noch ganz gemütlich an, das gebe ich zu. Das Zerlegen von größeren Datenbanken in Teiltabellen klingt sinnvoll und verständlich. Doch am Schluss wurde es richtig haarig. Scheinbar genügen die paar am Anfang gelernten SQL-Befehle bei weitem nicht aus. Für »fortgeschrittenes SQL« stehen dir viele weitere Befehle, Befehlskombinationen und Funktionen zur Verfügung. Davon konnte ich dir zumindest einen kleinen Ausschnitt vorstellen.

      416

      Zusammenfassung

      Zusammenfassung 0 Du weißt, dass du große Datenbankprojekte in mehrere Teiltabellen aufteilen solltest. So vermeidest du die Doppeleingabe. Du kennst den Begriff Normalisieren, also das Zerlegen von Datenbanktabellen in Teilmodule. 0 Du kennst die Bedeutung der Primärschlüssel. Dadurch, dass ein Primärschlüssel nur einem Datensatz zugeordnet ist, kannst du ihn z. B. als Kundennummer oder Produktnummer verwenden. 0 Du weißt, dass du mit Hilfe der Primärschlüssel Relationen (Verbindungen) zwischen den Datenbanktabellen aufbaust. Du speicherst fremde Primärschlüssel als »Platzhalter« für den gesamten Datensatz. 0 Du kennst den Begriff 1:n-Beziehungen. Einem Kunden können z. B. n Bestellungen zugeordnet werden. 0 Du kennst die SQL-Funktionen COUNT() und SUM(), mit denen du Zeilen zählen und Werte zusammenrechnen kannst 0 Du kennst die Technik des Joins, also des Verbindens mehrerer Tabellen. Um zu sinnvollen Abfrage-Ergebnissen zu gelangen, musst du mehrere WHERE-Klauseln durch AND verknüpfen.

      Ein paar Fragen … 1. Welches Datenfeld nimmt man gerne für eine Kunden- oder Produktnummer? 2. Wie nennt man das Aufteilen von großen Datenbank-Listen in mehrere Teiltabellen? 3. Welche SQL-Funktion ermittelt die Summe der Werte eines Feldes?

      … und ein paar Aufgaben 1. Verändere das letzte Skript (summary.php) so, dass zusätzlich noch der Vorname des Bestellers ausgegeben wird. Speichere es unter dem Namen summary1.php. 2. Blende weiterhin den Filmtitel als Überschrift ein. Dafür schreibst du am besten eine eigene SQL-Abfrage, die die Tabelle produkte abfragt. Nenne das Dokument summary2.php.

      417

      Kapitel

      16

      Aktivitäten verwalten: Wer kommt mit ins Kino? 3. Noch eine schwere Aufgabe! Erweitere die summary.php um ein Formularfeld, in welches du die id des Filmes eingibst. Nach Abschicken des Formularinhalts soll die »Buchungsbelegung« des jeweiligen Films angezeigt werden. Denke auch an eine Überprüfung der Eingabe – es muss ein Zahlwert sein. Zeige bei Fehleingaben an: Eingabe überprüfen. Speichere unter dem Namen summary3.php.

      Frage bequem alle Filme auf »Auslastung« ab.

      4. Sorge dafür, dass Doppeleinträge in der Datenbanktabelle bestellungen zuverlässig vermieden werden. Das gelingt durch einen Unique Index, in den du die Felder aid und Datum einbeziehst.

      Das sieht der Nutzer bei einem versehentlichen Reload – aber erst nachdem du den Unique Index gesetzt hast!

      Hier zeige ich dir als kleinen Tipp den SQL-Code für diesen Unique Index. Falls du Lust hast, es mal »von Hand« zu probieren: ALTER TABLE bestellungen ADD UNIQUE ( aid, Datum )

      418

      17 Automatisch Geburtstagsgrüße versenden Jetzt kommt das Highlight des Buches! Erweitere das Adressbuch aus Kapitel 13! Füge ein Feld für den Geburtstag ein. Schicke jedem deiner Kontakte einen elektronischen Geburtstagsgruß. Per E-Mail und ganz vollautomatisch. Und natürlich ganz individuell. In diesem Kapitel zeige ich dir zum krönenden Abschluss, wie du $ eine Tabelle um ein Feld erweiterst $ einen Pseudo-Cronjob (Skriptstart per Timer) einrichtest Wie auch immer – im Endeffekt entsteht ein pfiffiges kleines System, das ganz zuverlässig Geburtstagsgrüße verschickt. Wichtig: Dieses Skript arbeitet mit der Funktion mail(). Daher funktioniert es nur auf dem Webserver des Dienstleisters. Du kannst es also nur ausprobieren, indem du das Skript vorher auf den Server lädst. Beachte weiterhin, dass dein Dienstleister das Versenden unterstützen muss.

      419

      Kapitel

      17

      Automatisch Geburtstagsgrüße versenden

      MySQL und dein Dienstleister Das folgende Skript macht offline nicht viel Sinn. Ich setze voraus, dass du dich beim Dienstleister angemeldet hast. Rufe das hier installierte Tool phpMyAdmin auf, um die Datenbank adressen zu bearbeiten. Bei welchem Dienstleister bist du angemeldet? Beim Dienstleister Neue Medien Münnich (www.all-inkl.com) wählst du www.deinedomain.de/mysqladmin

      Gib nun Benutzernamen und Passwort ein. Es sind die gleichen Daten, die du zum Einloggen in das Kundenmenü benötigst. Schon bekommst du Zugriff auf phpMyAdmin – zum Zeitpunkt des Schreibens sogar in der neuesten Version! In diesem Skript kommt wieder die Funktion mail() zum Einsatz. Ohne zusätzliche Parameter hat die Funktion Probleme mit Umlauten. (Einige dieser zusätzlichen Angaben lernst du im Praxisbuch kennen.) Aus diesem Grund kodieren wir die PHP-Seite nicht als UTF-8, sondern wieder als ISO-8859-1. Genau so, wie wir es in Kapitel 8 gehalten haben. Denke auch daran, den Zeichensatz der Datei anzupassen. In PSPad wählst du FORMAT|ANSI. In Notepad++ lautet der Befehl KODIERUNG|KONVERTIERE ZU ANSI. Zumindest in Notepad++ kannst du die Kodierung noch feiner einstellen. Wähle KODIERUNG|ZEICHENSATZ|WESTEUROPÄISCH|ISO-8859-1.

      ALTER TABLE: Neue Spalte mit ADD COLUMN Öffne die Tabelle adressen, wie im Kapitel 13 gezeigt! Füge hier die neue Spalte ein. Dazu bedienst du dich des Befehls ALTER TABLE tabellenname ADD COLUMN feldname ...

      Die neue Spalte wird dabei automatisch am Schluss der Tabelle angehangen. Das neue Feld soll im Beispiel Geburtstag heißen. Hier trägst du den jeweiligen Geburtstag ein. Du benötigst für das Datum eine Länge von 10 Zeichen. Im Beispiel lautet der komplette SQL-Befehl also folgendermaßen: 420

      ALTER TABLE adressen ADD COLUMN Geburtstag VARCHAR(10)

      Vorüberlegung: Pseudo-Cronjob einrichten

      Einfügen einer neuen Spalte, hier in einer neuen Version von phpMyAdmin.

      Trage nun die Geburtstage ein. Wähle folgendes Format: TT.MM.JJJJ

      Im Klartext: Die Tages- und Monatszahl muss stets zweistellig angegeben werden. Und zwar mit einer führenden Null wie 01.07.1970. Das Jahr bekommt dagegen vier Stellen! Als Trenner zwischen den Werten dient der Punkt. Behalte dieses Format bei, denn das Skript basiert auf dieser Schreibweise. Wir verwenden deshalb den Punkt als Trenner, um das Datum später mit der Funktion explode() in seine Einzelteile zerlegen zu können.

      Vorüberlegung: Pseudo-Cronjob einrichten Das war’s im Prinzip schon. Nun folgen ein paar Vorüberlegungen und danach zeige ich dir mein Skript. Was muss das Geburtstags-Skript können? Nicht viel: Das Skript soll die Adressdatenbank einmal täglich nach Geburtstagen durchforsten. Bei einer Datumsübereinstimmung verschickt das Skript je zwei E-Mails. Eine E-Mail an das Geburtstagskind und eine Erinnerungsmail an dich. Denn nichts ist peinlicher, als wenn sich das Geburtstagskind für die Glückwünsche bedankt und du mal wieder überhaupt keine Ahnung hast. So weit, so gut. Bleibt ein Haken übrig. Wie bringst du das Skript dazu, einmal am Tage deine Datenbank abzuklappern? Zu diesem Zweck benötigst du eigentlich einen sogenannten Cronjob. 421

      Kapitel

      17

      Automatisch Geburtstagsgrüße versenden

      Ein Cronjob ist ein Skript, das zu einer bestimmten Zeit (Cronos ist griechisch und heißt Zeit) automatisch gestartet wird. Es ist eine Art Timer, der z. B. täglich 02:00 Uhr dein Geburtstagsskript ausführt. Der Haken: Die meisten Webhoster erlauben es dir nicht, solche Cronjobs einzurichten. Der Grund ist einfach: Cronjobs werden direkt auf dem Server ausgeführt und können diesen komplett lahm legen, wenn dein Skript fehlerhaft ist. Ich vermute mal, dass dir – genau wie mir – keine Cronjobs zur Verfügung stehen. Was machen wir da? Meine Idee: Platziere das Skript unsichtbar auf irgendeiner Seite deiner Präsenz. Auf einer möglichst häufig besuchten Seite. Sobald ein Besucher kommt, wird dein Skript aufgerufen. Sobald ein Besucher kommt, wird das Skript aufgerufen? Gibt es dann bei 20 Besuchern 20 Geburtstags-Mails? Natürlich nicht! Wir halten den ersten Aufruf des Tages fest, indem wir den aktuellen Wochentag in einer Textdatei speichern. Das Skript vergleicht beim nächsten Mal, ob dieser Wochentag schon eingetragen ist. So sorgen wir dafür, dass das Skript pro Tag nur ein einziges Mal aufgerufen wird. Es wird praktisch durch den ersten Besucher ausgelöst! Zugegeben, eine genaue Zeitsteuerung lässt sich damit nicht erreichen. Trotzdem sorgen wir dafür, dass das Skript einmal pro Tag startet. Einzige Voraussetzung: Mindestens ein Besucher verirrt sich auf deine Seite. Oder du rufst deine Seite im Zweifelsfalle selber auf, indem du sie besuchst.

      So klappt’s: Das GeburtstagsSkript Genug der Vorbemerkungen! Zeit, dass ich dir den kompletten Quelltext präsentiere. Es gibt weder Neuerungen noch irgendwelche Besonderheiten.

      Textdatei tag.txt Zuerst richtest du eine normale Textdatei ein. Tippe am besten den Wochentag von gestern ein. Oder irgendeinen anderen Wochentag außer dem heutigen. Wenn heute der 12. Mai ist, schreibst du eine 11. 422

      So klappt’s: Das Geburtstags-Skript Diese Datei nennst du tag.txt und lädst sie auf den Server. Denke auch an den schon oft besprochenen Befehl chmod zum Aufheben des Schreibschutzes, siehe Seite 254.

      Include-Datei zugriff.inc.php Weiterhin brauchen wir die schon aus den vorigen Kapiteln bekannte Include-Datei zugriff.inc.php. Dort liegen deine aktuellen MySQL-Zugangsdaten. Lade sie mit auf den Server. Entferne jedoch vorher Zeile 2, damit der Zeichensatz der MySQL-Verbindung auf ISO-8859-1 bleibt.

      Der Quelltext Doch nun zum Hauptjob. Ich zeige dir das komplette Skript im Überblick. Baue es in eine deiner am stärksten besuchten PHP-Seiten ein. An welcher Stelle? Das ist egal! Packe das Skript praktisch an eine beliebige Stelle. Schließlich arbeitet das Programm vollkommen im Hintergrund, der Besucher der Seite bekommt davon nichts mit!
      423

      Kapitel

      17

      Automatisch Geburtstagsgrüße versenden // Betreff für sich selbst $betreff2 = "Geburtstagsmail verschickt an:"; // Nur die wichtigen Felder abfragen $sql = "SELECT Vorname, Name, EMail, Geburtstag FROM adressen ORDER BY Geburtstag"; $result = mysqli_query($db, $sql); $zeilen = mysqli_num_rows($result); // alle Zeilen der Tabelle durchgehen: while ($row = mysqli_fetch_assoc($result)) { $geb = explode(".", $row["Geburtstag"]); if ($geb[0] == $tag && $geb[1] == $monat) { $alter = $jahr - $geb[2]; // Text der E-Mail $mailtext = "Hallo $row[Vorname] $row[Name]!\n\n" . "Ich gratuliere dir sehr herzlich zu deinem\n" . "$alter. Geburtstag und wünsche dir viel Glück\n" . "und alles Gute im persönlichen als auch im\n" . "beruflichen Leben!\n\n" . "Bleibe gesund!\n\n" . "Dein Johann-Christian :-)"; // Mails verschicken, inkl. Kontrollmail if (mail($row["EMail"], $betreff1 , $mailtext, "From: $absender")) { mail($absender, "$betreff2 $row[Vorname] $row[Name]", $mailtext, "From: $row[EMail]"); } // if Mail schließen } } // while schließen mysqli_close($db); } // if writemail schließen ?>

      Das Skript kurz erläutert Wollen wir das Beispiel gemeinsam kurz noch einmal durchgehen? Im ersten Teil ermittle ich die aktuelle Zahl des Wochentags, und zwar zweistellig. Dafür sorgt die Zeile $tag = date("d"); Danach wird die Datei tag.txt geöffnet und der Wert aus dieser Datei wird in der Variablen $aw gesichert. In einer if-Abfrage vergleiche ich den aktuellen Wochentag aus $tag mit diesem Wert. Nur wenn es keine Übereinstimmung gibt, wird die Flag-Variable $writemail auf true gesetzt. Dann wird gleichzeitig der aktuelle Tag in die Datei tag.txt geschrieben. 424

      So klappt’s: Das Geburtstags-Skript

      Stelle dir eine Flag-Variable wie ein kleines Fähnchen vor, das du im Erfolgsfalle hisst. Im Misserfolgsfalle bleibt die Fahne einfach unten. Diese »Schalterstellung« liest du später aus und reagierst darauf. Im Buch hast du die Technik mit den Flag-Variablen übrigens schon häufig genutzt. Ich wollte das Kind an dieser Stelle nur noch einmal beim Namen nennen! Bei einer Übereinstimmung beider Werte lautet der Wert von $writemail dagegen false. Das Skript wurde an diesem Tag also schon ausgeführt! Die nächsten Zeilen sind auch nicht weiter kompliziert. Nur wenn $writemail auf true steht – wenn also das Skript an diesem Tag noch gar nicht durchgeführt wurde – wird der Hauptteil ausgeführt: if ($writemail) {. Dann definieren wir einige weitere Variablen, ermitteln den aktuellen Monat, das Jahr, schreiben unsere Absender-Adresse ein, bereiten den Betreff vor usw. usf. Schaue einfach in meine PHP-Kommentare. Interessant ist, dass wir bei der SQL-Abfrage nicht alle, sondern nur die wichtigen Datenbankfelder ermitteln müssen. Im Beispiel sieht der SQL-Befehl deshalb so aus: $sql = "SELECT Vorname, Name, EMail, Geburtstag FROM adressen ORDER BY Geburtstag";

      Der Rest dürfte aus den vorigen Kapiteln bekannt sein. Zusätzlich kommt die ebenfalls schon in Kapitel 11 besprochene Funktion explode() zum Einsatz $geb = explode(".", $row["Geburtstag"]);

      Diese Funktion zerlegt das Datum aus dem Feld Geburtstag anhand des Trennzeichens in Tag, Monat und Jahr. Auf den Wochentag kann ich so z. B. mit $geb["0"] zurückgreifen, auf den Monat mit $geb["1"] usw. Nun erfolgt ein simpler Vergleich. Gibt es eine Übereinstimmung von Wochentag und Monat? Dann – und nur dann – wird die Geburtstagsmail verschickt, und zwar gleich mit einer Kopie an dich selbst. Damit es besonders persönlich wirkt, berechnet das Skript das Alter des Jubilars, speichert es in der Variablen $alter und gibt es mit aus.

      425

      Kapitel

      Automatisch Geburtstagsgrüße versenden

      17

      Das Skript erzeugt zwei Mails: Eine an das Geburtstagskind und eine an dich.

      Hehe, ganz schön clever, findest du nicht?

      Schlussbemerkung Du hast es geschafft! Das Buch ist damit zu Ende. Mir hat es Spaß gemacht, und dir? An dieser Stelle möchte ich dich zum Ausprobieren ermutigen! Lerne noch mehr PHP, beschäftige dich intensiver mit MySQL. Hinterfrage die Lösungen aus diesem Buch, denn vieles kann man noch besser machen oder anders lösen. Du hast ein besonders gutes Skript erstellt? Du hast eine bessere Lösung für eine Problemstellung gefunden? Her damit! Hund Buffi, Nele, Tim (die Kinder links und rechts am Seitenkopf) und Autor Hanke freuen sich sehr über dein Feedback: Surfe zu www.phpkid.de und teile uns deine Meinung mit. Vielen Dank und weiterhin viel Spaß mit PHP und MySQL. Und denke daran: Es gibt wichtigere Dinge im Leben als Computer … und eine Fortsetzung zu diesem Buch.

      Und zum Schluss noch ein Sicherheitstrick! Wie wichtig Sicherheit auf Webseiten ist, habe ich dir im Laufe des Buches immer wieder vermittelt. Manchmal geben schlampig programmiert Skripte sogenannte Notices aus, wir hatten uns darüber ja schon auf Seite 146 unterhalten. In vielen Fällen erscheinen aber auch richtig heftige Fehlermeldungen.

      426

      Das ist gut für dich als Skriptautor. So weißt du, an welcher Stelle das Problem liegt. Das ist aber nicht gut für die Sicherheit, denn auch Hacker

      Zusammenfassung bekommen durch diese Meldungen wertvolle Hinweise auf Variablen, Pfade und andere Interna. Schiebe dem einen Riegel vor. Es gibt eine ganz einfache Lösung! Notiere am Anfang eines jeden PHP-Skripts folgende Codezeile: error_reporting(0);

      Dadurch wird die Anzeige jeglicher Fehler im Skript ausgeblendet! Das erspart auch das Setzen des Klammeraffen @ vor den Funktionsnamen. Auf deinem lokalen System jedoch machst du es genau andersherum. Schreibe einfach error_reporting('E_ALL');

      Das blendet die Anzeige aller Meldungen ein, also auch der Notices. So wirst du vor schlampigem Programmieren bewahrt. Vergiss jedoch keinesfalls, diese Zeile vor dem Hochladen auf den Webserver durch error_reporting(0); zu ersetzen!

      Zusammenfassung 0 Du kennst den SQL-Befehl zum Einfügen einer neuen Spalte. Die Syntax lautet: ALTER TABLE tabellenname ADD COLUMN feldname ...; 0 Du weißt, wie du einen Cronjob simulieren kannst. Baue das Skript in eine Seite ein, die häufig aufgerufen wird. Sorge durch eine Sperre dafür, dass das Skript aber nur einmal pro Tag startet. 0 Du hast gelernt, dass du mit der Zeile error_reporting(0); die Anzeige aller Fehlermeldungen unterdrücken kannst.

      Ein paar Fragen … 1. Was ist ein Cronjob, was bedeutet das Wort Cronos? 2. Warum werden Cronjobs normalerweise nur in sehr teuren Paketen zur Verfügung gestellt? (Und oft auch erst, nachdem dein Dienstleister dein Skript überprüft hat?) 427

      Kapitel

      17

      Automatisch Geburtstagsgrüße versenden

      … und ein paar Aufgaben 1. Noch ist das Skript nicht perfekt! Du hast einen Geburtstag eingegeben, aber die Person besitzt keine E-Mail-Adresse? Dann macht das Verschicken von Geburtstagsgrüßen auch nicht viel Sinn. Fange diesen zusätzlichen Fall ab. Das Skript soll die Mail nur dann versenden, wenn das Feld EMail nicht leer ist. 2. Passe das Skript auch weiterhin auf deine Bedürfnisse an. Dir gefällt die Anrede Hallo Vorname Name nicht? Nimm den Nachnamen einfach weg. 3. Zum Schluss habe ich noch eine Aufgabe. Bilde dich weiter. Lies beispielsweise das PHP-Manual. Du findest es als Hilfedatei auf der CD zum Buch unter dem Pfad dokumente/php_manual.

      428

      Anhang A Für Eltern und Lehrer Ihr Kind will programmieren lernen? Fürs Internet? Großartig! Dabei sollten Sie es unbedingt unterstützen! 0 Ihr Kind lernt das logische Denken. 0 Ihr Kind bereitet sich in idealer Weise auf das Berufsleben vor. 0 Programmieren macht ungeheuer viel Spaß. (Und das ist und bleibt wohl doch das Wichtigste!) Helfen Sie Ihrem Kind bei der Installation eines lokalen Webservers. Natürlich nur, falls sie oder er es nicht schon selber schafft. Denn in manchen Dingen ist uns die Jugend von heute doch schon weit voraus. Vielleicht wollen Sie ja selber etwas PHP lernen und lassen sich von Ihrer Tochter oder Ihrem Sohn hier und da etwas helfen? Sie unterrichten Programmiersprachen an der Schule? Oder an einer anderen Bildungseinrichtung? Ich habe das Buch extra als Unterrichtsmaterial verfasst. Ich hoffe, dass Sie genug Beispiele und Übungen für möglichst spannenden und kurzweiligen Unterricht vorfinden. Egal ob im Unterricht oder für das Selbststudium: In diesem Buch lernt der Nachwuchs (und dabei ist die Altersgrenze nach oben hin durchaus fließend!), wie dynamische und datenbankgestützte Webseiten entstehen. Das ist wichtig, denn längst setzen die meisten großen Internet-Portale auf diese Technik. Sie investieren also in die Zukunft Ihrer Tochter, Ihres Sohnes oder Ihrer Schulklasse. (Oder in Ihre eigene!) Apropos investieren. Vielleicht sind Sie ja auch bereit, die monatlichen Kosten für einen Dienstleister zu tragen, der PHP unterstützt? Denn manche der in diesem Buch beschriebenen Programme funktionieren nur dann, wenn sie auf dem Webserver eines PHP-fähigen Dienstleisters ausgeführt werden. Ihr Kind wird schon wissen, was es sich in dieser Beziehung wünscht. Bei aller Begeisterung habe ich zum Schluss noch eine kleine Bitte: Achten Sie auch darauf, dass Ihr Programmiernachwuchs genügend frische Luft bekommt. Wer zu lange vor dem Computer hockt, bekommt eckige Augen 429

      Anhang

      A

      Für Eltern und Lehrer und verliert den Kontakt zur Realität. Glauben Sie mir, es gibt wichtigere Dinge im Leben als Computer. Ihr Johann-Christian Hanke www.phpkid.de

      430

      Anhang B Hochladen der Seiten mit FTP Du möchtest deine PHP-Seiten auf den Server laden? Nichts einfacher als das! Zum Hochladen benötigst du ein FTP-Programm. FTP ist die Abkürzung für File Transfer Protocol. Es handelt sich um das Übertragungsverfahren von Dateien zwischen dem Webserver und deinem lokalen PC. Das wohl bekannteste Programm dieser Art heißt FileZilla. Wir haben dir FileZilla mit auf die CD gepackt. Schaue in den Ordner programme/filezilla und gehe in den Unterordner für dein Betriebssystem. Die Installation sollte schnell und problemlos vonstatten gehen. Doppelklicke in Windows auf die entsprechende Exe-Datei – es ist die Datei FileZilla_3.2.7.1_win32-setup.exe. Folge den einfachen Schritten.

      Das Grundprinzip zum Veröffentlichen Zuerst zu den Grundlagen! Jeder Dienstleister gewährt dir einen FTPAccount. Also ein Konto, mit dem du Zugriff auf deinen Webspace bekommst und Dateien hochladen kannst. Du bekommst also 0 Benutzernamen (User-ID) 0 Passwort Du nutzt diese Angaben, um dich mit dem Dienstleister zu verbinden. Hoppla, du kennst deinen Benutzernamen und das Passwort nicht? Normalerweise findest du diese Daten z. B. im Konfigurationsmenü deiner Webpräsenz. Oder auf den Serviceseiten des jeweiligen Dienstleisters. Im Zweifelsfalle rufst du einfach die Hotline deines Webhosters an!

      431

      Anhang

      B

      Anhang B

      FileZilla konfigurieren Ich gehe nun davon aus, dass du die Daten deines FTP-Accounts kennst. Konfiguriere mit diesen Daten dein FTP-Programm, im Beispiel FileZilla.

      >

      Klicke auf die Schaltfläche ÖFFNET DEN SERVERMANAGER. Es ist die Schaltfläche ganz links.

      >

      Das Dialogfenster Servermanager erscheint. Wähle die Schaltfläche NEUER SERVER, du findest sie im unteren Bereich. Links oben erscheint ein Symbol mit dem Platzhalternamen Neuer FTP-Server.

      >

      Vergib einen eigenen Namen. Achte darauf, dass der eben erzeugte Platzhaltername markiert ist. Klicke auf die Schaltfläche UMBENENNEN. Der Dateiname »öffnet sich«. Tippe dort einen frei wählbaren Namen ein, beispielweise den Namen deiner Domain. Klicke neben das Feld, damit der Name zugewiesen wird.

      >

      Richte nun mit den Daten deines FTP-Accounts den Zugang ein. Fangen wir mit dem obersten Feld an: Bei SERVER muss in der Regel dein Domainname stehen. Und zwar nach folgendem Schema: www.deinedomain.de

      >

      So ist das beispielsweise bei der Firma Neue Medien Münnich (www.all-inkl.com), aber auch bei Hostern wie der 1&1 GmbH (www.1und1.de).

      >

      Bei MultiMania dagegen gibst du im Feld SERVER Folgendes ein: ftp.mitglied.lycos.de

      432

      >

      Das Feld SERVERTYP lässt du so. Dort muss FTP – File Transfer Protocol stehen. Wähle bei VERBINDUNGSART außerdem noch die Einstellung Normal.

      >

      Jetzt wird dein Benutzername benötigt. Trage in das Feld BENUTZER die entsprechende Zeichenfolge ein. Welche, musst du schon selber wissen.

      >

      Nun folgt dein geheimes PASSWORT. Hier werden dir beim Eintragen nur Sternchen angezeigt.

      >

      Wenn du magst, kannst du im Feld KOMMENTARE noch eine kurze Beschreibung zu diesem Zugang eintragen. Nötig ist das jedoch nicht.

      >

      Klicke auf die Schaltfläche OK, damit die Daten gespeichert werden.

      Hochladen der Seiten mit FTP

      So richtest du FileZilla für den Dienstleister MultiMania ein.

      So einfach hast du die Verbindung schon eingerichtet. Auf Wunsch kannst du nun weitere Konten anlegen. Klicke dafür wieder auf die Schaltfläche ÖFFNET DEN SERVERMANAGER.

      Hochladen live: FTP-Verbindung herstellen So, nun geht es ans Hochladen der Dateien. Das ist ganz einfach. FileZilla ist bei dir geöffnet? Sehr gut! Wähle nun die gewünschte FTP-Verbindung aus. Auch das gelingt über die Schaltfläche SERVERVERWALTUNG ÖFFNEN. Klicke diesmal jedoch nicht direkt auf die Schaltfläche – du willst ja keinen neuen Zugang einrichten. Wähle den kleinen Pfeil rechts neben dieser Schaltfläche. Nun klappen alle Zugänge herunter, die du schon eingerichtet hast.

      Klicke auf den kleinen Pfeil und wähle die gewünschte Verbindung aus.

      433

      Anhang

      B

      Anhang B Das FTP-Programm verbindet sich nun mit dem Server. Du kannst auf dein Verzeichnis zugreifen. Im linken Bereich siehst du stets den Inhalt der lokalen Festplatte. Im rechten Bereich hast du Einblick auf deine Daten auf dem Server.

      Die richtigen Dateien markieren Welche Dateien willst du auf den Server spielen? Bewege dich im linken Bereich in deinen Projektordner. Navigiere ähnlich wie im WindowsExplorer. Doppelklicke einfach auf den gewünschten Ordner, um ihn zu öffnen. Du möchtest eine Ordnerebene nach oben? Dann doppelklickst du stattdessen auf den obersten Ordner, auf den mit den zwei Punkten! Nun markierst du die entsprechende Datei, die du hochladen möchtest. Du kannst auch mehrere Dateien und Ordner gleichzeitig markieren. Klicke auf die erste Datei. Drücke nun die (ª)-Taste, halte sie gedrückt. Wähle jetzt die letzte Datei durch Anklicken aus. Automatisch werden alle dazwischen liegenden Dateien gleich mitmarkiert. Das Auswählen nicht zusammenhängender Dateien und Ordner dagegen gelingt bei gedrückter Taste (Strg).

      Von links nach rechts: Dateien hochladen Und wie spielst du nun die Dateien auf den Server? Ganz einfach: Durch Ziehen mit der Maus! Beachte zuerst, dass rechts der Ordner eingestellt ist, den der Dienstleister als Stammordner für dich zugewiesen hat. Bei MultiMania und Neue Medien Münnich musst du nichts verstellen. Hier ist es der voreingestellte Ordner. Bei der Domainfactory (www.domainfactory.de) musst du dagegen im rechten Bereich erst den Ordner webseiten aufrufen. Manchmal heißt der Ordner auch htdocs oder www.

      434

      Hochladen der Seiten mit FTP Alles bereit zum Hochladen? Du hast links die richtigen Dateien und/oder Ordner markiert? Ziehe den markierten Packen per Maus nach rechts und lasse die Maustaste los.

      Überspiele selbst komplette Ordner mit der Mauszugtechnik Drag & Drop.

      Kurz danach ist die Seite abrufbereit. Teste, ob die Links stimmen und die Grafiken angekommen sind! Ziehe gerne auch mehrere Ordner auf einmal mit Drag & Drop auf den Server. Von links nach rechts. Und sogar vom Windows-Explorer aus. Probiere es einfach aus! Beachte: Wenn du eine Datei ein zweites Mal hochlädst, wird die alte Version automatisch überschrieben.

      Tipps und Tricks zu FileZilla Und, hat es geklappt? FileZilla arbeitet wie ein Datei-Manager: Links siehst du den Inhalt deiner lokalen Festplatte. Rechts bekommst du Einblick in die Dateien/Ordner auf dem Server. Zum Navigieren in höher oder tiefer gelegene Ordner doppelklickst du so lange auf die entsprechenden Ordner bzw. den Ordner mit den zwei Punkten, bis du auf der gewünschten Ebene angekommen bist!

      435

      Anhang

      B

      Anhang B

      Sortieren nach Alphabet, Größe oder Datum Beachte auch die Spaltenköpfe, denn du kannst sie zum Sortieren verwenden! Du möchtest feststellen, welche Datei die neueste oder älteste ist? Du willst deine Dokumente nach Alphabet oder Größe sortieren? Klicke auf den betreffenden Spaltenkopf. Ein erneuter Klick dreht die Sortierreihenfolge wieder um!

      Ordner erstellen Du möchtest dagegen einen neuen Ordner auf deinem Webserver anlegen? Das gelingt durch Rechtsklick in einen freien Bereich. Wähle den Befehl VERZEICHNIS ERSTELLEN.

      Daten löschen Du möchtest eine Datei oder einen kompletten Ordner löschen? Markiere das Element im rechten Bereich. Drücke die Taste [Entf]. Das Löschen eines Ordners gelingt nicht? Beachte, dass der zu löschende Ordner in manchen Fällen erst leer sein muss. Sonst verweigert FileZilla manchmal das Löschen. Lösche dann ggf. erst alle Dateien in diesem Ordner. Probiere das Löschen des Ordners danach erneut!

      436

      Anhang C Empfehlenswerte PHP-Editoren Klar, ich bin ein Fan von PSPad. Dem Editor, den ich im Buch vorgestellt habe. Doch vielleicht bevorzugst du ein anderes Programm?

      Aptana Studio Aptana Studio ist für viele Profis erste Wahl, weil es so einen enormen Funktionsumfang besitzt. Und das Beste: Es läuft auch auf dem Mac oder am Linux-PC. Die Bedienung ist ähnlich komfortabel wie die von PSPad. Ich habe dir Aptana Studio auf der CD unter programme/aptana abgelegt, im Internet findest du es unter www.aptana.org/studio.

      Notepad++ Du magst es schlank und schnell? Dann empfehle ich dir das WindowsProgramm Notepad++. Es besitzt zwar längst nicht so viele Features wie Aptana Studio oder PSPad, aber es erfüllt seinen Zweck: hervorragende Farbhervorhebung, Zeilennummerierung, Tools zum Konvertieren in UTF-8 und ANSI, eine Automatik zur Anzeige von Klammernpaaren usw. Besonders wertvoll: Rechtsklicke auf die PHP-Datei im Windows-Editor und wähle EDIT IN NOTEPAD++. Die Heimatseite von Notepad++ findest du unter http://notepad-plus.sourceforge.net/de/site.htm.

      Weaverslave Bis vor kurzem war ich noch ein großer Fan von Weaverslave, dem PHPEditor von Thomas Weinert aus Köln. Besonders gut gefällt mir hier die Farbhervorhebung, HTML- und PHP-Bereiche lassen sich deutlicher voneinander unterscheiden als in anderen Editoren. Leider unterstützt Weaverslave kein Unicode, du kannst also keine in UTF-8 kodierten Dateien bearbeiten. Das Programm liegt auf der CD unter programme/weaverslave.

      PHPEdit Außerdem habe ich dir einen »Oldtimer« auf CD gelegt, die FreewareVariante von PHPEdit aus Frankreich. Mir gefällt das Programm deshalb so gut, weil es den PHP-Code automatisch einrückt. Es liegt unter dem Pfad programme/phpedit. Die allerneuste (kommerzielle) Version von PHPEdit bekommst du unter www.phpedit.com. 437

      Anhang

      c

      PHP und MySQL lernen

      PHP und MySQL lernen Du möchtest mehr erfahren über PHP? Du suchst tolle Web-Ressourcen zum Nachschlagen?

      Umfangreiche Referenz auf SELFPHP Kennst du die SELFPHP? Es handelt sich um ein hervorragendes, ganz umfangreiches Nachschlagewerk zu allen Befehlen und Funktionen von PHP. Surfe zu www.selfphp.de und schau dich um.

      Die offizielle PHP-Seite Die offizielle PHP-Seite findest du unter www.php.net. Dort gibt es viele Informationen zu neuen PHP-Versionen und Foren, wo du um Rat nachsuchen kannst. Leider sind die meisten Seiten auf Englisch.

      Das offizielle PHP-Handbuch Du suchst einen alternativen Funktions- und Befehlsüberblick? Dann empfehle ich dir die deutsche Übersetzung des offiziellen PHP-Handbuchs! Du findest diesen Text zum einen auf der CD, zum anderen auf: 0 www.php-homepage.de/manual Du möchtest dir das Dokument direkt auf den PC herunterladen, und zwar in der neuesten Fassung? Dann surfe doch einmal zu folgender Adresse: 0 www.php.net/download-docs.php Hier findest du dieses Handbuch z. B. als HTML-Version, als PDF-Dokument und als Version für den Palm Pilot. Ich nutze dieses Handbuch sehr gerne zum Nachschlagen! Dabei greife ich stets auf die handliche Version im HTML-Help-Format zurück. Du findest sie auch auf der Buch-CD unter dem Pfad dokumente\php_manual.

      Das offizielle MySQL-Handbuch Du möchtest dich intensiver mit MySQL, seinen Möglichkeiten, Datentypen und Problemen beschäftigen? Dann steht dir unter folgender Adresse das ins Deutsche übersetzte offizielle Handbuch zur Verfügung: 0 http://dev.mysql.com/doc/refman/5.1/de/ 438

      Stichwortverzeichnis $ ! 162 $_COOKIE 242 $_GET 141 $_POST 141 $_SERVER['PHP_SELF'] 164 .htaccess 342 { } 117 ++ 158 == 119

      A Abbruchbedingung für Schleifen 194 Absatz 36 action 140 ACTION 61 ADD COLUMN 420 Addieren der Bestellungen 412 addslashes() 351 Adressdatei 295 Adress-Datenbank erweitern 420 Adressen eintragen 307 Aktualisieren von Datensätzen 316 All-inkl.com 73 ALTER TABLE 420 and 121 Apache installieren 75 installieren, Windows XP/2000 76 Vorteile 75 Array $_POST 230 Arrays 134 assoziativ 129 assoziative Formulardaten 141 aus kommaseparierter Textdatei 266, 274 Datensätze als assoziatives Array 321

      einzelner Index-Wert 130 Elemente zählen 128 foreach 195 für Cookies 242 für Tage 126 Index-Wert 126 Kurzform 128, 131 Überblick 125 assoziative Arrays 129 für Cookies 242 Aufgabenteilung JavaScript und PHP 231 Aufzählungspunkte 43 Austauschen von Zeichen 218 Auswahl begrenzen 315 auto_increment 297

      B Back-Button nachbilden 388 Backslash als Escape-Zeichen 103 Backslashes entfernen 211 Begrenzen der Artikellänge 383, 384 Begrüßung nach Tagsezeit 124 Berechnungen 157 Bestellsystem 391 Bestell-Tabelle 396 Bestellungen anzeigen 403 Beziehungen zwischen Tabellen 413 Bild in HTML einfügen 40 Blöcke markieren 117 Blog 366 Bloggen 366 BODY 36 Bold 38 Bookmark 141 break 194 Break 39 Breite mit width 57 Browservorschau 35 Bruchzahlen, Dezimaltrenner 161

      439

      Stichwortverzeichnis

      C CAPTCHA Bildchen 291 per Berechnung 343 CHAR 305 chmod 253 chmod 666 254 chmod 777 254 CMS 365 Content Management System 365 Cookies Ablaufdatum 244 als assoziatives Array 242 Einführung 235 Einstellungen 239 für Passwortschutz 377 für Umfrage 272 Lebensdauergarantie 243 löschen 245 setzen 241 Sicherheitsrisiko? 236 sind problematisch 238 Speicherort 237 Zählstopp für Counter 256 count() 128 COUNT() 412 Counter 247 mit Zählstopp 256 CREATE TABLE 302 Cronjob 421, 422 CSS 49 Attribute und Werte 52 Breite festlegen 57 Datei erstellen 51 Kommentare 55 Musterbeispiel 55

      D 440

      DATE 306 DATE und VARCHAR() 336 date() 112, 133 Datei anzeigen 284 Datei auslesen 284

      Dateien am Trennzeichen zerlegen 266 Arbeit mit 247, 266 auf Webserver überführen 434 Modus 250 Dateiendung manipulieren 153 Dateiendungen einblenden 28 Dateigröße ermitteln 265 Dateizeiger 250 Daten ausgeben 90 Datenbank anlegen 299 Datenbankfelder 301 Datensätze 296 Datentypen 304, 305 Feldnamen 296 phpMyAdmin 298 Planung 296 Speicherordner 309 Überblick 295 Datenbank aufteilen 395 Datenbank und Datenbanktabelle 296, 299 Datenbank, Spalte hinzufügen 420 Datenbankdesign, schlechtes 396 Datenbankfelder definieren 301 Datenbanktabelle für Gästebuch 336 Datenbanktabellen, mehrere 395 Datenbanktabellen, Relationen 398 Datensätze als Tabelle ausgeben 325 bei MySQL-Tabellen 296 entfernen 316 mit while ausgeben 321 per Formular eingeben 328 sortieren 315 updaten 316 zählen 323 Datentypen 96 Datentypen für MySQL 304, 305 DATETIME 306 Datum 111 Datum komplett auf Deutsch 135 Datum mit PHP ausgeben 204 Datumsformate 113 Dekrementieren 158

      Stichwortverzeichnis DELETE 316 Dezimaltrenner bei Bruchzahlen 161 Diagramm 267 für Umfrage 267 Diagramm aus Säulen 169 die() 275 Dienstleister 71 DIV 58, 340 do while 189 Dokumenttyp-Deklaration 33 Domain, eigene 73 Doppeleinträge verhindern 286 DOUBLE 306 Dreisatz 268 DTD 33

      E echo 108 Anweisung zur Datenausgabe 90 mit HTML aufbessern 96 Einbinden von Dateien 151 Eingabe und Ausgabe von Datensätzen 330 Eingabeformular für Gästebuch 343 Einrückung 370 Eintragen von Datensätzen 307 else 116 elseif 123, 124, 134 Eltern, Hinweise für 429 E-Mail bei Besuch der Seite 203 Fehler unterdrücken 207 versenden mit PHP 202 E-Mail-Adresse auf Gültigkeit prüfen 222 empty() 162 Endlosschleife 188 Endungen einblenden 28 Entscheidungsstruktur if-else 116 error_reporting 426 Escapen 103 Euro-Zeichenfolge für Zahlen 168 explode() 266

      F Fallunterscheidung 148 Fallunterscheidung mit switch 147 Farben zuweisen 53 fclose() 253 Feedback 426 alle Felder ausgefüllt? 212 Name-Feld 210 über mail() 202 Universal-Formmailer 227 Feedback-Formular 205 Fehler einkreisen 338 Fehlermeldungen anzeigen 426 Fehlermeldungen bei SQL 304 Fehlermeldungen unterdrücken 323 Fehlermeldungen vermeiden 106 Fehlertext ausgeben 216 Felddatentypen 304, 305 Feldnamen 296 Feldnamen festlegen 301 Feldnamen, Regeln zur Benennung 297 Feldvariablen 125 fgets() 251 file pointer 250 filesize() 265 FileZilla Ordner erstellen 436 Programm zum Veröffentlichen von HTML-Seiten 431 Tipps und Tricks 435 Filtern 313 Flag-Variable 214, 425 Float 96 FLOAT 306 Flooding 225 fopen() 249 for 358, 359 foreach 195, 230 foreach() 325, 327 Formmailer, universaler 227 Formular erstellen 138 für Passwort 138 versenden 139

      441

      Stichwortverzeichnis Formular-Bereich für Kommentare 205 Formulare in HTML 59 Formularfelder, Werte speichern 173 Formularinhalt an sich selbst schicken 164 Formularinhalt wird gelöscht 216 Formulartest mit JavaScript 231 Formularvalidierung mit JavaScript 231 for-Schleife 190 for-Schleife, Schritt für Schritt 190 for-Schleife, Zählmuster 191 fputs() 253 fread() 265 FTP chmod für Textdatei 253 Konfiguration 432 Tripod 432 zum Veröffentlichen von Webseiten 431 Funktion zur Reload-Sperre 287 Funktion, Gültigkeit der Variablen 290 Funktionen Argumente 175 auslagern mit include() 179 Drei Argumente 178 Grundsyntax 176 in PHP 174 Leerzeichen nach Komma 175 Variablengültigkeit 177 vordefinierte 175

      G

      442

      Gänsefüßchen, richtig verschachteln 107 Gästebuch 279 Ausgabe sortieren 340 Datenausgabe mit SQL 338 Datenbanktabelle 336 Datensätze durchnummerieren 356 Eingebeformular 343 Einträge nummerieren 341 exakte Breite 340 mit MySQL 335

      Seitenweise Ausgabe 354, 357 Gästebuch, Datensicherung in Datei 280 Gästebuch, Doppeleinträge verhindern 286 Gästebuch, Hacking-Versuche unterbinden 283 Gästebuch, neueste Einträge zuoberst 285 Gästebucheintrag SQL 344 Geburtstagsgrüße 419 Gestalten mit Formatvorlagen 49 get 140 get_magic_quotes_gpc() 353 Geteilt 158 GET-Methode 355 GET-Parameter 374, 377 gleich 120 Gleichheit 119 Gliedern durch Leerzeilen 370 Grafik in HTML einfügen 40 größer als 120 Grundrechenarten 158 guestbook.php 343

      H Hacking in Gästebuch unterbinden 283 Hallo Welt 91 HEAD 33 heredoc 380, 381 heredoc, Notation 381 heredoc, Probleme 381 Hintergrundgrafik 371 history.back() 388 Hochladen mit FTP 433 Home-Link 374 Hovereffekt für Hyperlinks 57 htaccess 154 HTML 30 Body 36 Farben 53 fett und kursiv 38

      Stichwortverzeichnis Formatvorlagen 49 Formulare 59 Grafik einfügen 40 Head 33 Hyperlinks 45 Linie 39 Listen 43 Nummerierung 44 Paragraph 36 Tabellen 47 Überschriften 35 wichtige Tags 39 Zeilenumbruch 39 HTML in PHP 144 HTML in PHP mit heredoc 380, 381 HTML lernen 25 HTML-Codeeinrückung 61 HTML-Datei erstellen 30 htmlspecialchars() 219, 341 Hyperlink für Feedback 202 Hyperlinks mit Hovereffekt 57 mit HTML 45

      I if mit isset() 150 if-else 116, 133 if-else für Passwortabfrage 143 IMG-Tag Attribute 41 Grafik einfügen 41 inc.php 179 include Zugangsdaten für MySQL 342 include() 151 include(), Endungs-Tricks 152 include(), Funktionen auslagern 179 index.html 83 index.php 368 Index-Datei 368 Index-Wert, assoziativer 130 Index-Wert, numerischer 126 Inkrementieren 158 Inline-CSS 58

      INSERT INTO 308, 410 INSERT INTO VALUES 347 Installationsprogramm XAMPP 75 INT 305 Integer 96 is_numeric 163 isset() 144, 145

      J JavaScript history.back() 388 JavaScript als Client-seitige Programmiersprache 70 JavaScript und PHP 231 Join 413

      K Kamelschreibweise 289 Klammeraffe zum Unterdrücken von Fehlermeldungen 324 Klammern, geschweifte 117 Klammern, runde 146 Klammersetzung, korrekte 107 klare Struktur beim Programmaufbau 209 Klassische Schreibweise 39 kleiner als 120 Kollation 299 Kommaseparierte Textdatei 263 Kommentarbereich, Daten sichern 220 Kommentare in CSS 55 in PHP 105 Kontrollkästchen 59 Kundennummer 392

      L Länge eines Strings ermitteln 385 Länge ermitteln 221 Layout für Weblog 371 Lebensdauergarantie

      443

      Stichwortverzeichnis

      444

      für Cookies 243 Leerzeichen nach Komma 175 Leerzeilen zur Gliederung 370 Lehrer Hinweise für 429 LIKE 314 LIMIT 315, 355 Linie 39 Link 45 Listen in HTML 43 Localhost aufrufen 81 logische Operatoren 121, 133 Löschen Datensätze 316 eines Cookies 245 von Dateien auf dem Webserver 436

      Weblog 365 Zugangsdaten auslagern 342 MySQL beim Dienstleister 420 MySQL und phpMyAdmin 298 mysqli_affected_rows() 348 mysqli_close() 322 mysqli_connect() 319 mysqli_fetch_array() 322, 327 mysqli_fetch_assoc() 321, 322, 327 mysqli_fetch_row() 322, 327 mysqli_num_rows() 323 mysqli_query() 320 mysqli_real_escape_string() 352 mysqli_select_db() 320

      M

      Nachkommastellen, auffüllen 167 Nachkommastellen, runden auf 166 Name-Feld 210 Namenskonventionen für Variablen 94 Navigation im Weblog 375 new line 101, 109 News-System als CMS 365 nl2br() 283 Normalisieren 395 Normalisieren, Vorteile 396 NOT NULL 301 Notices 426 Nummerierung 44 Nutzer-ID 403

      magic_quotes 351, 352 mail() 202, 419 mail(), Fehlerbehandlung 207, 208 Mailto-Link 202 Mal 158 Maskieren von Sonderzeichen 104 Mathematik 157 Mehrfachvotes unterdrücken 273 Meta-Tag für Zeichensatz 33 method 140 Mindestlänge bei Formularfeldern 221 Minus 158 Mittagspause mit Vergleich 118 Modulbauweise 338 Monat ermitteln 132 Multiplizieren 159 MySQL 295 Datensätze ausgeben 317 Datensätze eintragen 307 Datensätze filtern 313 Eingabe von Datensätzen mit PHP 328 Gästebuch 335 Sortieren 315 Speicherordner 309

      N

      O Oder-Verknüpfung 122 Onlineshop 231 Operatoren für Vergleich 120 Operatoren, logische 121 OPTION 172 or 121 or die() 324 ORDER BY 315 Ordner erstellen 26 Ordner für Weblog 368

      Stichwortverzeichnis

      P Parameter start 374 Passwort ausgeben 142 if-else 143 Passwortabfrage mit switch() 149 Passwortabfrage und Sicherheit 152 Passwortabfrage, Tricks 152 Passwortausgabe 141 Passwortschutz für Weblog 377 Passwortschutz, Allgemeines 137 PEAR-Standard 370 PHP Arbeit mit Dateien 247, 266 Aufbau des Dokuments 90 Cookies 237 Datum und Zeit 204 Kommentare 105 Kurzform für Verkettung 210, 215 testen 84 Tipps zur Notation 370 PHP und JavaScript 70 PHP und MySQL auf der Homepage 71 PHP und SQL 317 PHP_SELF 164 PHP-Abschnitt 90 PHP-Handbuch 437 phpinfo() 84 phpMyAdmin Benutzername und Kennwort 298 testen 86 Tipps zur Bedienung 310 Überblick 298 PHP-Referenz 437 Planen eines Weblogs 366 Planung von Datenbanken 296 Plus 158 post 140 preg_match() 223 Primärschlüssel 297, 301 PRIMARY KEY 301 Produkte auflisten 393 Projekt in PSPad 88 Projekt Schritt für Schritt 338 Projekte in PSPad 63

      Prozentrechnung 165 PSPad Browservorschau 35 HTML-Editor 28 Lesezeichen 62 Projekte 63 Speichern 34 Tipps und Tricks 61 Punkt statt Komma 161

      Q Query-String 377

      R Radiobuttons 59 readfile() 284 Rechtevergabe für Textdatei 253 RegExp 222 regulärer Ausdruck 222 regulärer Ausdruck, kurze Erklärung 224 Relationen zwischen Tabellen 398 Reload-Sperre 286, 289 rewind() 252 round() 166 Runden 166

      S Säulendiagramm 169, 267 Schleifen Abbruchbedingung einfügen 194 Bedingung prüfen 186 do while 189 Endlosschleife 188 for 190 foreach 195 Grundlagen 183 Tabelle dynamisch erzeugen 193 while 184 Zählmuster 191

      445

      Stichwortverzeichnis

      446

      Zählvariable 188 Schlüsselfeld 297, 301 Schreibschutz aufheben 253 Schutz für Ordner 154 Schutz vor Doppeleinträgen 348 Seitenweise Ausgabe 354 Seitenweise Ausgabe der Datensätze 357 Selbstverweis 164 SELECT 170 SELECT FROM 313 SELFPHP 437 Semikolon am Zeilenende 106 Servervariablen 164 Session 405 setcookie() 241 Shopmichel 231 Sicherheit 275 allgemeine Hinweise 21 beim Onlineshp 405 CAPTCHA 291 Cookies als Risiko? 236 Doppeleinträge vermeiden 348 durch Cookies 377 durch magic_quotes 351 durch Passwortschutz 137 durch regulären Ausdruck 355 error_reporting() 426 Fehleranzeige deaktivieren 426 für Zugangsdaten 342 im Gästebuch 290 per .htaccess 373 per include() 152 Schutz vor SQL-Injection 348 Variablentest 405 Verzicht auf Servervariablen 165, 272 Sichern des Formularinhalts 217 Skriptfehler ausblenden 426 SMALLINT 306 Sonderzeichen 219 Sortieren der Ausgabe in Gästebuch 340 Sortieren von Datensätzen 315 Spalte hinzufügen 420 Spamming 290

      Speichern 34 Speicherordner für MySQL 309 sprintf() 167 SQL Abfragen 312 Auswählen 313 COUNT() 412 Daten eintragen 308 Datensätze aktualisieren 316 Einführung 300 Entfernen von Datensätzen 316 Fehlermeldungen 304 Filtern 313 fortgeschrittene Funktionen 411 fortgeschrittenen Abfragen 413 LIMIT 315, 355 mehrere Tabellen gleichzeitig 413 Mustervergleich mit LIKE 314 ORDER BY 315 SUM() 412 Tabelle anlegen 300 SQL Injection 348, 351 SQL-Befehle für Gästebuchtabelle 337 SQL-Code für Gästebucheintrag 344 SQL-Code in Variable speichern 320 SQL-Code zur Dateneingabe 387 String 96 stripslashes() 211 strlen() 221, 385 strtr() 218 Style Sheets 49 Styles für Weblog 371 SUBMIT 61 substr() 386 Subtrahieren 160 SUM() 412 switch() 147, 148 Syntaxhighlighting 93

      T Tabelle unsichtbare 267 Tabelle für Bestellungen 406 Tabelle zur Ausgabe der Datensätze 325

      Stichwortverzeichnis Tabelle, Datenbanktabelle 296 Tabellen mit HTML 47 Tabellen für Säulendiagramm 169 Tabellen, mehrere 395 TABLE 47 Tag, aktueller 127 Tage als Array 126 TD 47 Teilbereich eines Strings ermitteln 386 Teiltabellen 395 Test 158 Testen von Formularfeldern 212, 221 TEXT 302, 305 TEXTAREA 205 Textdatei für Umfrage 265 kommaseparierte 263 time() 287 Timer für Skript 421 TIMESTAMP 306 Top-Anker 376 TR 47 Trennzeichen Punkt 161 Tripod 71 Tripod.Lycos 420

      U Überprüfen von Formularen 212 Uhrzeit 111, 115, 116 Uhrzeitformate 115 Umbenennen von Ordnern 27 Umfrage 261 Hauptseite 270 Mehrfachvotes unterdrücken 273 mit HTML vorbereiten 59 prozentuale Auswertung 278 Umfrage, prozentuale Auswertung 293 Umkehroperator 162 Umlaute nicht umschreiben 33 Und-Verknüpfung 121 ungleich 120 Unique Index 348 Universal-Formmailer 227

      Unix-Epoche 287 Unterdrücken von Fehlermeldungen 323 UPDATE 316 Upload 433 URL, Daten anhängen 377 URL-Parameter 355, 374 utf-8 32, 33

      V Validieren von Formularfeldern 212, 221 value sichern 173 VARCHAR 302, 305 VARCHAR() statt DATE 336 Variable an die URL anhängen 374 Variablen Einführung 94 Flag-Variable 214 Gültigkeit in Funktionen 177 initialisieren 95 Namenskonventionen 94 verbotene Zeichen 358 Zuweisungsoperator 95 Variablen auf Vorhandensein testen 144 Variablen innerhalb einer Funktion 290 Variablennamen, Probleme 107 Variablentest mit empty() 162 Verbinden von Tabellen 413 Verbotene Zeichen bei Variablen 358 Vergleichsoperatoren 119, 120, 133 Verhältnisgleichung 268 Verketten, Kurzform 210, 215 Verkettung 97 freiwillig 98 Pflicht 99 Verkettungsoperator 97, 109 Vermischen von PHP und HTML 144 Verweis nach open 376

      447

      Stichwortverzeichnis

      W Warenkorb 231 Weaverslave Dateiprofile 93 Webhostlist 74 Weblog ältere Einträge 375 Artikellänge begrenzen 383, 384 Beiträge einbinden 376 Daten ausgeben 369 Daten eingeben in SQL 382 Datenbankabfrage 372 Datenbanktabelle 367 eigener Ordner 368 Gesamtzahl der Einträge 374 mit CSS gestalten 371 mit MySQL 365 Passwortschutz 377 planen 366 SQL-Code zur Dateneingabe 387 Zurück-Link 388 Webseiten zu PHP 437 Webserver Apache-Webserver 75 Warum ein eigener? 69 Was ist das? 68 Web-Umfrage 261 Werte verschwinden aus Formularfeld 173 WHERE 313 while 356 while, Grundsyntax 185 while-Schleife 184

      448

      Wiederholen von Befehlen 184 Windows Explorer Ansicht aktualisieren 27 aufrufen 26 Wochentag ermitteln 113 Wochentage auf Deutsch 125 www.all-inkl.com 420

      X XAMPP 75 XAMPP, Dateiablage 81

      Z Zählen der Bestellungen 412 Zahlen formatieren 167 Zählen von Array-Elementen 128 Zählen von Datensätzen 323 Zahlenwert prüfen 163 Zähler 247 Zählschleife 190 Zählstopp für Counter 256 Zählvariable bei Schleifen 188 Zeichen austauschen 218 Zeichensatz festlegen 33 Zeiger auf Datei 250 Zeilenumbruch 39 Zeilenumbruch erhalten 283 Zeilenumbruch, automatischer 62 Zeilenumbruch, br und new line 101 Zeit mit PHP ausgeben 204 Zeitstempel mit Sekunden 287 zugriff.inc.php 342, 423 Zuweisungsoperator 95

      Recommend Documents

      PHP & MySQL Unser Online-Tipp für noch mehr Wissen … ... aktuelles Fachwissen rund um die Uhr – zum Probelesen, Downl...

      É»¾¼¿¬»²¾¿²µóß°°´·µ¿¬·±²»² ³·¬ ÐØÐ «²¼ Ó§ÍÏÔ É»¾¼¿¬»²¾¿²µóß°°´·µ¿¬·±²»² ³·¬ ÐØÐ «²¼ Ó§ÍÏÔ Ø«¹¸ Ûò É·´´·¿³- ú Ü¿ª·¼ Ô...

      По договору между издательством «Символ-Плюс» и Интернет-магазином «Books.Ru – Книги России» единственный легальный спос...

      PHP 5.3 + MySQL 5.1 Florence Maurice PHP 5.3 + MySQL 5.1 Der Einstieg in die Programmierung dynamischer Websites An...

      00 6728 fm 9/2/04 1:15 PM Page i “I’ve never purchased a better programming book… This book proved to be the most in...

      PHP & MySQL ® FOR DUMmIES 3RD ‰ EDITION PHP & MySQL ® FOR DUMmIES 3RD by Janet Valade ‰ EDITION PHP & My...

      00 7842 FM 3/6/01 3:38 PM Page i  PHP and MySQL Web Development Luke Welling and Laura Thomson 201 West 103rd St...

      00 6728 fm 9/2/04 1:15 PM Page i “I’ve never purchased a better programming book… This book proved to be the most in...

      PHP/MySQL avec Flash 8 Jean-Marie Defrance PHP/MySQL avec Flash 8 CHEZ LE MÊME ÉDITEUR Du même auteur J.-M. DEFR...