178
Standort Hagen Fachbereich Technische Betriebswirtschaft Webtechnologie Die Lehre von den Techniken des World Wide Web und von ihren Auswirkungen auf Wirtschaft und Gesellschaft — Teil I: Grundlagen — Vorlesungsskript für das fünfte Semester Andreas de Vries Version: 20. Dezember 2019 Dieses Skript unterliegt der Creative Commons License CC BY 4.0 (http://creativecommons.org/licenses/by/4.0/deed.de)

Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Standort HagenFachbereich Technische Betriebswirtschaft

Webtechnologie

Die Lehre von den Techniken des World Wide Web und von ihrenAuswirkungen auf Wirtschaft und Gesellschaft

— Teil I: Grundlagen —

Vorlesungsskript für das fünfte Semester

Andreas de Vries

Version: 20. Dezember 2019

Dieses Skript unterliegt der Creative Commons License CC BY 4.0(http://creativecommons.org/licenses/by/4.0/deed.de)

Page 2: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Inhaltsverzeichnis

I Technische Grundlagen des Web 7

1 Überblick über TCP/IP 81.1 Das Prinzip einer Schichtenarchitektur . . . . . . . . . . . . . . . . . . . . . . 91.2 Adressierung mit Sockets und URL . . . . . . . . . . . . . . . . . . . . . . . 91.3 IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101.4 UDP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111.5 TCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111.6 HTTP und HTTPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2 HTML 162.1 Elemente und Tags, Inhalt und Attribute . . . . . . . . . . . . . . . . . . . . . 162.2 Erstes Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182.3 Pfade und Hyperlinks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202.4 Tabellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232.5 Formulare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262.6 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

3 Cascading Stylesheets (CSS) 313.1 Syntax: Deklarationen, Selektoren und CSS-Regeln . . . . . . . . . . . . . . . 313.2 Einbindung von CSS in HTML . . . . . . . . . . . . . . . . . . . . . . . . . . 333.3 Die Kaskadierung geschachtelter Regeln . . . . . . . . . . . . . . . . . . . . . 343.4 Media Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353.5 Weitere Informationen und Quellen . . . . . . . . . . . . . . . . . . . . . . . 36

4 Formate zum Datenaustausch 384.1 XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384.2 JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464.3 Binäre Austauschformate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474.4 Textbasierte versus binäre Austauschformate . . . . . . . . . . . . . . . . . . . 48

II Serverseitige Programmierung am Beispiel von PHP 50

5 PHP Grundlagen 515.1 Prinzip von PHP-Programmen . . . . . . . . . . . . . . . . . . . . . . . . . . 525.2 Ausgaben in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535.3 Variablen in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545.4 Kommentare in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565.5 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

2

Page 3: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

5.6 Variablen, Datentypen und Operatoren . . . . . . . . . . . . . . . . . . . . . . 57

6 Kontrollstrukturen in PHP 656.1 Die if-Anweisung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 656.2 Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676.3 Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 696.4 Auslagern und Einbinden von PHP-Code . . . . . . . . . . . . . . . . . . . . 716.5 Zeit- und Datumsfunktionen in PHP . . . . . . . . . . . . . . . . . . . . . . . 73

7 Arrays 747.1 Indizierte (numerische) Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . 747.2 Die foreach-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 777.3 Assoziative Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 777.4 Mehrdimensionale Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . 807.5 Nützliche Funktionen für Arrays . . . . . . . . . . . . . . . . . . . . . . . . . 837.6 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

8 Eingaben 878.1 Eingaben in ein PHP-Skript . . . . . . . . . . . . . . . . . . . . . . . . . . . . 888.2 Eingabe und Verarbeitung in einem einzigen Skript . . . . . . . . . . . . . . . 898.3 Eingabe und formatierte Ausgabe von Kommazahlen . . . . . . . . . . . . . . 928.4 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

9 Cookies 949.1 Cookies und HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 949.2 Cookies in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

10 Sitzungen (Sessions) 9810.1 Eigenschaften von Sitzungen . . . . . . . . . . . . . . . . . . . . . . . . . . . 9810.2 Sitzungen in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9910.3 Sitzungen ohne Cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10010.4 Sicherheitsapekte: Erneuerung der Session-ID . . . . . . . . . . . . . . . . . . 10010.5 Gegenüberstellung Cookies und Sessions . . . . . . . . . . . . . . . . . . . . 101

11 Objekte 10311.1 Das Konzept eines Objekts in der Programmierung . . . . . . . . . . . . . . . 10311.2 Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10511.3 Traits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10611.4 Vergleich von Objekten und Arrays in PHP . . . . . . . . . . . . . . . . . . . 107

12 Datenbankzugriffe übers Web: HTML & PHP & SQL 10812.1 Zugriff von PHP auf MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . 10912.2 Anzeigen von Daten im Browser . . . . . . . . . . . . . . . . . . . . . . . . . 11412.3 Informationen über gerade abgesetzte SQL-Befehle . . . . . . . . . . . . . . . 11612.4 SQL Injection entschärfen mit escape_string . . . . . . . . . . . . . . . . . . 11712.5 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

13 Datenbankinteraktionen mit dem Browser 11913.1 Eintragen-Skript mit unformatierten Ausgaben . . . . . . . . . . . . . . . . . . 12013.2 Eintragen-Skript mit Funktionen und Formatierungen . . . . . . . . . . . . . . 12313.3 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

3

Page 4: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

14 Informationssicherheit 12714.1 SQL-Injektion: Angriffe auf Daten . . . . . . . . . . . . . . . . . . . . . . . . 12714.2 Session Fixation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12914.3 CSRF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

15 Dateien 13215.1 Zugriffsrechte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13215.2 Lesen und Schreiben von Dateien . . . . . . . . . . . . . . . . . . . . . . . . 13315.3 CSV-Dateien abspeichern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13415.4 Hochladen von Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13515.5 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

III Clientseitige Programmierung mit JavaScript 139

16 JavaScript 14016.1 Einleitende Beispiele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14216.2 Grundsätzliche Syntaxregeln . . . . . . . . . . . . . . . . . . . . . . . . . . . 14516.3 Dynamisch und implizite Typisierung . . . . . . . . . . . . . . . . . . . . . . 14516.4 Prototypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14616.5 Mathematische Funktionen und Konstanten . . . . . . . . . . . . . . . . . . . 14816.6 Kontrollstrukturen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14916.7 Wichtige Standardobjekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15016.8 Funktionen und Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15416.9 DOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15916.10XMLHttpRequest und AJAX . . . . . . . . . . . . . . . . . . . . . . . . . . . 16416.11Web Workers: Nebenläufigkeit in JavaScript . . . . . . . . . . . . . . . . . . . 16916.12DOM Storage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170

Literaturverzeichnis 172

Index 174

4

Page 5: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Vorwort

Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus derZeit gefallen“. Er verwendet das alte Wort Technologie, das sich vom griechischen τεχνη tech-ne „Kunst, Handwerk“ und λóγoς logos „Wort, Lehre Wissenschaft“ ableitet und daher tref-fend mit „Lehre von den Techniken“ übersetzt werden kann. Genau so definierte der PhilosophChristian Wolff den Begriff 1740.1 Nun wurde der Ausdruck im Laufe des 20. Jahrhundertsvon dem englischen technology überlagert, das im Wesentlichen dem deutschen Wort Technikentspricht.2 So konnte sich im Englischen dann auch die Pluralform entwickeln, die mit derBedeutung einer „Lehre“ nicht vereinbar ist, und heute spricht man ganz selbstverständlich vonTechnologien, meint aber Techniken. Entsprechend sollten die web technologies im Deutschenauch Webtechniken heißen. Aber sei’s drum, Sprache lebt.

Was sind nun die Inhalte der Webtechnologie, also der „Lehre von den Webtechniken”? Sieumfasst einerseits die informatische Ebene des Internets, also die Behandlung sowohl seinertechnischen Infrastruktur mit den verschiedenen Schichten und Protokollen, als auch seiner Pro-grammiersprachen, Algorithmen und Speichermechanismen. Webtechnologie beschäftigt sichandererseits aber auch mit den wirtschaftlichen und gesellschaftlichen Wirkungen des Webs,also den Chancen und Gefahren, den Möglichkeiten und Grenzen dieser weltumfassenden in-formationellen Revolution, deren Keim mit Alan Turings Konzept einer Rechenmaschine 1936entstand [16] und nun mit Social Media, dem „Internet der Dinge“ und mobilen Technikenzur bedeutendsten wirtschafts- und kulturhistorischen Umwälzung seit der Industriellen Revo-lution führte und deren psychologische, politische und gesellschaftliche Auswirkungen bislangallenfalls visionäre Kulturwissenschaftler wie Marshall McLuhan [10, 11] erahnt haben. So ver-standen gehört die Webtechnologie also zu einem der Kerngebiete der Wirtschaftsinformatik.

Ein wesentliches Ziel der Webtechnologie ist es, durch die Vermittlung der technischenGrundlagen unserer digital vernetzten Welt zu deren Verstehen und zu deren Gestaltung beizu-tragen. Damit will die Webtechnologie einer derzeit zu beobachtenden gesellschaftlichen Ent-wicklung entgegen treten: Immer mehr von uns bedienen sich einer immer höher entwickeltenTechnik, aber das Verständnis für die Funktionsweise der Hard- und Software, mit deren Hilfewir arbeiten, plaudern oder flirten, koppelt sich immer weiter davon ab. Dieser Trend zu ei-nem „digitalen Analphabetismus“ ist gefährlich. Denn solange die allem unterlegte Welt derAlgorithmen, Programmiersprachen und Speichertechniken des Netzes uns magisch und uner-klärlich erscheint, solange bleiben wir durch sie manipulierbar. Diese Welt verstehen, kritisierenund gestalten zu können ist die dringlichste Herausforderung für den modernen Menschen. Je-dem von uns müssen die Mittel an die Hand gegeben werden, die alltäglich verwendete Technikzu durchschauen und sie zu beherrschen, um nicht von ihr beherrscht zu werden.

1 „Est itaque Technologia scientia artium & operum artis.“ Etwa: „So ist Technologie die Wissenschaft vonden Handwerken und den Handwerkserzeugnissen.“ C. Wolff (1740): Philosophia rationalis sive logica, S. 33.https://books.google.com/books?id=9mYOAAAAQAAJ&pg=PA33

2 http://www.merriam-webster.com/dictionary/technology

5

Page 6: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Zum Inhalt dieses SkriptsAn der FH Südwestfalen in Hagen wird Webtechnologie über zwei Semester angeboten. Im vor-liegenden Skript über die Grundlagen der Webtechnologie werden nach einer Einführung dergrundlegenden Begriffe wie HTML, CSS, XML und JSON Datenbankanbindungen über das In-ternet mit PHP als serverseitiger Technik behandelt, sowie JavaScript als zentrale clientseitigeWebtechnik. Beide Techniken spielen eine ökonomisch wichtige Rolle, nicht nur zur Intensi-vierung von Kundenanbindungen oder als Erweiterungspotenzial für Vertriebskanäle, sondernauch für unternehmensinterne Prozesse im Rahmen eines Intranets.

Warum PHP und JavaScript als Beispiele für Webtechniken? Mitte der 1990er Jahre ent-standen, sind beide Sprachen immerhin mittlerweile in die Jahre gekommene und zudem nichtunumstrittene Sprachen. Allerdings hat sich PHP wegen seiner relativ einfachen Handhabbar-keit und dem Rückgriff auf frei verfügbare Open-Source-Produkte, vor allem in Kombinati-on mit der Datenbank MySQL, zu einem De-Facto-Standard der Webtechniken entwickelt.JavaScript auf der anderen Seite läuft auf allen modernen Browsern und ist eine der Säu-len moderner Webanwendungen, vor allem Google trieb den weltweiten Einsatz von Java-Script seit den 2000er Jahren massiv voran. Auch Facebook bietet auf seiner Entwicklersei-te https://developers.facebook.com/ Programmierumgebungen (SDK’s) für JavaScript undPHP an, neben weiteren für die Programmierung mobiler Apps der gängigen Smartphonesys-teme und für die Spiel-Engine Unity. Den Stellenwert der beiden Programmiersprachen fürdie Entwicklung von Webanwendungen kann man also kaum überschätzen. Zudem sind nachW3Techs (http://w3techs.com/) beide Sprachen die im Web am weitesten verbreiteten, PHPmit über 80 % als serverseitige Sprache und JavaScript mit über 90 % als clientseitige Sprache.

Daher liegt es nahe, Studierenden der Wirtschaftsinformatik und des Wirtschaftsingenieur-wesens, aber auch anderen an Internetanwendungen Interessierten das Thema PHP und Daten-banken als Einführung in die Webtechnologie zu vermitteln. Insbesondere, da alternative Tech-niken wie Ruby on Rails, Java EE oder ASP ähnlich funktionieren und daher eine Einarbeitungdarin mit vorhandenen Kenntnissen von PHP leichtfällt.

Ein Hinweis noch zur Handhabung dieses Skripts. Betrachten Sie es als Obermenge zudem Stoff, der in der Vorlesung und den Praktika behandelt wird. Diejenigen Teile des Skripts,die in den Veranstaltungen nicht behandelt werden, sollen Ihnen als Materialsammlung undNachschlagewerk zum Thema dienen. Da mir oft die Frage gestellt wird, welche Teile desSkripts denn für die Prüfungen verlangt werden, lautet die Antwort also: Die Beherrschung derInhalte des gesamten Skripts ist hinreichend zum Bestehen der Prüfungen, das Beherrschen desStoffs aus Vorlesung und Praktika aber ist notwendig.

Danksagungen. Am Ende möchte ich denjenigen danken, die zur Entstehung und Vollendungdieses Skripts beigetragen haben. Insbesondere wäre es ohne meinen langjährigen Freund undMitarbeiter Ingo Schröder und seine wichtigen Anregungen, Ideen und Initiativen nicht in dieserForm entstanden. Mein Dank gilt zudem Robert Schweda, der als in dem Bereich der Webent-wicklung professionell Tätiger nicht nur wichtige Impulse gegeben, sondern auch die Inhaltedes Kapitels über CSS beigesteuert hat.

Hagen,im Dezember 2019 Andreas de Vries

6

Page 7: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Teil I

Technische Grundlagen des Web

7

Page 8: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

1Überblick über TCP/IP

Kapitelübersicht1.1 Das Prinzip einer Schichtenarchitektur . . . . . . . . . . . . . . . . . . . . . . . . . . 91.2 Adressierung mit Sockets und URL . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.3 IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101.4 UDP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111.5 TCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111.6 HTTP und HTTPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

TCP/IP ist eine Protokollfamilie, die die Verständigung von Rechnern in Netzwerken, also ins-besondere im Internet ermöglicht. Die Abkürzung steht für Transmission Control Protocol /Internet Protocol.

Ein erster Überblick über die TCP/IP-Familie ergibt sich durch einen Vergleich mit demsogenannten ISO/OSI-Referenzmodell.1 Dieses Standardmodell unterteilt die Kommunikationin rechnerbasierten Netzen in sieben Schichten, die von der physikalischen Schicht bis zur An-wendungsschicht reichen. Grundidee dieses Modells ist es, dass jede Spezifikation einer Netz-werktechnologie nur schichtenweise beschrieben werden muss, die Schnittstellen zwischen denSchichten sind festgelegt. Auf diese Weise funktioniert beispielsweise das Internet unabhängigvon der physikalischen Realisierung, also ob kabelbasiertes Ethernet, drahtloses WLAN oderModem-gestütztes PPP.

TCP/IP entstand früher als der ISO/OSI-Standard und ist daher unabhängig davon. Im Sin-ne von ISO/OSI ist TCP/IP keine vollständige Protokollarchitektur, es deckt nicht die unterenSchichten 1 und 2 ab, und an Stelle der drei Anwendungsschichten gibt es mehrere Protokolle,die OSI-Schicht übergreifend definiert sind, siehe Abbildung 1.1.Im Einzelnen: Die unteren beiden Schichten sind im TCP-IP-Modell gar nicht definiert. DieseSchichten bleiben Standards wie Ethernet, WLAN oder DSL überlassen. Auf jeden Fall benötigtwird die Verknüpfung zwischen den Adressen. Die Internetschicht entspricht der OSI-Schicht3, und das vorherrschende Protokoll ist IP Internet Protocol.

Die Transportschicht der TCP/IP-Familie entspricht der OSI-Schicht 4 und enthält zweigrundlegend verschiedene Protokolle, TCP als „verbindungsorientiertes“ Protokoll mit Fluss-kontrolle, und UDP als „verbindungsloses“ Protokoll mit weniger Overhead, aber auch gerin-gerer Zuverlässigkeit als TCP.

1 ISO steht als Abkürzung für International Organization for Standardization, OSI für Open Systems Inter-connection model.

8

Page 9: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 9

Darstellung

Sitzung

Transport

Sicherung

Bitübertragung

Anwendung

OSI-Schicht

Anwendung

Transport

Vermittlung Internet

Internet-Schicht

TCP UDP

ARPNetzzugang

TCP/IP-basierte Protokolle

Telnet

IP (IPv4, IPv6), ICMP

IEEE 802.x, IEEE 811.xx, DSL, ISDN

SMTP, XMPP, MQTT

FTP

HTTP HTTPS

SSH

SFTP

TLS

Abbildung 1.1: TCP/IP-Protokollfamilie im Vergleich zum OSI-Referenzmodell, sowie die gebräuchlichstenProtokolle.

Die Applikationsschicht der TCP/IP-Familie umfasst die OSI-Schichten 5 bis 7 und behan-delt spezifische Anwendugsprotokolle, also Protokolle, die zu bestimmten Anwendungen gehö-ren, also z.B. HTTP und HTTPS zu Browsern, FTP zu E-mail-Programmen, usw. Es sind die sogenannten „Internet-Dienste“. Gäbe es die Anwendungsprotokolle nicht, so könnte man nichtvon beliebigen Clientprogrammen auf beliebigen Betriebssystemen auf Dienste im Internet zu-greifen. Dass man sich über Protokolle und einsetzende Software bei Internet und allgemeinenClient-Server-Verbindungen kaum Gedanken machen muss, ist den standardisierten Protokollender Applikationsschicht zu verdanken.

1.1 Das Prinzip einer SchichtenarchitekturHauptziel eines Schichtenmodells ist die Standardisierung der Kommunikation zwischen tech-nischen Systemen. Solche Systeme können Computer, mobile Endgeräte oder auch chipbasierteSensoren und Aktoren sein. Wie in jeder Kommunikation ist stets eines der Systeme in der Rol-le des Senders und eines in der des Empfängers einer Nachricht. Im Laufe der Zeit können dieSysteme ihre Rolle als Sender und Empfänger durchaus wechseln. In einer Schichtenarchitekturwerden aufeinanderfolgende Schichten (englisch: layer) mit jeweils spezifischen Aufgaben de-finiert. Sowohl Sender als auch Empfänger arbeiten in jeder Schicht nach festgelegten Regeln,die zu einem Protokoll zusammengefasst werden.

1.2 Adressierung mit Sockets und URLProzesse als laufende Programme auf Rechnern sind über Sockets mit Ports adressierbar. EinRechner, der einen Prozess zur Kommunikation mit einem Prozess auf einem anderen Rechnerfreigibt, öffnet einen bestimmten Port. Die Syntax eines Sockets lautet:

Protokoll://IP-Adresse:Port︸ ︷︷ ︸Socket

also z.B. http://haegar.fh-swf.de:80. (Genaugenommen ist ein Socket – „Steckdose“ – einbesonderer Datentyp im UNIX-Betriebssystem, der als Schnittstelle zwischen beliebigen Pro-zessen für sie Prozeduren zur Kommunikation bereitstellt.)

Page 10: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

10 Andreas de Vries

Sender (Server)

Anwendung

Transport

Internet

Netzzugang

Empfänger (Browser)

Anwendung

Transport

Internet

Netzzugang

Aufruf Webseite

HTTP

TCP

IP

Ethernet→WLAN

Abbildung 1.2: Schichten und Protokolle, hier am Beispiel der TCP/IP-Familie: die logische Kommunikati-on über Protokolle (→) verläuft horizontal innerhalb jeder Schicht, die reale physikalische Kommunikation (⇒)vertikal durch die Schichten.

Zentral für jeden Internetdienst ist der URL (Uniform Resource Locator),2 der einen Dienstim Internet weltweit eindeutig aufruft. Das Adressformat ist wie folgt definiert:

protokoll://[benutzer[:passwort]@]server[:port] [/pfad[?query][#fragment]]

Kursiv Gedrucktes bezeichnet einzusetzende Variablen, die eckigen Klammern bezeichnen op-tionale Angaben, und die vorgegebenen Zeichen (:, /, ?, #) sind in nichtproportionaler Schriftgedruckt. Hierbei bedeuten:

• protokoll: gewünschter Internetdienst (ftp, telnet, http, ...);

• benutzer:passwort@ wird nur verwendet, wenn Passwortschutz gegeben ist (i.d.R. beiTelnet oder ftp)

• server: Domainname oder IP-Nummer des Servers

• port: die Nummer des Ports, d.h. des auf dem Server eingerichteten Verbindungspunktes(Socket);

• pfad: gibt den Pfadnamen des gewünschten Objekts

Ein URL ist nach RFC3986 (http://tools.ietf.org/html/rfc3986) ein spezieller URI (Uni-form Resource Identifier), der auch allgemeinere, also nicht nur über das Internet verfügbareRessourcen identifiziert.

1.3 IPDas Internet Protocol (IP) ist für die logische Adressierung und Zustellung von Paketen zu-ständig. Das Paket wird über verschiedene physikalische Stellen weitergereicht, bis es die Ziel-adresse erreicht. IP arbeitet dabei verbindungslos (connectionless), d.h. es kennt keinen Zustandirgendeiner Verbindung („Session“), auch wenn sie in einer höheren Schicht oder einer Anwen-dung aufgebaut werden. Jedes Paket wird unabhängig von den anderen behandelt, IP weiß nichtsdavon, ob Pakete zusammengehören. IP ist also wie der Paketdienst eines Versandhandels. Gibtman im Versandhandel eine Bestellung auf, stellt der Versender die Lieferung zusammen. Eskann dabei durchaus vorkommen, dass mehrere Pakete einzeln auf den Weg geschickt werden.Der Paketdienst (IP) behandelt alle Pakete gleich, er weiß nicht, ob sie zusammen gehören.

Nach der IP-Adressierung Version IPv4 ist eine IP-Adresse 4 Byte (32 bit) lang, und 16Byte = 128 bit nach der neueren und erweiterten Version IPv6. Prinzipiell sind damit maximal

2 http://tools.ietf.org/html/rfc1738

Page 11: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 11

232 ≈ 4,3 Milliarden Rechner mit IPv4 möglich, denn die IP-Adresse eines Rechners mussim gesamten Internet eindeutig sein, d.h. es darf keine doppelten IP-Adressen geben (bis aufdie privaten Adressräume, siehe unten). Mit IPv6 sind es entsprechend 2128 ≈ 3,4 ·1038 („340Sextillionen“) mögliche Adressen. In IPv4 wird zur besseren Lesbarkeit die „Dotted Decimal“-Darstellung verwendet, die jedes der 4 Bytes getrennt als Dezimalzahl darstellt.

1. Byte 2. Byte 3. Byte 4. Byte194 94 2 21

Darunter sind auch die privaten Adressräume, d.h. festgelegte IP-Adressen, die zwar einen Zu-gang zum Internet haben können, aber nicht von außen sichtbar sind (Tab. 1.1). Für diese Rech-

Klasse Adressraum maximale Netzanzahl maximale Rechneranzahl je NetzA 10.0.0.1 – 10.255.255.254 1 16777214B 172.16.0.1 – 172.31.255.254 16 65534C 192.168.0.1 – 192.168.255.254 256 254

Tabelle 1.1: Private IP-Addressräume (nach RFC 1918, erneuert durch RFC 6761).

neradressen sind keine Registrierungen notwendig. Die privaten Adressräume sind auch fürUnternehmen interessant, die ihr Intranet nicht nach außen öffnen wollen, und so das physi-kalisch angebundene Netz mit „Tunneling“ nur für Berechtigte zugänglich macht („VirtuellePrivate Netzwerke“ VPN).

Insgesamt ergibt das eine maximal mögliche Rechneranzahl von 3 702 423 846 nach demIP-Protokoll IPv4, die Rechner mit privaten Adressen nicht mitgezählt.

1.4 UDP

UDP (User Datagram Protocol) ist ein Transportdienst gemäß OSI-Schicht 4 wie TCP, jedochverbindungslos. Wie IP schickt UDP Datenpakete ungeprüft „so wie sie kommen“ und weiß garnicht, welche zusammen gehören und welche nicht. Insbesondere werden Fehler wie Datenver-lust oder eine falsche Reihenfolge der Pakete nicht bemerkt.

Der Vorteil von UDP gegenüber TCP ist, dass es ein schnelles Protokoll ist. Es wird vor al-lem dort eingesetzt, wo es auf einen geringen Overhead ankommt. Typische Einsatzgebiete vonUDP sind Anwendungen mit Frage-Antwort-Charakter, etwa ein Ping („schick mich zurück“),eine Anfrage beim Name-Server („Welche IP-Nummer gehört zu dem Domain-Name?“) odereine Synchronisation der Netzwerkzeit von Servern (NTP, network time protocol). Hier geht esum einen simplen Austausch von Informationen, und wenn die Antwort nicht zurückkommt,wird einfach nochmal gefragt. Auch für Audio- und Videoübertragungen eignet sich UDP bes-ser als TCP.

1.5 TCP

Während das Internetprotokoll IP eine logische Kommunikation zwischen zwei Rechnern er-möglicht, verbindet das Transmission Control Protocol TCP zwei Prozesse („Programme“) mit-einander. Im OSI-Schichtenmodell findet sich TCP in der Transportschicht (OSI-Schicht 4)wieder, siehe Abb. 1.1 (S. 9), und wird über IP übertragen.

Page 12: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

12 Andreas de Vries

1.5.1 VerbindungenTCP ist ein verbindungsorientiertes Protokoll, das heißt es wird eine bidirektionale Verbindungzwischen zwei Prozessen aufgebaut, über eine gewisse Zeit aufrecht erhalten und schließlichwieder geordnet beendet. Ohne einen Verbindungsaufbau ist erst gar kein Datentransfer mög-lich. Jeder Empfang eines Datenverkehrs wird quittiert (ähnlich wie bei einem Einschreiben),so dass der Sender genau weiß, welche Pakete auf jeden Fall angekommen sind.

Man kann sich eine verbindungsorientierte Kommunikation wie ein Telefonat vorstellen.Jemand ruft an, der Angerufene muss explizit abnehmen (bestätigen), erst dann kommt eineVerbindung zustande. Während des Verbindungsaufbaus werden noch keine Nutzdaten übertra-gen, und am Ende des Gesprächs wird die Verbindung explizit beendet, indem jeder Teilnehmerauflegt.

Betrachten wir uns die Eigenschaften einer TCP-Verbindung etwas genauer. Die Datenpa-kete bei TCP heißen Segmente. Der Verbindungsaufbau bei TCP erfolgt in drei Schritten undwird daher auch als three way handshake bezeichnet (Abb. 1.3).

1. Der Client initiiert die Verbindung, indem er dem Server ein TCP-Segment sendet, beidem ein bestimmtes Bit, das SYN-Flag (synchronize), gesetzt ist und das eine zufälli-ge Sequenznummer (ISN initial sequence number) beinhaltet. Diese Sequenznummer istein 32-Bit-Feld wird bei jedem nachfolgend verschickten TCP-Segment der bestehendenVerbindung hoch gezählt.

2. Der Server sendet ein TCP-Segment zurück, bei dem das SYN- und das ACK-Flag (ack-nowledge) gesetzt sind und das eine zufällige ISN sowie die Acknowledge-Nummer ent-hält, die einfach die Client-ISN um eins erhöht.

3. Der Client bestätigt den Empfang des SYN-Flags des Servers durch ein Segment, bei demdas ACK-Flag gesetzt ist mit der ISN des Servers um eins erhöht.

Die ACK-Flags stellen also so etwas wie Empfangsbestätigungen dar, mit denen der Sendereines Segments genau weiß, was auf jeden Fall beim Empfänger angekommen ist.

Der Verbindungsabbau funktioniert ähnlich wie der Aufbau, nur dass an die Stelle des SYN-Flags das FIN-Flag tritt. Allerdings gibt es bei einem Verbindungsabbau das Problem, dass der

Client:1234 Server:80

SYN [ISN−Server]ACK [ISN−Client + 1]

ACK [ISN−Server + 1]

SYN [ISN−Client]

Verbindungsaufbau

Client:1234 Server:80

Verbindungsabbau

FIN [M]

ACK [M+1]

FIN [N]

ACK [N+1]

Zeit

half

clo

se

half

clo

se

Abbildung 1.3: Verbindungsaufbau und -abbau bei TCP. Die Sequenznummer M beim Verbindungsabbau ergibtsich aus der Summe von ISN-Client und der Anzahl der vom Client in der Verbindung verschickten TCP-Segmente;entsprechend ist N die Summe von ISN-Server und der Anzahl der vom Server verschickten TCP-Segmente.

Client nicht einseitig die Verbindung beenden kann (da hinkt unser Telefonbeispiel von oben,denn ein Telefonat kann einseitig beendet werden!), wenn nämlich der Server noch nicht alleDaten versendet hat. Die Lösung ist ein Verbindungszustand half close, nachdem also eineStation das FIN-Segment verschickt hat und auf das ACK-Segment wartet; in diesem Zustand

Page 13: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 13

kann sie keine weiteren Daten senden außer einem ACK-Segment. Abb. 1.3 rechts zeigt einenVerbindungsabbau schematisch. Erst nach der letzten Bestätigung ist die Verbindung sauberbeendet.

Es wird von TCP eine Fehlerüberprüfung und Flusskontrolle durchgeführt, die folgendeFehler bemerkt und ggf. durch erneutes Senden korrigieren lässt.

• Datenverlust beim Transport;

• fehlerhafte empfangene Daten;

• falsche Reihenfolge der Datenpakete;

• netzwerkbedingte Verzögerung der Datenlieferung.

Notwendig für diese Funktionen sind Sende- und Empfangspuffer, also temporäre Speicher, indie die Daten der Verbindung zwischengespeichert werden (Abb. 1.4).

User−Daten

Sendepuffer

Segmentpuffer

User−Daten

Empfangspuffer

Segmentpuffer

nummerierte

nummerierteBestätigungen

Datensegmente

Sender TCP Empfänger TCP

Abbildung 1.4: Sende- und Empfangspuffer für Datensegmente bei TCP.

Eine TCP-Verbindung ist bidirektional, man spricht daher auch von einer Full-Duplex-Fähigkeitvon TCP. Um auch größere Datenmengen austauschen zu können, ohne gleich bei jedem kleinenSegment die Quittungen auszutauschen, gibt es das TCP-Window: Der Empfänger teilt über einFeld im TCP-Segment seine TCP-Window-Größe mit, also wieviel Platz er aktuell in seinemEmpfangspuffer hat.

1.6 HTTP und HTTPSDer Anwender kommt mit TCP oder IP nicht in Berührung, denn die Anwendungsschicht istnach Tabelle 1.1 die Schnittstelle und damit die „Vermittlungsschicht“ zwischen ihm und TCPund nachgelagert IP. Diejenigen Protokolle, die er verwendet, sind entsprechend die Anwen-dungsprotokolle oder Internet-Dienste. Es sind Dienste im Sinne der Client/Server-Architektur,die alle auf TCP oder UDP basieren.

Als endbenutzerorientiertes Anwendungssystem besteht das WWW aus Web-Servern, dieHTML-Dokumente bereitstellen, die von Web-Clients, den Browsern, abgerufen und dargestelltwerden. Das Übertragungsprotokoll für diese Anwendungsschicht ist HTTP (hypertext transferprotocol). Es basiert auf TCP und ist standardmäßig auf Port 80 des Web-Servers. Bislangwurden drei Versionen HTTP veröffentlicht, HTTP/1.0 im Mai 1996,3 HTTP/1.1 im Juni 1999,4

und HTTP/2 im Mai 2015.5

3 http://tools.ietf.org/html/rfc19454 http://tools.ietf.org/html/rfc26165 https://tools.ietf.org/html/rfc7540

Page 14: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

14 Andreas de Vries

HTTP ist ein zustandsloses (stateless) Protokoll, d.h. es gibt mit HTTP nur isolierte Trans-aktionen, und Informationen jeder vorhergehenden Transaktion werden nicht gespeichert, son-dern sofort vergessen. Insbesondere können über HTTP also keine Verbindungen oder Sessionsvermittelt werden, dazu sind ergänzende Speichermechanismen am Browser oder am Servernotwendig (z.B. Cookies). Da ganz allgemein für eine Verbindung zwischen Kommunikati-onsteilnehmern Informationen über den Zustand der Verbindung nötig sind, ist ein zustandslo-ses Protokoll immer auch verbindungslos. Demgegenüber ist ein zustandsbehaftetes Protokollnicht notwendig auch verbindungsorientiert: Beispielsweise ist IP zustandsbehaftet, aber ver-bindungslos [14, S. 476].

Eine Transaktion in HTTP funktioniert nach dem Request-Response-Muster und bestehtjeweils aus den folgenden vier Schritten:

1. Anfrage (request), immer ausgehend vom Client,

2. Antwort (response) des Servers,

Die Kommunikationseinheiten in HTTP zwischen Client und Server heißen Nachrichten (mes-sages), von denen es also zwei Arten gibt, die Anfrage (request) vom Client und die Antwort(response) vom Server. Die Daten, die der Server bereitstellt, heißen Ressource und werden übereinen eindeutigen URI (S. 10) adressiert. Jede Nachricht besteht aus zwei Teilen, dem Nachrich-tenkopf (message header) mit Metadaten wie die Absendezeit, die verwendete Textkodierungoder Clientinformationen, und dem Nachrichtenrumpf (message body), der die Nutzdaten ent-hält.

Eine Anfrage muss stets ihre Methode spezifizieren, die eine von neun gemäß HTTP de-finierten und in Tabelle 1.2 angegebenen Methoden sein muss.6 Diese Methoden werden spe-

Methode Beschreibung der AnfrageOPTIONS prüft, welche Methoden auf einer Ressource zur Verfügung stehen.TRACE gibt die Anfrage zurück, wie sie der Zielserver erhält.HEAD fordert Metadaten der angegebenen Ressource an. HEAD entspricht also GET,

nur dass kein Nachrichtenrumpf erwartet wird.GET fordert die angegebene Ressource vom Server an. GET weist keine Nebenef-

fekte auf, d.h. der Zustand des Servers wird nicht verändert.DELETE fordert die Löschung der angegebenen Ressource.PUT fordert das Anlegen einer Ressource unter dem angegebenen URI mit den an-

gehängten Daten. Wenn die Ressource bereits existiert, wird sie geändert. Einerfolgreiches Anlegen einer neuen Ressource wird mit dem Statuscode 201(Created) angezeigt, im Falle einer geänderten Ressource 200 (OK) oder 204(No Content).

PATCH ein Teil der angegebenen Ressource wird geändert. PATCH bewirkt also Ne-beneffekte auf dem Server. (Definiert seit Juni 2010 RFC 5789.)

POST übermittelt Daten an die angegebene Ressource, die der Server weiterverarbei-ten soll. Das Ergebnis dieser Verarbeitung kann eine neue Ressource sein, derenURI der Server mit dem Statuscode 201 (Created) zurücksendet oder mit 200(OK) bzw. 204 (No Content) quittiert.

CONNECT fordert, die Verbindung durch einen TCP-Tunnel zu leiten. Wird meist einge-setzt, um eine HTTPS-Verbindung über einen HTTP-Proxy herzustellen.

Tabelle 1.2: Anfragemethoden gemäß HTTP.

zifiziert in idempotente Methoden und in sichere Methoden: Eine idempotente Methode kannNebeneffekte (side effects) haben, d.h. den Zustand des Servers verändern, aber eine Wieder-holung derselben Anfrage hat dann keinen weiteren Nebeneffekt mehr. Spezielle idempotente

6 https://tools.ietf.org/html/rfc7231#section-4, https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods

Page 15: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 15

Methoden sind die sicheren (safe) Methoden, die auch beim ersten Aufruf keine Nebeneffektebewirken.

Idempotente Methoden: OPTIONS, TRACE, HEAD, GET, PUT, DELETESichere Methoden: OPTIONS, TRACE, HEAD, GET

Obwohl GET in HTTP-Protokoll als sichere Methode definiert ist, kann nicht ausgeschlossenwerden, dass sie dennoch Nebeneffekte erzeugt: Im Prinzip kann eine dynamische Ressource,z.B. ein PHP-Skript, durchaus den Zustand des Servers verändern. Entscheidend bleibt jedoch,dass sich der anfragende Client gemäß HTTP nicht darauf verlassen kann, eine GET-Anfragegibt ihm die Ressource eben nur „zur Ansicht“.

PATCH und PUT unterscheiden sich dadurch, dass PATCH bei einer noch nicht vorhande-nen Ressource diese nicht notwendig anlegt. Der grundlegende Unterschied zwischen POSTund PUT ist, dass bei POST der URI die Ressource adressiert, die die Anfrage bearbeitensoll, während PUT anfragt, die Ressource unter diesem URI anzulegen. Entsprechend kanndie Ressource einer POST-Anfrage ein Prozess (z.B. ein PHP-Skript, s.u.) sein, der die Datenserverseitig beliebig verarbeitet, wohingegen bei einer PUT-Anfrage die übermittelten Datenals Ressource unter der angegebenen URI auf dem Server gespeichert werden müssen.

Welche der Anfragemethode für einen gegebenen Webserver möglich ist, hängt von dessenKonfiguration ab. Üblicherweise sind nur GET und POST ermöglicht.

Jeder Antwort auf eine HTTP-Anfrage wird ein dreistelliger Statuscode mitgeliefert, derüber Erfolg, Warnungen oder Fehler der Anfrage informiert. Eine Übersicht über wichtige

Code Nachricht Bedeutung200 OK Die Anfrage wurde erfolgreich bearbeitet und das Ergeb-

nis der Anfrage wird in der Antwort übertragen.304 not modified Der Inhalt der angeforderten Ressource hat sich seit der

letzten Abfrage des Clients nicht verändert und wird des-halb nicht erneut übertragen.

404 not found Die angeforderte Ressource wurde nicht gefunden. Die-ser Statuscode kann ebenfalls verwendet werden, um ei-ne Anfrage ohne näheren Grund abzuweisen. Links, wel-che auf solche Fehlerseiten verweisen, werden auch als„Tote Links“ bezeichnet.

500 internal server error Unerwarteter Serverfehler

Tabelle 1.3: Wichtige HTTP-Statuscodes einer HTTP-Antwort.

HTTP-Statuscodes gibt Tabelle 1.3, für eine vollständige Auflistung sei auf Abschnitt 6 desRFC7231 verwiesen: https://tools.ietf.org/html/rfc7231#section-6.

HTTPS (HTTP Secure oder HTTP over TLS) ist die verschlüsselte Variante von HTTP, essetzt auf TLS auf als Zwischenschicht zwischen TCP und HTTP.7

7 http://tools.ietf.org/html/rfc2818

Page 16: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

2HTML

Kapitelübersicht2.1 Elemente und Tags, Inhalt und Attribute . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.1.1 Dateiendung .html und Kommentare . . . . . . . . . . . . . . . . . . . . . . 182.2 Erstes Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

2.2.1 Der Vorspann, Zeichensatzkodierung . . . . . . . . . . . . . . . . . . . . . . 182.2.2 <head> und <body> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192.2.3 Überschriften, Absätze und Zeilenumbrüche . . . . . . . . . . . . . . . . . . 20

2.3 Pfade und Hyperlinks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202.3.1 Hyperlinks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222.3.2 Bilder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

2.4 Tabellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232.4.1 Grundproblematik der Darstellung einer Tabelle im Browser . . . . . . . . . . 232.4.2 Struktur einer Tabelle in HTML . . . . . . . . . . . . . . . . . . . . . . . . . 232.4.3 Spaltenformatierung mit colgroup . . . . . . . . . . . . . . . . . . . . . . . . 25

2.5 Formulare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262.5.1 Datenübertragung mit GET und POST . . . . . . . . . . . . . . . . . . . . . . . 30

2.6 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

Was passiert eigentlich, wenn der Browser eine Webadresse aufruft? Hinter jeder (gültigen)Webadresse verbirgt sich stets eine Datei oder eine Ressource auf dem Web-Server. Der Browserfordert diese Datei an (request). Der Webserver, der als eifriger Dienstleister permanent aufsolche Requests horcht, antwortet auf sie umgehend mit einer Response (Antwort). Die ganzeKommunikation im Internet basiert auf diesem primitiven und sehr einseitigen Frage-Antwort-Spiel. Stets fordert ein Browser eine Ressource an und bekommt sie.

Es ist dieses einfache Request-Response-Muster, das einerseits für den durchschlagendenErfolg des Internets als Informationsmedium verantwortlich ist, das andererseits aber für einegewisse Starrheit sorgt: Informationen vom Client zum Server sind nämlich gar nicht vorgese-hen. Diesen Mangel zu beheben ist nicht einfach, eine der möglichen Antworten darauf ist PHP.Doch bevor wir uns dieser Webtechnik zuwenden, wollen wir erst HTML kennen lernen.

2.1 Elemente und Tags, Inhalt und AttributeHTML ist eine einfache formale Sprache, die aus vordefinierten Formatierungsanweisungenbesteht und von einem Interpreterprogramm, dem Browser, übersetzt und auf dem Bildschirm

16

Page 17: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 17

dargestellt wird. „HTML“ steht dabei als Abkürzung für Hypertext Markup Language, also etwa„Hypertext Markierungssprache“ oder „Hypertext Auszeichnungssprache“, wobei der Begriffmarkup ursprünglich aus dem Verlagswesen stammt und jene handschriftlichen Markierungen(„Textauszeichnungen“) bezeichnet, die ein Layouter als Anmerkungen für den Setzer in einManuskript einfügt und die im fertigen Endausdruck natürlich nicht sichtbar sind.

Entsprechend bestehen HTML-Dokumente aus rein ASCII-textbasierten Anweisungen, densogenannten Elementen. Es gibt eine bestimmte Menge von Elementen, die in einem HTML-Dokument von sogenannten Tags umschlossen sind. Tags tauchen also fast immer paarweise auf(Ausnahmen sind die leeren Elemente, s.u.). Man schreibt dabei das Anfangs-Tag, indem manden Namen des Elements in spitzen Klammern schreibt, <name>, und das Ende-Tag zusätzlichmit einem Schrägstrich (slash) </name> versieht, also z.B.

<name> . . . </name>

Der Inhalt „. . . “ des Elements steht innerhalb dieser Tags und kann wiederum Elemente enthal-ten. Wichtig ist dabei die Regel, dass ein inneres Element erst geschlossen sein muss, bevor einäußeres geschlossen werden kann, also z.B.

<html>

<head>

<title>

Seitenname

</title>

</head>

<body>

Inhalt

</body>

</html>

Auf diese Weise entsteht eine logische Baumstruktur ineinander geschachtelter Elemente (Abb.2.1). Sie stellt in diesem Fall ein HTML-Dokument dar, das ein head- und ein body-Element als

Abbildung 2.1: Die logische Baumstruktur eines HTML-Dokuments.

Kinder enthält, und head enthält wiederum als Kind das Element title. Die Elemente title undbody enthalten als Inhalt Mein Seitenname und Inhalt.

Falls ein Element kein Kind und keinen Inhalt besitzt, heißt es leer und kann geschriebenwerden als <name/>, d.h.

<name> </name> = <name/>.

Ein Element kann mehrere Attribute enthalten. Ein Attribut ist eine bestimmte Eigenschaft desElements und kann einen Wert aus einer vorgegebenen Menge annehmen. Es wird in das Start-Tag des Elements geschrieben und sein Wert nach einem Gleichheitszeichen dahinter in Anfüh-rungszeichen:

Page 18: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

18 Andreas de Vries

<name attribut="wert"> . . . </name>

In XML, dem allgemeinen „Dokumentenstandard“ des Web (siehe Abschnitt 4.1 ab Seite 38)spielt die Groß- und Kleinschreibung von Tags und Attributen eine Rolle, meist werden Ele-mentnamen klein geschrieben.

2.1.1 Dateiendung .html und KommentareAls weitere allgemeine Information zu HTML-Dokumenten muss man wissen, dass sie eineTextdatei sind, erstellbar mit jedem einfachen Editor, und die Endung .html oder .htm ha-ben müssen. Ferner können Kommentare an beliebiger Stelle nach dem Vorspann (s.u.) in einHTML-Dokument eingefügt werden. Sie haben die Syntax

<!-- ... -->

Ein Kommentar ist also ein einzelner Tag, allerdings kein Element; es kann und darf daher nichtgeschlossen werden. Kommentare werden vom HTML-Interpreter des Browsers ignoriert undalso im Browserfenster nicht dargestellt. Das gleiche Schicksal ereilt auch jedes Leerraumzei-chen (Whitespace), also Leerzeichen, Tabulator, Zeilenumbruch usw., das auf ein Leerraumzei-chen folgt.

2.2 Erstes BeispielDas folgende Beispiel gibt ein vollständiges HTML-Dokument wieder und verwendet einigederjenigen Elemente, die wir im Folgenden benötigen werden. Es ist eine reine Textdatei undmuss als Endung .html oder .htm haben, um vom Browser bzw. vom Webserver als HTML-Dokument erkannt zu werden. Das Dokument wird dann wie in Abb. 2.2 dargestellt.

Listing 2.1: Einfaches HTML-Dokument zur Begrüßung1 <!DOCTYPE html>

2 <html>

3 <head>

4 <title>Meine erste Seite</title>

5 </head>

6

7 <body>

8 <h1>Hallo Welt!</h1>

9 <p>

10 Dies ist ein vollständiger Absatz.

11 </p>

12 Hier befindet sich nur Text, der hier

13 <br/>

14 umgebrochen wird,

15 </body>

16 </html>

2.2.1 Der Vorspann, ZeichensatzkodierungDie erste Zeile des HTML-Dokuments ist der Vorspann, der die genaue HTML-Version desDokument bestimmt. Die derzeit übliche ist HTML5. Wie in jeder der gängigen Programmier-sprachen ist die standardgemäße Textcodierung für HTML der ASCII-Code, kennt also keine

Page 19: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 19

Abbildung 2.2: Die Ausgabe von Listing 2.1.

Sonderzeichen wie z.B. ä, ß, ç, usw. Möchte man Sonderzeichen darstellen, so gibt es zweiMöglichkeiten. Einerseits gibt es dafür in HTML Sonderbefehle, z.B.:

Zeichen HTML-Befehl Erläuterungä, Ä &auml; &Auml; „a Umlaut“, „A Umlaut“

ß &szlig; „sz Ligatur“e &euro;

ϕ &#966; = &#x3C6; 966 = 0x3C6 ist der Unicode von ϕ

(Achtung: das Semikolon gehört zu den Anweisungen!) Eine vollständige Liste aller in HTMLdarstellbaren Zeichen finden Sie unter

https://wiki.selfhtml.org/wiki/Referenz:HTML/Zeichenreferenz

Eine andere (und bequemere) Möglichkeit ist es, innerhalb des <meta>-Tags im <head>-Tag dasAttribut charset auf die Kodierung einzustellen, also

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

</head>

...

Üblich sind die beiden Werte "UTF-8" für Unicode und "ISO-8859-1" für den erweiterten ASCII-Zeichensatz. Die mächtigere von beiden Kodierungen ist natürlich UTF-8, mit dem alle interna-tional gebräuchlichen Schriftsätze dargestellt werden können, wie die Internetseite Wikipedia.

org eindrucksvoll zeigt.Sie können Ihr HTML-Dokument auf Gültigkeit überprüfen lassen, indem Sie den HTML-

Validator des W3-Consortiums (W3C) verwenden, http://validator.w3.org/Bis auf die Angabe des Dokumententyps hat der Vorspann keinen Einfluss auf die Dar-

stellung des HTML-Dokuments, also der „Webseite“. Das Dokument selber besteht aus einemeinzigen <html>-Element. Hier muss der Inhalt des Dokuments festgelegt werden.

2.2.2 <head> und <body>

Die beiden Kindelemente eines <html>-Elements sind <head> und <body>. Das <head>-Elementkann Zusatzinformationen („Metainformationen“) enthalten sowie im Element <title> den Na-men des Dokuments, der in der Titelzeile des angezeigten Fensters erscheint. Der Fensterinhalt

Page 20: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

20 Andreas de Vries

wird im <body>-Element festgelegt. Jeder hier erstellte Text wird im Fenster dargestellt, es seidenn er ist in einem Tag.

2.2.3 Überschriften, Absätze und ZeilenumbrücheDer im <body>-Element erstellte Text kann mit Tag-Formatierungen nun gestaltet werden. EineÜberschrift kann mit dem <h1>-Element erstelllt werden, wobei ,h‘ für header steht und die 1für die Ebene; es gibt weitere Elemente <h2> . . . <h6>, die jeweils verschiedene Unterüberschrif-ten erstellen. Der Inhalt der Überschrift ist dann ganz einfach der Text innerhalb der beidenTags <h1> . . . </h1>.

Ein Absatz wird in HTML durch das <p>-Element markiert, der Browser stellt seinen Inhaltpassend im Fenster dar und bricht abhängig von der Fensterbreite automatisch um. Standardmä-ßig wird der Text linksbündig dargestellt. Andere Formatierungen kann man mit dem Attributstyle erreichen:

HTML-Anweisung Wirkung<p style="text-align:justify"> . . . </p> Absatz in Blocksatz<p style="text-align:center"> . . . </p> Absatz zentriert<p style="text-align:right"> . . . </p> Absatz rechtsbündig

Beachten Sie die Anweisung als Attribut-Wert-Paar. Der Wert ist hier übrigens eine CSS-Anweisung. (Auf CSS werden wir weiter unten noch etwas genauer eingehen.) Früher wur-de zur Zentrierung oft das <center>-Element verwendet; es gilt heute jedoch als deprecated(„abgelehnt“) und sollte unbedingt vermieden werden. Eine Auflistung von veralteten HTML-Anweisungen finden Sie unter:

http://wiki.selfhtml.org/wiki/HTML/deprecated

Möchte man einen Zeilenumbruch im laufenden Text erzwingen, so kann man es mit dem <br>-Element (für break) erreichen. Da es ein leeres Element ist, sollte man es XML-konform als<br/> verwenden.

2.3 Pfade und HyperlinksDas ,H’ in HTML geht auf Hypertext zurück, eine Eigenschaft, die maßgeblich zum Erfolg desWebs beigetragen hat: Man kann nämlich an beliebiger Stelle im Text einen Hyperlink, oderkurz Link, setzen, also einen Verweis auf irgendeine Webadresse im Internet, auf die man durchAnklicken gelangen kann.

Verantwortlich dafür ist das <a>-Element (für anchor – Anker), das wir im folgenden Bei-spiel kennen lernen. Da wir dazu das Konzept der Pfade im Internet benötigen, das man auchzur Darstellung von Bildern einsetzen muss, ist gleich auch noch eine Grafik eingebaut.

Listing 2.2: Hyperlinks1 <!DOCTYPE html>

2 <html>

3 <head><title>Links</title></head>

4 <body>

5 Hier geht es zur <a href="http://www.fh-swf.de">FH Südwestfalen</a>

6 mit einem absoluten Pfad,

7 deren Logo so aussieht:

Page 21: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 21

8 <br/>

9 <img src="http://haegar.fh-swf.de/grafiken/logo.gif" width="100"

10 border="0" alt="Logo"/>.

11 <br/>

12 Hier geht es zu einem

13 <a href="../programme/auszeichnungen.html">HTML-Dokument</a>

14 mit einem relativen Pfad zum Nachbarverzeichnis <tt>/programme</tt>.

15 </body>

16 </html>

Im Browser ergibt sich damit die Darstellung in Abb. 2.3.

Abbildung 2.3: Die Ausgabe von Listing 2.2.

HTML-Dateien bestehen nur aus Text. Dennoch können sie Grafiken enthalten. Solche Ele-mente werden in HTML in Form eines Verweises auf eine Grafik notiert. Auch ein ausführbarerVerweis zu einer anderen eigenen oder fremden Web-Seite ist nur ausführbar, wenn er sein Ver-weisziel korrekt und genau benennt. Für all diese Zwecke wird das Referenzieren mit Pfaden inHTML benötigt.

Jede Datei im Internet hat eine weltweit eindeutige Adresse, den URI (Uniform ResourceIdentifier). Das ist eine vollständige Webadresse wie

http://haegar.fh-swf.de/grafiken/logo.gif

Das ist ein absoluter Pfad. Ein Pfad ist üblicherweise schreibungssensitiv (case sensitive), /Pfadverweist also auf etwas anderes als /pfad. Das Ende einer Hierarchiestufe – sei es der Rechneroder ein Verzeichnis – wird stets mit einem Slash / gekennzeichnet. (Beachten Sie: die DOS-Notation mit dem Backslash \ funktioniert nicht im Internet!).

Im Gegensatz dazu gibt es relative Pfade, die den Ort einer Datei relativ zum aktuellenDokument angeben. Hierbei gibt es die beiden Notationen

./Verzeichnispfad oder ../Verzeichnispfad

Ein einzelner Punkt vor dem Verzeichnispfad (der zu einer Datei – manchmal auch nur zu ei-nem Unterverzeichnis – führt) besagt, dass der Startpunkt sich im Verzeichnis des aktuellenDokuments befindet. Zwei Punkte bedeuten, dass man zum Startpunkt des Verzeichnispfadesvom aktuellen Dokument eine Verzeichnisstufe höher und von dort den angegebenen Verzeich-nispfad entlang gehen muss.

Im Beispiel 2.2 sind die beiden Adressen

Page 22: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

22 Andreas de Vries

http://www.fh-swf.de und http://haegar.fh-swf.de/grafiken/logo.gif

als zwei absolute Pfade angegeben. Der erste zeigt nur auf das Hauptverzeichnis des Rechnerswww.fh-swf.de, der zweite auf die Datei logo.gif im Verzeichnis /grafiken im Hauptverzeich-nis. Das Hauptverzeichnis eines Rechners ist üblicherweise das Verzeichnis htdocs.

Demgegenüber ist ../programme/auszeichnungen.html ein relativer Pfad, der auf die Da-tei auszeichnungen.html verweist, die sich neben dem Verzeichnis des aktuellen Dokumentsbefindet. Würde sich die Datei im gleichen Verzeichnis befinden, würde man schreiben ./aus-

zeichnungen.html.

2.3.1 Hyperlinks

Hyperlinks, also anklickbare Verweise auf andere Dateien, werden in HTML mit dem <a>-Element (anchor = Anker) erstellt. Der Start-Tag muss zwingend das Attribut href besitzen,das den Pfad zu der verlinkten Datei als Wert erhält. Innerhalb der beiden Tags <a> und </a>

befindet sich der Text (oder auch das Bild), der markiert erscheint und den man anklicken kann,um den Link auszuführen. Der Pfad als Wert des href-Attributs kann absolut oder relativ zumaktuellen Dokument sein, wie im Beispiel:

<a href="http://www.fh-swf.de">FH Südwestfalen</a>

oder

<a href="../programme/auszeichnungen.html">HTML-Dokument</a>

Bei dem ersten Link ist noch anzumerken, dass der Pfad ja gar nicht auf eine Datei verweist,sondern nur auf das Hauptverzeichnis. Wieso wird dann trotzdem eine Webseite angezeigt?Allgemein gibt der Webserver den Inhalt der Datei index.html an den Browser. Falls sich keineDatei mit diesem Namen in dem verlinkten Verzeichnis befindet, wird auch tatsächlich keineWebseite angezeigt! (Je nach Einstellung des Webservers sieht man dann tatsächlich nichts odereine Liste aller Dateien des Verzeichnisses, die man dann einzeln anklicken kann.) Wenn sicheine Datei namens index.html in dem Verzeichnis befindet, sind daher die drei folgenden Pfadeäquivalent:

http://www.fh-swf.de = http://www.fh-swf.de/ = http://www.fh-swf.de/index.html

2.3.2 Bilder

Bilder werden vom Browser durch das <img>-Element dargestellt, das zwingend das Attribut src(source = Quelle)1 enthalten muss, dessen Wert der Pfad zu dem gewünschten Bild ist. Ähnlichwie der Zeilenumbruch <br/> ist auch das <img>-Element leer, besteht also aus nur einem Tag.

Gemäß Standard ist ebenso das Attribut alt erforderlich, dass das anzuzeigende Bild kurzbeschreibt. Dieser Text wird angezeigt, wenn das Bild nicht dargestellt werden kann. Ein „mi-nimales“ <img>-Tag hat also die folgende Gestalt,

<img src="http://haegar.fh-swf.de/garfik/logo.png" alt="Logo FH"/>

1 Interessanterweise ist ein häufig gemachter Fehler, dass man das Attribut scr nennt, was die unangenehmeFolge hat, dass der Browser das Bild nicht anzeigt (und natürlich auch sonst keine Fehlermeldung ausgibt); fürdiesen Fehler scheint es einerseits die Erklärung zu geben, dass man zu schnell tippt und den Dreher reinbekommt,oder dass man intuitiv bei Bildern an Screen denkt und so auf ,scr’ kommt. Daher: Es heißt src, von Source, Source,Source!

Page 23: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 23

Optional sind die Attribute width und height für die Breite und Höhe des Bildes in Pixel, sowieborder für die Dicke des Rahmens. Legt man nur eines der beiden Attribute width oder heightfest, so wird die andere Größe proportional errechnet; werden beide weg gelassen, so wird dasBild in Originalgröße angezeigt. Legt man beide fest, so wird das Bild entsprechend verzerrt.

Man sollte bei Bildern ein webfähiges Bildformat verwenden, das von allen Browsern dar-gestellt werden kann. Je nach Bildart2 sind dies die Formate JPG, GIF und PNG. VerwendenSie insbesondere keine BMP-Dateien.

2.4 TabellenTabellen erlauben eine sehr übersichtliche Darstellung von Daten oder Information. Sie spielendaher insbesondere für die Präsentation von Daten aus Datenbanken eine wichtige Rolle. Da esin HTML möglich ist, Tabellen ohne Gitterlinien („blinde Tabellen“) zu erstellen, haben sichTabellen auch als Gestaltungsmittel für Webseiten etabliert. Aus Gründen der Barrierefreiheit,also der Anforderung an Internetauftritte, die Information auch für behinderte Menschen, ins-besondere Blinde, Sehbehinderte oder Farbenblinde, zugänglich zu halten, ist dies jedoch mitBedacht zu tun. Empfehlungen zur Barrierefreiheit (Web Content Accessability) finden Sie unterhttp://www.w3.org/TR/WAI-WEBCONTENT-TECHS/.

2.4.1 Grundproblematik der Darstellung einer Tabelle im BrowserEine Tabelle hat eine zweidimensionale Struktur, besitzt also zwei Richtungen. Bei Tabellenspricht man üblicherweise von Zeilen (in der Waagerechten) und Spalten (in der Senkrechten).Ein einzelner Eintrag, beispielsweise die zweite Zeile in der dritten Spalte, heißt Zelle.

Wir Menschen lesen Tabellen kontextabhängig. Zunächst überprüfen wir, wofür jede Zeileund Spalte steht, und gehen dann je nach Interesse spalten- oder zeilenweise durch die Zellen.So haben wir relativ schnell die Information aus einer Tabelle gewonnen.

Ein Browser kann solch ein bedeutungsabhängiges Verhalten natürlich nicht durchführen, erversteht sein Handeln ja nicht. Man muss sich also auf ein automatisches Vorgehen einigen, mitdem alle Browser eine Tabelle interpretieren: er geht zeilenweise durch die Tabelle (Abb. 2.4).Im Umkehrschluss bedeutet das, dass wir in HTML eine Tabelle zeilenweise aufschreiben müs-

Abbildung 2.4: Eines Browser interpretiert eine Tabelle zeilenweise

sen, unabhängig von der Bedeutung der Zeilen und Spalten.

2.4.2 Struktur einer Tabelle in HTMLEine Tabelle wird mit dem <table>-Element erzeugt. Das <table>-Element enthält mindes-tens ein Kindelement <tr> (table row – Tabellenzeile), das <tr>-Element wiederum beinhaltetmindestens ein Kindelement <th> (table head – Tabellenkopf) oder <td> (table data – Tabellen-daten, Zelle). <th> und <td>-Elemente sind gleichberechtigt, sie unterscheiden sich nur darin,

2 Grob gesagt eignet sich JPG für Fotos oder Bilder mit vielen Farb- oder auch Grautönen, während PNG undGIF eher für Bilder mit wenigen Farbtönen, z.B. Logos, verwendet werden sollten.

Page 24: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

24 Andreas de Vries

dass <th>-Elemente den Text zentriert und fett darstellen, <td>-Elemente dagegen linksbündigund normal. Der Grundaufbau eines <table>-Elements ist also stets:

<table>

<tr>

<th> ... </th>

...

</tr>

<tr>

<td> ... </td>

...

</tr>

</table>

Diese Verschachtelung muss unbedingt eingehalten werden. Die Anzahl der Zeilen ergeben sichaus der Anzahl der <tr>-Elemente, während die Spaltenanzahl sich aus der maximalen Anzahlvon <td> und <th>-Elementen je Zeile ergibt. Die folgende Beispieltabelle hat also 3 Zeilen mitjeweils 2 Spalten, im Browser wird sie wie in Abb. 2.5 dargestellt.

Listing 2.3: Tabelle in HTML1 <!DOCTYPE html>

2 <html>

3 <head>

4 <meta charset="UTF-8"/>

5 <title>Tabelle</title>

6 </head>

7 <body>

8 <table style="margin:auto; width:500px" border="1">

9 <tr>

10 <th>Nummer</th>

11 <th>Tipp</th>

12 </tr>

13 <tr>

14 <td style="width:200px">Blumentip 1</td>

15 <td>

16 Vergessen Sie nie Ihre Blumen zu gießen!

17 </td>

18 </tr>

19 <tr style="background:#FFC200">

20 <td style="height:50pt">Blumentip 2</td>

21 <td>Nachtschattengewächse im Dunkeln lagern</td>

22 </tr>

23 </table>

24 </body>

25 </html>

Innerhalb des <table>-Tags können verschiedene Attribute zur Formatierung gesetzt werden.Drei häufig verwendete Attribute des <table> wurden im Quellcode bereits angewendet.

• style="width:500px" : Die Tabellenbreite wird fest auf 500 Pixel gesetzt

• border="1" : Die Gitterlinien der Tabelle werden mit 1 Pixel Dicke dargestellt. Mit der

Page 25: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 25

Abbildung 2.5: Die Ausgabe von Beispiel 2.3.

Anweisung border="0" erhält man somit eine blinde Tabelle, also eine ohne sichtbareGitterlinien.

Die Standardvorgaben für die Tabelleneinträge sehen wie folgt aus:

• Die Breite der Spalten richtet sich nach der breitesten Tabellenzelle innerhalb dieser Spal-te.

• Die Höhe richtet sich nach der höchsten Tabellenzelle innerhalb dieser Reihe.

• Die Ausrichtung des Zelleninhaltes ist linksbündig und vertikal zellenzentriert.

Entsprechend kann man – allerdings mit gewissen Beschränkungen – auch einzelne Zeilen oderZellen formatieren, beispielsweise Breite, Höhe oder Hintergrundfarbe festlegen. Für die Dar-stellung von Zahlenspalten wird oft eine rechtsbündige Formatierung benötigt, die man mit CSSwie folgt erreicht:

<td style="text-align:right"> 21,99 &euro;</td>

Weitere Hinweise zur Formatierung von Tabellen mit Hilfe von CSS siehe

https://css-tricks.com/complete-guide-table-element/

2.4.3 Spaltenformatierung mit colgroupMit dem <colgroup>-Element können die Spalten einer Tabelle einheitlich formatiert werden.Das Element kann in dem <table>-Element vor dem ersten <tr>-Tag erscheinen und legt mit<col>-Tags die Formatierungen für die einzelnen Spalten fest.

<table>

<colgroup>

<col style="background-color:red;">

<col style="background-color:yellow;">

...

</colgroup>

<tr>

...

</tr>

</table>

Page 26: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

26 Andreas de Vries

Dabei kann mit dem Attribut span die Anzahl der betroffenen aufeinanderfolgenden Spaltenangegeben werden, wenn diese gleich zu formatieren sind. Beispielsweise werden in folgendemBeispiel die zweite und dritte Spalte gelb gefärbt, die erste rot:

<table>

<colgroup>

<col style="background-color:red">

<col span="2" style="background-color:yellow">

</colgroup>

<tr>

<th>ISBN</th>

<th>Titel</th>

<th>Preis</th>

</tr>

<tr>

<td>987-3-4768-96</td>

<td>My first HTML Table</td>

<td>$53,--</td>

</tr>

</table>

Weitere Informationen siehe http://w3schools.com/tags/tag_colgroup.asp.

2.5 FormulareIn HTML gibt als Benutzerschnittstelle zur Eingabe von Daten durch den Anwender die sogenannten Formulare, das <form>-Element. Um ein Eingabeformular wie in Abbildung 2.6 an-zeigen zu lassen, muss man in HTML den Quelltext 2.4 programmieren.

Listing 2.4: Ein Formular mit den wichtigsten Eingabeelementen1 <!DOCTYPE html>

2 <html>

3 <head>

4 <meta charset="UTF-8"/>

5 <title>Formular</title>

6 </head>

7 <body>

8 <h1>Eingabeformular</h1>

9 <form action="http://haegar.fh-swf.de/spiegel.php" method="GET">

10 <label for="an">Anmeldename:

11 <input type="text" name="anmeldename" id="an" placeholder="Name"/>

12 </label>

13 <br/>

14 <label for="pwd">Passwort:

15 <input type="password" name="passwort" id="pwd" />

16 </label>

17 <br/>

18 Tel: <input type="tel" id="phone" pattern="[-0-9]+"/>

19 <p>

20 <label><input type="checkbox" name="blume[]" value="Rose"/>Rose</label>

Page 27: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 27

21 <label>

22 <input type="checkbox" name="blume[]" value="Tulpe" checked/>Tulpe

23 </label>

24 <label><input type="checkbox" name="blume[]" value="Gerbera"/>Gerbera</label>

25 <label><input type="checkbox" name="blume[]" value="Lilie"/> Lilie</label>

26 </p>

27 <p>

28 Farbe:

29 <select name="farbe" size="1">

30 <option value="rot"> rot </option>

31 <option value="gelb" selected> gelb </option>

32 <option value="blau"> blau </option>

33 </select>

34 </p>

35 <fieldset>

36 <legend> Größe </legend>

37 <label><input type="radio" name="groesse" value="k"/>klein</label>

38 <label><input type="radio" name="groesse" value="m"/>mittel</label>

39 <label><input type="radio" name="groesse" value="g" checked/>groß</label>

40 </fieldset>

41 <p>

42 Frist: <input type="date" name="datum"/>

43 Uhrzeit: <input type="time" name="zeit" step="900" value="12:00"/>

44 </p>

45 Beitrag: <br/>

46 <textarea name="beitrag" rows="9" cols="45">

47 Da steh ich nun, ich armer Tor!

48 und bin so klug als wie zuvor;

49 heiße Magister, heiße Doktor gar,

50 und ziehe schon an die zehen Jahr

51 herauf, herab und quer und krumm,

52 meine Schüler an der Nase herum -

53 und sehe, dass wir nichts wissen können!

54 Das will mir schier das Herz verbrennen!

55 </textarea>

56 <hr/>

57 <input type="submit" value="Abschicken"/>

58 <input type="reset" value="zurücksetzen"/>

59 </form>

60 </body>

61 </html>

Die meisten Eingabeelemente werden durch das Element <input> implementiert, dessen At-tribut type über die Darstellung entscheidet. Allgemein sollte jedes Eingabeelement mit demAttribut name einen Namen erhalten, der in dem Formular eindeutig ist. Für die Darstellung istdieser Name zwar nicht wichtig, jedoch werden wir später sehen, dass dieses Attribut für dieserverseitige Verarbeitung der Eingabedaten notwendig ist.

Der Standardtyp ist type="text" und zeigt ein Textfeld an.

<input type="text" name="abc" value="Vorgabetext"/>

Page 28: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

28 Andreas de Vries

Abbildung 2.6: Die Ausgabe des HTML-Formulars aus Beispiel 2.4.

Page 29: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 29

Mit dem optionalen Attribut value kann hierbei ein Standardtext als Vorgabe angezeigt werden.Statt eines Wertes kann es auch einen Platzhaltertext beinhalten:

<input type="text" name="abc" placeholder="Platzhaltertext"/>

Er wird in dem Textfeld abgeschwächt angezeigt und verschwindet bei der ersten Eingabe. Erwird oft statt eines Textes vor dem Eingabefeld als Eingabehilfe verwendet.

Weitere Eingabeelemente sind durch die Typen "checkbox" und "radio" gegeben, die anklick-bare Checkboxen bzw. Radiobuttons darstellen. Zusammengehörige Auswahloptionen gehörenhierbei zu einer Gruppe und werden mit demselben Namen bezeichnet, erhalten jedoch mitdem Attribut value verschiedene Werte, die nicht mit den zu der jeweiligen Checkbox bzw.dem Radiobutton angezeigten Text übereinstimmen müssen. Der Unterschied der beiden Ein-gabeelemente ist, dass aus einer Gruppe von Radiobuttons nur höchstens ein Button angeklicktwerden kann, während eine Checkbox eine Mehrfachauswahl ermöglicht. Um bei einer Mehr-fachauswahl die korrekte Übertragung (und vor allem spätere Verarbeitung) zu ermöglichen,sollte der Name mit einem Paar eckiger Klammern enden:

<input type="checkbox" name="blume[]"/>

So werden die Daten in einem Array, also einer Art Datencontainer, übertragen und könnenvom Server „durchnummeriert“ werden (Arrays werden wir später im Zusammenhang mit PHPbehandeln).

Um die Bedienerfreundlichkeit zu erhöhen ist übrigens empfohlen, insbesondere Checkbo-xen und Radiobuttons jeweils in label-Elemente mit dem Attribut for zu umschließen, alsobeispielsweise:

<label for="klein">

<input type="radio" name="groesse" value="k" id="klein"/> klein

</label>

Hierbei bezieht sich der Wert des for-Attributs auf die id des umschlossenen Buttons, hierid="klein". Die Wirkung des <label>-Elements ist, dass der Anwender zur Auswahl nicht un-bedingt den Button bzw. die Checkbox anklicken muss, sondern auch den in dem Elemententhaltenen Text. Man kann das for- und das id-Attribut auch weglassen, die Wirkung bleibtdieselbe.

Entsprechend kann man die Bedienbarkeit durch eine Strukturierung der Engabelementemittels des <fieldset>-Elements erhöhen, die einen Rahmen um sie bildet. Mit dem Elementlegend kann man diesem Rahmen auch einen Namen geben, der in der Umrandung angezeigtwird.

Neben den <input>-Tags gibt es noch die Auswahlbox

1 <select name="farbe">

2 <option value="rot">rot</option>

3 ...

4 </select>

die mit dem optionalen Attribut size die Anzahl der in dem Sichtfenster angezeigten Optionenvorgibt. Eine Option kann standardmäßig vorausgewählt angezeigt werden durch das Attributselected. Ein längerer Text schließlich kann mitttels <textarea> eingegeben werden, dessenHöhe und Breite durch die Anzahl der Zeilen rows bzw. Spalten cols festgelegt.

Jedes <input>-Element kann als Attribut required erhalten. Damit wird bewirkt, dass derBrowser das Formular nicht abschickt in dem Fall, dass das Eingabeelement nicht ausgefülltbzw. ausgewählt wurde.

Page 30: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

30 Andreas de Vries

Das action-Attribut und der submit-Button

Wesentlich für die Übertragung der einegegebenen Daten zum Server sind das Attribut actionim Formular und der Submit-Button

<input type="submit"/>

Die Inhalte aller sonstigen <input>- und weiteren Eingabeelemente mit Namen (!) werden nachAnklicken des submit-Buttons an den URL im action-Attribut abgeschickt. Hier ist dies einPHP-Programm spiegel.php auf dem Haegar-Server, dass einfach die empfangenen Daten ineiner Tabelle wieder an den Browser zuücksendet.

2.5.1 Datenübertragung mit GET und POST

Wenn ein Browser eine Seite von einem Server anfordert, so wird die Kommunikation zwischenBrowser und Server über das HTTP-Protokoll abgewickelt. Als Teil der Anfrage und damit auchdes Protokolls überträgt der Browser eine „Methode“, mit der festgelegt wird, wie dem Servereventuelle Inhalte von Formularfeldern übermittelt werden. Standardmäßig ist diese MethodeGET, also beispielsweise auch bei einem normalen Aufruf einer HTML-Seite nach einem Klickeinen Hyperlink oder Eingabe eines URI Man kann in mit Hilfe der GET-Methode beliebigeDaten als Attribut-Werte-Paare übermitteln, indem zunächst ein Fragezeichen an den URI ge-hängt wird und die Attribut-Werte-Paare (ohne Leer- und Anführungszeichen) und durch einKaufmanns-Und voneinander getrennt werden, beispielsweise:

http://haegar.fh-swf.de/spiegel.php?x=5&y=10.5&art=koordinate

Probieren Sie es aus!Bei der HTML-Programmierung von Formularen legen wir über das method-Attribut des

<form>-Tags fest, welche Methode beim Abschicken des Formulars genutzt werden soll. Hiergibt es zwei Möglichkeiten: GET und POST. Bei POST werden die Daten gewissermaßen demRequest angehängt und erscheinen nicht in der URI. Dementsprechend können per POST über-mittelte Daten auch Binärdaten wie z.B. Dateien sein.

2.6 ZusammenfassungIn den zurückliegenden Seiten wurde ein Schnelleinstieg in HTML geliefert. Er soll dazu die-nen, kurz diejenigen HTML-Elemente vorzustellen, die wir im Folgenden benötigen werden.Er kann keinen Anspruch auf Vollständigkeit stellen. Insbesondere das schwierige Thema derGestaltung von Webseiten, vor allem unter dem Aspekt der Barrierefreiheit (Fußnote S. 23),kann im Rahmen dieses Skripts nicht vertieft werden. Auch können rechtliche Aspekte nichtangesprochen werden, die bei einem Webauftritt, insbesondere mit kommerziellen Absichten,zu beachten sind. Zur Vertiefung sei auf die selfhtml http://de.sefhtml.org empfohlen.

Page 31: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

3Cascading Stylesheets (CSS)

Kapitelübersicht3.1 Syntax: Deklarationen, Selektoren und CSS-Regeln . . . . . . . . . . . . . . . . . . . 313.2 Einbindung von CSS in HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333.3 Die Kaskadierung geschachtelter Regeln . . . . . . . . . . . . . . . . . . . . . . . . . 343.4 Media Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353.5 Weitere Informationen und Quellen . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

Cascading Stylesheets (deutsch: „geschachtelte Formatvorlagen“) dienen dazu, das Design unddas Layout von HTML-Seiten getrennt von dem eigentlichen Inhalt zu programmieren. DasDesign legt hierbei die Ästhetik einer Seite fest und ist häufig für einen vollständigen Webauf-tritt gültig, also „global“. Typischerweise bestimmt das Design die Farbgebung von Haupttext,Überschriften und Hintergrund. Das Layout einer Seite bezieht sich auf die Anordnung vonElementen, bestimmt also beispielsweise den Ort der Navigation.

3.1 Syntax: Deklarationen, Selektoren und CSS-RegelnDen Kern von Formatierungsanweisungen in CSS bilden Deklarationen, die Attribut-Wert-Paare sind und gemäß der Syntax

eigenschaft1: wert1;

eigenschaft2: wert2;

aufgebaut sind. Die Deklarationen werden durch Semikolons voneinander getrennt. Die Forma-teigenschaften und die jeweils möglichen Werte sind hierbei vorgegeben. Eine gute Übersichtdarüber findet man in dem Wiki von selfhtml.org:

http://wiki.selfhtml.org/wiki/CSS/Eigenschaften

Wie erfolgt nun genau die Verknüpfung zwischen den zu formatierenden HTML-Elementenund den definierten CSS-Deklarationen? Ein Selektor (oder einer Liste mehrerer durch Kommasgetrennter Selektoren) bildet hierbei die Auswahlbedingung für diejenigen Elemente des HTMl-Dokuments, für das die in geschweiften Klammern zu einem Block eingeschlossenen CSS-Regeln gelten sollen:

31

Page 32: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

32 Andreas de Vries

selektor1, selektor2 {

eigenschaftA: wertA;

eigenschaftB: wertB;

}

Das letzte Semikolon vor der schließenden geschweiften Klammer kann weggelassen werden.Ein solcher mit Selektoren versehener Block von CSS-Deklarationen heißt CSS-Regel. WichtigeSelektoren sind die folgenden:

• Ein Typselektor: wählt Elemente abhängig von einem angegebenen HTML-Elementtypaus, also z.B. <p> (allerdings ohne die spitzen Klammern!).

• Ein Klassenselektor beginnt mit einem Punkt und seinem Namen dahinter (.meineKlasse)und wählt diejenigen Elemente des HTML-Dokuments aus, deren Attribut class diesenspezifizierten Wert haben, also beispielsweise

<p class="meineKlasse"> ... </p>

• Ein ID-Selektor beginnt mit einem Doppelkreuz und wählt das (eindeutige) Element einesDokuments aus, das den Wert des ID-Attributes hat.

<!DOCTYPE html><html><head><style type="text/css">.someDiv {

width: auto;margin: 20px;padding: 20px;border: 5px solid LightBlue;

color: #ffffff;text-align: center;font-family: Arial;

}</style>

</head><body>

class="someDiv">CSS is awesome!

</div></body></html>

Quelltext Ausgabe im Browser

Dimensionen

Auflistung aller CSS-Eigenschaften

http://www.w3.org/TR/CSS2/propidx.html

background-color: DarkSlateBlue;

<div

Abbildung 3.1: Funktionsweise eines Klassenselektors und der Begrenzungsregeln in CSS.

An beliebiger Stelle einer CSS-Regel können Kommentare eingefügt werden, z.B.:

/* Kommentare wie in C, Java, PHP, ...*/

selektor1, selektor2 {

eigenschaftA: wertA;

eigenschaftB: wertB;

}

Kommentare werden von /*...*/ umschlossen.Bereits hier erkennen wir, dass die Syntax von CSS völlig unterschiedlich zu derjenigen von

HTML ist. Insbesondere wird in CSS kein Gleichheitszeichen verwandt, sondern der Doppel-punkt, und zwischen zwei Deklarationen muss stets ein Semikolon erscheinen, ganz im Gegen-satz zu HTML. Wir haben also das grundsätzliche Problem, CSS-Anweisungen in ein HTML-Dokument „einzuschleusen“. Es gibt drei Arten der Einbindung, die im folgenden Abschnittdargestellt werden.

Page 33: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 33

3.2 Einbindung von CSS in HTMLCSS-Anweisungen müssen in ein HTML-Dokument eingebunden werden. Man unterscheidetdrei Formen der Einbindung von CSS-Quelltext in ein HTML-Dokument:

• Inline: Bestehende HTML-Elemente werden um ein Attribut namens style erweitert, dasCSS-Deklarationen für dieses Element enthält. Die Syntax dazu lautet (am Beispiel des<div>-Elements):

<div style="eigenschaft1: wert1; eigenschaft2: wert2"> ... </div>

Die Deklarationen dürfen hierbei nicht durch geschweifte Klammern zu einem Blockzusammengefasst werden und dürfen keinen Selektor enthalten. Letzteres ist auch garnicht nötig, das Style-Attribut betrifft nur das Element, in dem es definiert wird. DieInline-Einbindung eignet sich für individuelle Adhoc-Formatierungen.

• Embedded: CSS-Regeln werden im <head>-Bereich eines HTML-Dokuments definiert.

<head>

<title>A title</title>

<style>

h1 {

color: red;

}

</style>

</head>

<body>

...

</body>

Die CSS-Anweisungen gelten dann für das gesamte Dokument. Man kann das <style>-Element auch um das Attribut type="text/css" ergänzen, es ist jedoch für HTML5 (<!DOCTYPEhtml>) nicht mehr notwendig. Diese Einbindungsart eignet sich für generelle CSS-Regeln,die sich auf das gesamte Dokument beziehen.

• Extern: CSS-Regeln werden in einer externen Datei definiert und im <head>-Element alsLink verknüpft.

<head>

<title>A title</title>

<link rel="stylesheet" href=" ... Pfad zur CSS-Datei ..." />

</head>

Die CSS-Datei enthält ausschließlich CSS-Regeln mit Selektoren und Deklarationsblö-cken sowie Kommentare. Diese Form der Einbindung eignet sich für generelle CSS-Regeln, die sich auf alle Dokumete des gesamten Webauftritts beziehen sollen.

Beispiel 3.1. Beispiele für die Arten der Einbindung von CSS-Anweisungen in ein HTML-Dokument.

(a) Inline

<h1 style="color:red;">FH SWF</h1>

(b) Eingebettet

Page 34: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

34 Andreas de Vries

<head>

<title>A title</title>

<style>

h1 {

color: red;

}

</style>

</head>

<body>

...

</body>

(c) Externe Datei, z.B.:

<head>

<title>A title</title>

<link rel="stylesheet" href="./fhswf.css" />

</head>

mit der Datei fhswf.css im selben Verzeichnis:

h1 {

color:red;

}

Die CSS-Anweisungen können dann in mehreren verschiedenen HTML-Dokumenten verwen-det werden. �

Bei Inline-Styles ist nur das HTML-Element verknüpft, dessen <style>-Attribut es belegt.Eingebettete und externe Definitionen müssen mit Selektoren arbeiten.

3.3 Die Kaskadierung geschachtelter RegelnAufgrund der verschiedenen Einbindungsmöglichkeiten und der Verschachtelungen von forma-tierten HTML-Elementen können mehrere CSS-Regeln zur selben Formateigenschaft in einembestimmten HTML-Element vorhanden sein. CSS verspricht durch das „C“ in seinem Nameneine Kaskadierung von Formatanweisungen. Wie genau sieht diese Kaskadierung der Regelnaus? Welcher Stil wird denn nun angewendet bzw. welche Farbe hat der Text in der Darstellung?Die Kaskadierung in CSS richtet sich hauptsächlich nach der direkten Verarbeitungsreihenfolgedes Browsers, also nach den folgenden Prioritäten:

1. Die CSS-Regel des innersten formatierten HTML-Elements hat die höchste Priorität.

2. Die Priorität hängt dann ab von der Einbindungsart der CSS-Regel,

inline > embedded > extern.

(Also „inline“ gewinnt immer!)

3. Die Priorität hängt bei eingebetteten oder der externen Einbindung ab vom Selektor, ge-mäß

ID-Selektor > Klassenselektor > Typselektor.

Diese Prioritätenregeln („Spezifitäten“) können explizit außer Kraft gesetzt werden, und zwarmit den !important-Anweisungen, siehe http://www.w3.org/TR/CSS2/cascade.html#specifity.

Page 35: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 35!""#"$%$&'()*+,$-./-$%$+!!"#$%&'()*+!,-"&!"#$%&'()*+,'(%-"#("*)"(./011"(23"#(456(7%#3"(0/12()8#(38#+,(3")(9:;(<;=(1"/">'*"#'(7"#3")?(

!!&"#$%%&'()*+(,-'"#$%&'()*+!,-"&@%#3"(%-"#(3")(9:;(23"#(3*"(./011"(A81&"7B,/'(7"#3")?(

!!&).&'()*/)0$1-)0'&"#$%%&'()*+(,-'"&#$%&'()*+!,-"&@%#3"(38#+,(0//"(C"/">'2#")(081&"7B,/'(7"#3")?(

!&.&&&/01023&1(.4&5&

2()*+(,-3.&&&/01023&4#5(4&5&

6()*/)0$1-)03.&&&/01023&01((*4&5&

01/.$%$2'()+

3%4..$5.$%$2'()+678+

9:#"$%$2'()+6;8+

<=52'+678+=5>++?4='$+6;8++@$4&A'$5B+

Abbildung 3.2: Selektoren in CSS. Welche Farbe hat der Text jeweils?

3.4 Media QueriesWebseiten müssen auf mobile Endgeräte reagieren („Responsive Webdesign“). In der Version3 bietet CSS hierfür die sogenannten Media Queries an,

http://www.w3.org/TR/#tr_CSS.

Sie ermöglichen die Erkennung verschiedener Geräte und Geräteklassen anhand von deren Auf-lösung und Orientierung. Die Syntax für Media Queries ist wie folgt:

@media ( ... Bedingung ... ) {

{ ... CSS-Regeln ... }

}

Hinter dem Schlüsselwort @media folgt in runden Klammern eine Bedingung, die bei Erfüllungden nachfolgenden Block von CSS-Regeln gültig werden lässt.

Betrachten wir dazu das folgende Beispiel.

1 <!DOCTYPE html>

2 <html>

3 <head>

4 <style type="text/css">

5 @media (max-width: 480px) {

6 table {

7 display: none;

8 }

9 }

10 </style>

11 </head>

12 <body>

13 <table>

14 <tr>

15 <td>1</td>

16 <td>2</td>

17 </tr>

18 </table>

Page 36: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

36 Andreas de Vries

19 </body>

20 </html>

Hierbei leitet @media ein Media Query ein, das in Alltagssprache ausformuliert etwa lautenwürde: „Blende auf Geräten mit einer maximalen Auflösung von 480 Pixeln alle Elemente vomTyp table aus!“ Ist also der Bildschirm klein genug, greift die CSS-Deklaration display: none,die die Tabelle verschwinden lässt.

Mehrere Bedingungen können in einem Media Query mit dem Schlüsselwort and verknüpftwerden.

1 <!DOCTYPE html>

2 <html>

3 <head>

4 <title>Aktion</title>

5 <style>

6 @media (min-width: 800px) {

7 div {

8 background-color: green; color: white;

9 }

10 }

11 @media (min-width: 600px) and (max-width: 800px) {

12 div {

13 background-color: yellow;

14 }

15 }

16 @media (max-width: 600px) {

17 div {

18 background-color: #FF0000;

19 }

20 }

21 </style>

22 </head>

23 <body>

24 <div>

25 Da steh ich nun, ich armer Tor

26 </div>

27 <div>

28 Und bin so klug als wie zuvor.

29 </div>

30 </body>

31 </html>

Bei diesem Media Query wechseln die <div>-Elemente ihre Hintergrundfarbe bei Veränderungder Fensterbreite, und zwar für die drei Fälle

800 px < Breite, 600 px < Breite < 800 px, Breite < 600 px,

3.5 Weitere Informationen und Quellen• http://www.w3.org/standards/techs/css#w3c_all – Die aktuellen Standards, formal und

trocken; wenig Beispiele

Page 37: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 37

• http://wiki.selfhtml.org/wiki/CSS – deutschsprachige Erklärungen und gute Beispiele

• https://developer.mozilla.org/en-US/docs/Web/CSS – englischsprachige Beispiele undTutorien (teilweise auf Deutsch übersetzt)

• https://css-tricks.com/snippets/css/ – viele Beispiele, auch ausgefallene

Page 38: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

4Formate zum Datenaustausch

Kapitelübersicht4.1 XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

4.1.1 Die Idee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394.1.2 Elemente und Tags, Inhalt und Attribute . . . . . . . . . . . . . . . . . . . . . 394.1.3 Wohlgeformte XML-Dokumente . . . . . . . . . . . . . . . . . . . . . . . . . 414.1.4 Gültige XML-Dokumente . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

4.2 JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464.3 Binäre Austauschformate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

4.3.1 BSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484.3.2 CBOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

4.4 Textbasierte versus binäre Austauschformate . . . . . . . . . . . . . . . . . . . . . . . 48

Das World Wide Web Consortium [W3C] ist ein 1994 gegründetes Gremium zur Standardisie-rung von Web-Techniken. Ein solcher durch das W3C festgelegter Standard zur Definition undzum allgemeinen Datenaustausch ist XML. Es ist gewissermaßen eine Obermenge zu HTML,oder anders ausgedrückt: HTML ist eine spezielle Instanz von XML. Obwohl XML seit den2000er Jahren sich in seiner Allgemeingültigkeit zu einem weitverbreitetem Format zum text-basierten Datenaustausch entwickelt hat, gibt es andere Formate, die sich erfolgreich etablierenkonnten. Die wichtigsten darunter sind JSON als ein weiteres textbasiertes Format, aber auchbinäre Formate wie BSON oder CBOR.

4.1 XMLXML ist ein Akronym für eXtensible Markup Language, also eine erweiterbare Auszeichnungs-sprache.1 XML ist eine Metasprache, d.h. es lassen sich mit XML wiederum Sprachen fürbestimmte spezielle Zwecke definieren [6, S. 9], beispielsweise XHTML (eine „strenge Vari-ante“ von HTML). Obwohl XML in 1998 zunächst nur für elektronische Veröffentlichungenvon Dokumenten konzipiert war, etablierte es sich zunehmend auch als allgemeines Daten-austauschformat. Die Sprachspezifikationen werden vom World Wide Web Consortium [W3C]festgelegt.

1 Eine Auszeichnungssprache ist eine formale Sprache, die Teile eines Textes (meist ASCII oder Unicode)durch Markierungen beschreibt, so dass sie auf bestimmte Weise dargestellt werden können. Beispiele für Aus-zeichnungssprachen sind HTML, LaTeX oder Wikitext (der bei Wikipedia verwendet wird).

38

Page 39: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 39

4.1.1 Die IdeeBevor wir auf die Spezifikationen genauer eingehen, ist es hilfreich, sich die grundlegende Ideevon XML zu verdeutlichen. Da XML mit dem Anspruch entwickelt wurde, eine Rahmenspra-che zur Speicherung und Veröffentlichung von Dokumenten zu sein, muss zunächst einmal dieFrage beantwortet werden: Woraus besteht eigentlich ein Dokument? Was muss demnach allesgespeichert werden?

Ein allgemeines Dokument kann beispielsweise ein Formular, ein Vertrag, ein Brief, eineZeitung oder ein Buch sein. Ein Dokument besitzt immer einen Inhalt, beispielsweise als Text

Abbildung 4.1: Die logischen Bestandteile eines Dokuments und das Prinzip von XML.

oder als Bilder, eine innere Struktur, wie Fließtexte, Paragraphen, Kapitel, und eine konkre-te Form der Darstellung, z.B. Formatierungen, Wahl des Mediums wie Papier oder Karton.Diese drei Strukturbausteine sind in Abb. 4.1 links illustriert. Entsprechend trennt XML alsTechnologie prinzipiell den Inhalt, die Form und die Struktur eines Dokuments. Hierbei wirddas konkrete Dokument mit seinem Inhalt als ein XML-Dokument gespeichert, die Strukturin einer XML-Schema-Datei (XSD, früher oft auch in einer DTD) und die Art der Darstel-lung in einem XSL-Programm, das die Formatierungen konkret darstellt (z.B. ein Browser, derXHTML-Dokumente im Fenster anzeigt), oder ein XSLT-Programm, das das XML-Dokumentin ein spezielles Format (z.B. PDF) umformt.

Beispiel 4.1. Ein Beispiel für eine XML-Sprache ist XHTML, eine Art „strenges HTML“,nämlich HTML gemäß den noch zu nennenenden XML-Regeln. (Historisch entstand HTMLvor XML.) Die Struktur XHTML ist in einer DTD-Datei, d.h. einer Strukturdatei, festgelegt. Mitdieser Struktur ist definiert, welche Tags überhaupt und in welchen Verschachtelungen erlaubtsind. �

4.1.2 Elemente und Tags, Inhalt und AttributeAllgemein besteht ein XML-Dokument aus Unicode-Text. Die einzigen allgemein in XMLreservierten Zeichen mit bestimmter Bedeutung sind die spitzen Klammern, das Kaufmanns-Und (ampersand), das Semikolon, das Gleichheitszeichen, die Anführungszeichen oben undder Apostroph:

Zeichen < > & ; = " ’

Unicode &#x3C; &#x3E; &#x26; &#x3B; &#x3D; &#x22; &#x27;XML-Entität &lt; &gt; &amp; &#x3B; &#x3D; &quot; &apos;

(4.1)

Allerdings haben diese Zeichen nur in bestimmten Kombinationen eine Bedeutung, beispiels-weise hat das Semikolon nur nach einem Kaufmanns-Und Auswirkungen, oder das Gleichheits-zeichen und die Anführungszeichen nur innerhalb von spitzen Klammern. Die ausführlichenSyntaxregeln für die Grundbausteine finden Sie zum Beispiel in [15, S. 12].

Page 40: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

40 Andreas de Vries

Die Bausteine von XML-Dokumenten sind Elemente. Sie werden von Tags (Auszeichnun-gen) umschlossen. Tags tauchen also stets paarweise auf, nämlich als Start-Tag und als Ende-Tag. Man schreibt dabei das Start-Tag, indem man den Namen des Elements in spitzen Klam-mern schreibt, und das Ende-Tag zusätzlich mit einem Schrägstrich (slash) versieht, also etwa

<name> . . . </name>

Das Innere „. . . “ des Elements zwischen den Tags kann einen beliebigen Unicode-Text, denInhalt des Elements, oder wiederum Elemente enthalten.

Falls ein Element kein Kindelement und keinen Inhalt besitzt, heißt es leer und kann kurzgeschrieben werden als <name/>, d.h.

<name/> = <name></name>.

Ein Element kann mehrere Attribute enthalten. Ein Attribut ist eine bestimmte Eigenschaft desElements und kann einen Wert aus einer vorgegebenen Menge annehmen. Es wird in das Start-Tag des Elements geschrieben und sein Wert nach einem Gleichheitszeichen dahinter in Anfüh-rungszeichen:

<name attribut="wert"> . . . </name>

Eine Prozessinstruktion (processing instruction, PI) oder Verarbeitungsanweisung ist in XMLein spezielles Tag, das mit einem Fragezeichen beginnt und direkt dahinter einen Namen auf-weist,

<?name . . . ?>

siehe [15, S. 28]. Beispielsweise ist <?php ... ?> eine solche Prozessinstruktion, die wir imZusammenhang mit PHP noch kennen lernen werden. Zu Beginn eines XML-Dokuments musseine spezielle Prozessintruktion stehen, die XML-Deklaration:

<?xml version="1.0"?>

Sie gibt an, welche XML-Version verwendet wird. Aktuell gibt es nur die zwei Versionen 1.0und 1.1, allerdings verstehen die meisten Browser verlässlich nur Version 1.0.2 Daneben kannes ein Attribut encoding geben, das die Textkodierung festlegt, sowie ein Attribut standalone,das anzeigt, ob das vorliegende Dokument keine externe Strukturdatei (XML Schema, DTD,. . . ) benötigt,

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

Das Attribut für die Version ist obligatorisch, die anderen beiden sind optional. Sind sie jedochvorhanden, so ist die Reihenfolge version→ encoding→ standalone vorgeschrieben.

Ferner können Kommentare an beliebiger Stelle nach dem Vorspann (s.u.) in ein XML-Dokument eingefügt werden, und zwar wie in HTML mit der Syntax

<!- ... ->

Ein Kommentar ist also genau wie eine Prozessinstruktion nur ein einzelner Tag, kein Element.Beides kann und darf daher nicht wie eine leeres Element geschlossen werden.

2 https://www.w3.org/XML/Core/. Der wesentliche Unterschied zwischen den Versionen 1.0 und 1.1 ist dass1.1 stets automatisch die aktuellste Version des Unicode erlaubt.

Page 41: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 41

4.1.3 Wohlgeformte XML-Dokumente

Ein wohlgeformtes (well-formed) XML-Dokument hat folgende Kriterien zu erfüllen:

• Es enthält genau ein Wurzelelement, das Dokumentelement, dessen Start- und Ende-Tagdas gesamte Dokument (bis auf die Prozessinstruktion am Anfang) umschließt.

• Jedes Element muss geschlossen werden, auch wenn es leer ist. In HTML übliche Kon-strukte wie <p> bla <p> blubb , bla <br> blubb , <input ...> oder <img ...> sind da-mit kein wohlgeformtes XML.

• Elemente dürfen nur streng ineinander verschachtelt werden. Das impliziert, dass ein in-neres Element erst geschlossen sein muss, bevor ein äußeres geschlossen werden kann.

Abbildung 4.2: Die logische Baumstruktur eines XML-Dokuments.

Auf diese Weise entsteht eine streng logische Baumstruktur ineinander geschachtelterElemente wie in Abb. 4.2.

• Groß- und Kleinschreibung für Element- und Attributnamen muss streng beachtet wer-den. <p> ... </P> ist also nicht wohlgeformtes XML.

• Attributwerte müssen in Anführungszeichen stehen. <img border=0/> ist also nicht wohl-geformt.

• Ein Attributname darf nur einmal im Start-Tag vorkommen.

• Die in (4.1) aufgelisteten Sonderzeichen dürfen nicht innerhalb von Element- oder At-tributnamen auftauchen, die Zeichen <, " und & nicht einmal in Attributwerten. Auch inElementinhalten darf < gar nicht und & nur in definierten Fällen in Kombination mit einemSemikolon (also Begrenzer von „Entitäten“) erscheinen. Man kann beliebige Zeichenfol-gen (außer ]]>) in CDATA-Sektionen schreiben (CDATA steht für Character Data):

<![CDATA[ <hier kann <alles & stehen>!]]> (4.2)

als Elementinhalt wäre also wohlgeformtes XML. Alternativ können die Zeichen mit denaus HTML bekannten Entitäten &lt;, &gt; und &amp; dargestellt werden oder durch ihreUnicode-Werte &#x3C;, &#x3E; und &#x26; gemäß Tabelle (4.1).

Die Wohlgeformtheit eines XML-Dokuments können schon Browser wie Firefox und Inter-net Explorer überprüfen. (Probieren Sie es mal aus!) Das XML-Dokument in Beispiel 4.1 istwohlgeformtes XML.

Page 42: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

42 Andreas de Vries

Listing 4.1: Das XML-Dokument Buch.xml1 <?xml version="1.0" encoding="UTF-8"?>

2 <buch>

3 XML in zwei Schritten.

4 <kapitel>

5 Der erste Schritt

6 <abschnitt ausrichtung="Blocksatz">

7 Am Anfang gab es nur Worte, erst später

8 kam die Struktur.

9 </abschnitt>

10 <abschnitt>

11 Die meisten entspannen bei Musik, nur wenige auch bei mathematischen

12 Ungleichungen der Form x + 1 &#x3C; x*x.

13 </abschnitt>

14 </kapitel>

15 </buch>

Abbildung 4.3: Die Ausgabe von Beispiel 4.1 im Firefox.

Generell können Element- oder Attributnamen in XML jedes Zeichen des spezifizierten Zei-chensatzes enthalten, bis auf die Sonderzeichen von (4.1). Wohlgeformt gemäß XML wärenalso die Elemente <tele.fon nummer="0123/> oder <e-mail>[email protected]</e-mail> .

4.1.4 Gültige XML-DokumenteOft ist ein XML-Dokument schon einsetzbar, wenn es wohlgeformt ist, beispielsweise für denDatenaustausch zwischen Datenbanken. Die Wohlgeformtheit sagt jedoch noch nichts über dieFrage aus: Welche Elemente und Attribute sind überhaupt möglich, und in welcher Kombinati-on? Ein XML-Dokument heißt gültig (valid), wenn seine Elemente der in einer (meist separatgespeicherten) Strukturdatei festgelegten Elementenstruktur entsprechen. In einer Strukturdateiwird genau beschrieben, welche Elemente in der XML-Sprache überhaupt existieren, welcheAttribute sie haben können oder müssen, und wie die Elemente verschachtelt sein dürfen.

Für XML gibt es mehrere Struktursprachen. Die älteste ist die DTD Document Type Defini-tion), sie ist die Struktursprache für XHTML. Da DTD selbst allerdings keine XML-Sprache ist,

Page 43: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 43

entwickelte das W3C als Alternative XML Schema. In einer DTD sind die beiden grundlegen-den Datentypen Strings (in DTD-Syntax: #PCDATA, für parsed character data) und Notationen(<!NOTATION ...>), die nicht verarbeitet (geparst) werden sollen und als Referenz auf externeDateien dienen. Eine detaillierte Beschreibung von DTD und ihrer Syntax findet man in z.B. [6,S. 30ff] oder [15, S. 38ff].

Namensräume

Das Konzept der Namensräume (name spaces) gibt es in vielen Programmiersprachen. In Ja-va ist es beispielsweise über Pakete implementiert. Generell ist der Sinn von Namensräumen,Datei- oder Objektnamen eindeutig referenzierbar zu halten bei gleichzeitig größtmöglicherFreiheit bei der Namensvergabe eigen erstellter Dateien oder Objekte. So gibt es beipielswei-se in Java zwei Klassen Date, die allerdings in verschiedenen Paketen liegen (java.util bzw.java.sql).

Ohne Namensräume müsste ein Programmierer also jedesmal überprüfen, ob der Name,den er vergeben möchte, bereits belegt ist, um gegebenenfalls einen anderen Namen wählen zumüssen. Damit würde natürlich ein wichtiger Aspekt der Namensvergabe, nämlich „sprechendeNamen“ zu verwenden, insbesondere für große Systeme erheblich ausgehöhlt. Innerhalb einesNamensraums müssen die Namen selbstverständlich unterschiedlich sein.

Auch in XML gibt es Namensräume. Ein Namensraum in XML ist (meist) ein allgemeinerURI.3 Das spezielle Attribut xmlns spezifiziert eine Namensraum-Deklaration in XML. Es gibtzwei Möglichkeiten, in XML Namensräume zu definieren: Entweder mit der Standardnamensraum-Deklaration

1 <unternehmen id="4711" xmlns="http://example.org/">

2 <name>XYZ GmbH</name>

3 <telefon>

4 <anlage>Siemens</anlage>

5 <technologie>Voice Over IP</technologie>

6 </telefon>

7 </unternehmen>

für die der Namensraum in allen Unterelementen gilt, oder mit der qualifizierten Namensraum-Deklaration,

1 <it:unternehmen id="4711" xmlns:it="http://example.org/">

2 <it:name>XYZ GmbH</it:name>

3 <it:telefon>

4 <it:anlage>Siemens</it:anlage>

5 <it:technologie>Voice Over IP</it:technologie>

6 </it:telefon>

7 </it:unternehmen>

mit einem Präfix (hier: it), durch das in jedem Unterelement gezielt ein Namensraum ausge-wählt werden kann. Qualifizierte Namensräume werden insbesondere dann unabdingbar, wennin einem XML-Dokument mehrere Namensräume benötigt werden.

3 URI (Uniform Resource Identifier): ein nach dem Prinzip Schema: schemaspezifischer Teil aufgebau-ter Identifikator einer abstrakten oder physischen Ressource wie Webseiten, Dateien, Webservices, E-Mail-Empfängern.[RFC3986] Beispielsweise ist http://haegar.fh-swf.de ein URI, oder doi:10.1002/piuz.200401040.Spezielle URIs sind URL (Unified Resource Locators), also Internetquellen. Allerdings wird die BezeichnungURL von dem W3C als deprecated eingestuft [RFC3305, §2.2].

Page 44: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

44 Andreas de Vries

XML Schema

XML Schema, oft auch als XSD bezeichnet, stammt ursprünglich von Microsoft und wurde2001 zum W3C-Standard [XSD]. Im Unterschied zu DTD basiert XML-Schema komplett aufXML und hat wesentlich mehr Datentypen als DTD. Allerdings sind komplexe Strukturen ineiner DTD erheblich kürzer beschreibbar.

Beispiel 4.2. Das XML Schema Buch.xsd:

1 <?xml version="1.0" encoding="UTF-8"?>

2 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"

3 targetNamespace="http://example.org/Buch" xmlns="http://example.org/Buch" >

4

5 <xs:element name="buch" type="buchTyp" />

6

7 <xs:complexType name="buchTyp" mixed="true">

8 <xs:sequence>

9 <xs:element name="kapitel" type="kapitelTyp"

10 minOccurs="0" maxOccurs="unbounded" />

11 </xs:sequence>

12 </xs:complexType>

13

14 <xs:complexType name="kapitelTyp" mixed="true">

15 <xs:sequence>

16 <xs:element name="abschnitt" type="abschnittTyp"

17 minOccurs="0" maxOccurs="unbounded" />

18 </xs:sequence>

19 </xs:complexType>

20

21 <xs:complexType name="abschnittTyp" mixed="true">

22 <xs:attribute name="ausrichtung">

23 <xs:simpleType>

24 <xs:restriction base="xs:string">

25 <xs:enumeration value="Blocksatz"/>

26 <xs:enumeration value="linksbündig"/>

27 <xs:enumeration value="zentriert"/>

28 </xs:restriction>

29 </xs:simpleType>

30 </xs:attribute>

31 </xs:complexType>

32

33 </xs:schema>

und ein entsprechendes XML-Dokument:

1 <?xml version="1.0" encoding="UTF-8"?>

2 <p:buch xmlns:p="http://www.example.org/Buch"

3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4 xsi:schemaLocation="http://www.example.org/Buch Buch.xsd ">

5 XML in zwei Schritten.

6 <kapitel>

7 Der erste Schritt

Page 45: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 45

8 <abschnitt ausrichtung="Blocksatz">

9 Anfang gab es nur Worte, erst später

10 kam die Struktur.

11 </abschnitt>

12 <abschnitt>

13 Die meisten entspannen bei Musik, nur wenige auch bei mathematischen

14 Ungleichungen der Form x + 1 &#x3C; x*x.

15 </abschnitt>

16 </kapitel>

17 </p:buch>

Die Verschachtelung der Elemente des XML-Dokuments ist in dem XML-Schema vordefiniert.�

Ein XML-Schema besteht aus einem schema-Element als Wurzel, mit einem fest vorgege-benem Namensraum (im Beispiel mit xs bezeichnet). Es enthält im Wesentlichen die Elementeelement, die wiederum als obligatorisches Attribut name besitzen. Mit diesen Elementen defi-niert man genau die Elemente, die in einem XML-Dokument erlaubt sind.

Jedes Element muss von einem angegebenen Datentyp sein. Diesen Datentyp kann mananonym direkt anlegen, indem man einfach die beinhalteten Elemente als Kindelemente ein-baut, oder aber, indem man die Datentypen als Elemente definiert. Es gibt eine ganze Reiheelementarer Datentypen in XML-Schema, die wichtigsten sind:

• boolean mit den mögliche Werten "true" (oder "1"), und "false" (oder "0");

• double gemäß IEEE 754;

• hexBinary für binäre Daten mit Wörtern aus den Zeichen 0–9, A–F, a–f;

• int für Ganzzahlwerte mit 4 Byte;

• integer für beliebige ganze Zahlen (ohne Speicherbegrenzung);

• string für alle Unicode-Wörter ohne die Zeichen <, > und &.

Eine vollständige Liste aller in XML-Schema vorgesehenen Datentypen befindet sich in [15,S. 91ff].

Daneben kann man mit XML-Schema komplexe Datentypen definieren, nämlich durch dasElement complexType. Es beinhaltet weitere Elemente, allerdings benötigt es als direktes Kind-element (u.a.) choice (für eine beliebige Reihenfolge der umschlossenen Elemente) oder se-quence (für eine durch die Reihenfolge ihres Auftretens festgelegte Reihenfolge der umschlos-senen Elemente). Ein komplexer Typ, der neben inneren Elementen auch Text als Inhalt enthal-ten kann, muss das Attribut mixed mit dem Wert "true" besitzen. Jedes so definierte Elementmuss genau einmal im XML-Dokument auftauchen, es sei denn, die beiden Attribute minOc-curs and maxOccurs sind mit Werten "0", "1", . . . oder "unbounded" angegeben (voreingestellterWert jeweils: "1"). Natürlich muss minOccurs 5 maxOccurs gelten.

Ferner werden die möglichen Attribute eines Elements definiert durch das Element attri-bute, und zwar innerhalb des betreffenden Elements als Kindelemente. Es enthält als Attributezwingend name und optional use, das vorbelegt den Wert "false" hat und bei "required" als At-tribut im XML-Dolument auftauchen muss. Soll ein Attribut nur bestimmte Werte annehmen, sokann man das durch das Kindelement simpleType, dann restriction und schließlich enumerationerreichen:

Page 46: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

46 Andreas de Vries

1 <xs:simpleType>

2 <xs:restriction base="xs:string">

3 <xs:enumeration value="Blocksatz"/>

4 <xs:enumeration value="linksbündig"/>

5 <xs:enumeration value="zentriert"/>

6 </xs:restriction>

7 </xs:simpleType>

Hierbei legt das Attribut base im restriction-Element den Datentyp der Grundmenge fest, unddas Attribut value in enumeration definiert jeweils einen Wert der Grundmenge.

Namensräume in XSD. Der Umgang mit Namensräumen in XSD kann beliebig kompliziertwerden, insbesondere wenn man nichtqualifizierte Elemente und gleichzeitig qualifizierte At-tribute verwendet. Eine Grundregel, die sich erfahrungsgemäß bewährt hat, lautet:

Merkregel 1. Arbeitet man mit Namensräumen in einem XML-Schema, so sollte man die Ele-mente qualifizieren, nicht aber die Attribute.

Einbindung von XSD in ein XML-Dokument Eine XML-Schema-Datei wird als Instanz indas Wurzelelement eines XML-Dokuments eingebunden.

Validierung eines XML-Schema-Dokuments

Die meisten XML-Editoren haben eingebaute Validierungsmöglichkeiten, um ein XML-Doku-ment gegen ein XML-Schema oder eine DTD zu validieren. Daneben gibt es jedoch auch einenOnline-Validator vom W3C, http://www.w3c.org/2001/03/webdata/xsv/

4.2 JSONJSON, kurz für JavaScript Object Notation und gesprochen wie der englische Name Jason,ist ein schlankes textbasiertes Format zum Datenaustausch zwischen Software-Anwendungenund zum RPC (Remote Procedure Call, d.h. Aufruf von Methoden auf anderen Rechnern). WieXML verwendet JSON Unicode.

Das JSON-Format ist spezifiziert in RFC71594, der offizielle Internet Media Type (früher„MIME“) für JSON ist application/json. JSON kennt als Attributnamen Strings (in Anfüh-rungszeichen!) und als Werte Strings (in Anführungszeichen), Zahlen und die Konstanten null,true und false. Diese Elemente können auf zwei Arten als Datenstruktur zusammengefasstwerden, einerseits als (numerisch indiziertes) Array

["Hallo", 123, null, false, true, "John Doe"]

in eckigen Klammern, oder als Attribut-Werte-Paare (assoziatives Array, Map)

{"key":"Abc", "key2":123, "key3":null, "flag":true}

in geschweiften Klammern. Üblicherweise werden einfache Listen in JSON durch ein Arraydargestellt, also zum Beispiel die Liste der ersten 5 Primzahlen als

[2, 3, 5, 7, 11, 17]

4 http://tools.ietf.org/html/rfc7159

Page 47: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 47

Vornehmlich wird JSON in AJAX-Webapplikationen eingesetzt als Alternative zu XML, aller-dings gibt es eine ganze Reihe von Programmen, die JSON in Objekte anderer Programmier-sprachen wie Java transformieren und umgekehrt, vgl. http://json.org, so beispielsweise eineJava-API von Google5 Ein einfaches Beispiel, welches eine Struktur in JSON mit der entspre-chenden XML-Struktur vergleicht, ist in Tabelle 4.1 angegeben. Hierbei wurde die Liste der

Besucher in XML6 Besucher in JSON<besucher>

<id>481048</id>

<name>Peter Müller</name>

<email>[email protected]</email>

<gebuchteKurse>5</gebuchteKurse>

<gebuchteKurse>21</gebuchteKurse>

<gebuchteKurse>22</gebuchteKurse>

<gebuchteKurse>23</gebuchteKurse>

<gebuchteKurse>40</gebuchteKurse>

<gebuchteKurse>44</gebuchteKurse>

</besucher>

{

"id": 481048,

"name": "Peter Müller",

"email": "[email protected]",

"gebuchteKurse": [

5,

21,

22,

23,

40,

44

]

}

Tabelle 4.1: Beispielstruktur Besucher in XML und JSON

gebuchten Kurse in JSON kurz als ein Array implemenitiert.Es ist sofort ersichtlich, dass Dateien in JSON weniger Speicherplatz einnehmen. Ein wich-

tiger Unterschied zwischen den beiden Formaten XML und JSON ist ferner, dass XML-Dateienüber die Forderung nach Gültigkeit eines Dokuments erzwingen kann, dass sie einem festen vor-gegeben Schema genügen müssen. Für bestimmte Anwendungsfälle, z.B. Speicherung struktu-rierter Daten mit häufigen Suchzugriffen, ist diese Eigenschaft vorteilhaft. Oft sind auch, geradein der Speicherung von Massendaten und großen Netz-Communities, dynamische schemaloseSpeicherstrukturen gefragt, für die JSON besser geeignet ist.7

4.3 Binäre AustauschformateTextbasierte Austauschformate wie XML oder JSON haben neben ihren Vorteilen der Lesbar-keit und einfachen Erstellbarkeit einen großen Nachteil: Sie verbrauchen oft mehr Speicherplatzals ihr eigentlicher Informationsgehalt benötigt. Beispielsweise erfordert der 20-stellige String

"18446744073709551615"

in UTF-8 kodiert 20 Bytes. Als vorzeichenloser Integer allerdings erfordert diese Zahl nur 8Bytes, denn

18446744073709551615 = 0xffffffffffffffff = 264−1 (4.3)

hat in Hexadezimaldarstellung 16 Stellen à 4 bit. Zudem kann ein längerer Text durch Daten-kompressionen wie ZIP oder RAR beträchtlich speicherreduziert werden.

Gerade für die Übertragung sehr großer Datenmengen oder für einen effizienten Datenaus-tausch zwischen cyberphysikalischen Systemen, d.h. „intelligenten“ Gegenständen mit geringerRechenleistung wie Uhren, Wearables, Sensoren, selbstfahrende Autos, lernende Thermostate,

5 https://github.com/google/gson [2015-10-05]6 http://www.heise.de/ix/artikel/2006/01/070/02.shtml [2008-09-15]7 http://www.codeproject.com/Articles/604720/JSON-vs-XML-Some-hard-numbers-about-verbosity

Page 48: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

48 Andreas de Vries

Kühlschränke, usw. sind daher binäre Austauschformate als Alternative sinnvoll. So war ins-besondere das Ziel der schnellen Übertragung sehr großer Datenmengen – „Big Data“ – derHauptgrund für die Entwicklung und den Einsatz solcher Formate bei Google und Facebook(Protocol Buffers und Apache Thrift). Dagegen wird ganz aktuell die Vernetzung cyberphysi-kalischer Systeme das sogenannte „Internet der Dinge“ (Internet of Things, IoT) bilden, das wie-derum allgemein als die technische Grundlage für die künftige Logistik, Produktion, Gebäude-und Verkehrsinfrastruktur angesehen wird.

4.3.1 BSONBinary JSON (BSON http://bsonspec.org) wurde für die Speicherung JSON-ähnlicher Daten-strukturen (Maps) entwickelt. Inhalte einer BSON-Datei können nachträglich geändert werden,ohne sie komplett neu schreiben zu müssen. Das unterscheidet BSON von anderen binärenAustauschformaten. BSON wird in der NoSQL-Datenbank MongoDB zur Datenspeicherungverwendet.

Die Inhalte dieses Abschnitts stammen zu einem großen Teil aus [18].

4.3.2 CBORConcise Binary Object representation (CBOR) ist ein auf Datenkompaktheit hin optimiertesAustauschformat und eignet sich daher gut für Anwendungen im Internet der Dinge. Es ist2013 im RFC 7049 (http://tools.ietf.org/html/rfc7049) und zielt darauf ab, in langlebigenAnwendungen auf veränderte Anforderungen reagieren zu können. Als Ausgangspunkt dientedas JSON-Datenmodell, es werden jedoch weitere Datentypen unterstützt. Weitere Informatio-nen sind unter http://cbor.io/ verfügbar.

4.4 Textbasierte versus binäre AustauschformateTextbasierte Austauschformate wie XML oder JSON wurden unter anderem wegen ihrer Les-barkeit entwickelt und verbreitet. Dennoch gibt es mehrere Gründe anzunehmen, dass künftigvermehrt binäre Austauschformate verwendet werden.

1. Spezialisierte Datentypen: Grundsätzlich gibt es in textbasierten Datenformaten wie inXML nur einen einzigen Datentyp, den String. In JSON gibt es zusätzlich Zahlen, geerbtvon JavaScript. (Wobei JavaScript mit ganzen Zahlen vom Betrag ≤ 253−1 genau rech-nen kann, also mit 53 Bits < 7 Bytes.8) Da das Parsen der Stringdarstellung einer Zahloder eines Datums stets Rechenaufwand erfordert und zudem die Konvertierung einesDezimalbruchstrings in eine Gleitkommazahl sprachabhängig (Komma oder Punkt) istund so zu Problemen beim Datenaustausch zwischen Systemen unterschiedlicher Spra-chen führen kann, ist der Datenaustausch mit wohldefinierten Datentypen effizienter undschneller und bietet eine verlässlichere Übertragung bei verteilten Systemen. Neben demeffizienteren Speicherbedarf von Zahlen wie in oben in (4.3) beschreiebn kann die Effi-zienz der Übertragung von Daten durch noch differenziertere Datentypen (16 Bit, 32 Bit,64 Bit) zusätzlich erhöht werden. Insbesondere bei begrenzter Rechenkapazität, wie beiRechenchips im Internet der Dinge, ergeben sich daher durch Formate mit differenziertenDatentypen große Vorteile gegenüber textbasierten Formaten.

8 Nach [ECMA, §20.1.2.6 & 8] ist die größte in JavaScript darstellbare ganze Zahl Number.MAX_SAFE_INTEGER= 0x1fffffffffffff = 253−1.

Page 49: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 49

2. Kommunikation Maschine-zu-Maschine: Ein Argument pro Binärformate ergibt sich ge-rade aus dem zentralen Entwurfskriterium textbasierter Formate: Die Lesbarkeit einerTextdatei nimmt mit zunehmender Komplexität ab, beispielsweise werden üblicherwei-sen XML-Editoren für größere XML-Dateien eingesetzt, die die Daten übersichtlich dar-stellen und die Korrektheit der Syntax prüfen. Dateien werden eben nicht von Menschenmanuell erzeugt und von Menschen gelesen, sondern sind Medium einer Maschine-Ma-schine-Kommunikation. Maschinen können jedoch effizienter mit Binärdateien umgehen,Textparser und Konvertierungsroutinen sind recht rechenintensiv. Der Nachteil der feh-lenden Lesbarkeit kann einfach durch geeignete Editoren gelöst werden, die die Daten ingeeigneter Form darstellen.

3. Trends aktueller Netzwerkprotokolle: Neue Netzwerkprotokolle wie HTTP/2 und CoAPunterstützen binäre Austauschformate. Damit soll insbesondere eine Entwicklung hinzum Internet der Dinge und zu Web-APIs mit effizienterem Zugriff auf Datenbankengefördert werden.

Page 50: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Teil II

Serverseitige Programmierung am Beispielvon PHP

50

Page 51: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

5PHP Grundlagen

Kapitelübersicht5.1 Prinzip von PHP-Programmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

5.1.1 Dateiendung .php, PHP-Tag <?php ... ?> und Skriptausführung auf dem Server 525.2 Ausgaben in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

5.2.1 Ausgabe mit echo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535.3 Variablen in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

5.3.1 Konkatenation von Strings mit dem Punktoperator . . . . . . . . . . . . . . . 555.3.2 Regeln und Konventionen für Variablennamen . . . . . . . . . . . . . . . . . 55

5.4 Kommentare in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565.5 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575.6 Variablen, Datentypen und Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . 57

5.6.1 Undefinierte Variablen und isset . . . . . . . . . . . . . . . . . . . . . . . . 585.6.2 Konstanten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585.6.3 Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

PHP wurde Anfang 1995 von Rasmus Lerdorf als eine Programmiersprache speziell für denEinsatz auf Webservern zur dynamischen Generierung von Webseiten entwickelt. PHP ist da-mit nur wenig jünger als Java. Die Syntax von PHP ähnelt derjenigen von Java oder C sehr,angereichert mit einigen Elementen aus Perl (z.B. „$“, „#“ und „.“).

PHP ist eine sogenannte Skriptsprache, also eine Interpretersprache, die erst zur Laufzeitim Arbeitsspeicher aus dem Quelltext übersetzt und ausgeführt wird.1 Die Abkürzung PHPsteht als rekursives Akronym2 für PHP Hypertext Preprocessor (nach dem Vorbild von GNU= GNU’s not Unix). Ursprünglich stand die Abkürzung von dem „Erfinder“ von PHP, RasmusLerdorf, allerdings einfach für „Personal Home Page / Forms Interpreter“, weshalb die erstePHP-Version 1995 denn auch als „PHP/FI“ in die Annalen einging.

PHP ist quelloffene (open source) Software, d.h. alle zu Grunde liegenden Quelltexte sindoffen zugänglich und unter Aufsicht eines Kontrollgremiums auch veränderbar. Insbesondereist PHP damit kostenlos erhältlich, es gibt keine Lizenzgebühren.

1 Der Interpreter verwendet für PHP ab Version 4 aus Performance-Gründen intern die ZEND-Engine, die denQuelltext nach dem Vorbild von Java als Bytecode compiliert [1, §1.3].

2 Ein Akronym ist ein Kunstwort, das sich aus Anfangsbuchstaben verschiedener Worte zusammensetzt, z.B.USA, NATO oder Azubi

51

Page 52: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

52 Andreas de Vries

Installation und Ausführung von PHP-SkriptenPHP läuft nicht wie andere Programmiersprachen eigenständig („stand alone“), sondern alsModul, also Unterprogramm, eines Webservers, vorzugsweise Apache. Ein PHP-Skript kannnur ausgeführt werden, indem es von einem Browser aus über die Webadresse (beim eigenenRechner: http://localhost) aufgerufen wird. Entsprechend muss zwingend ein Webserver zu-sammen mit dem PHP-Modul installiert sein. Um zusätzlich auf eine Datenbank zuzugreifen,muss entsprechend auch ein Datenbankserver vorhanden sein. Bisschen viel auf einmal?

Unter Linux ist die Installation von PHP problemlos, bei den meisten Distributionen ist PHP,Apache und MySQL standardmäßig vorinstalliert. Für Windows gibt es das Installationspro-gramm XAMPP, das Apache, PHP, MySQL und PHPMyAdmin direkt installiert.Zu beachtenist, dass Ihre PHP-Dateien und HTML-Dokumente sich unter dem Verzeichnis htdocs im Ver-zeichnis xampp befinden, am besten in einem eigenen Verzeichnis programme oder ähnlich. Nurso können Sie sie nach dem Start von XAMPP mit Ihrem Browser durch Eingabe der Webad-resse http://localhost/programme/ oder, falls das nicht klappt, http://127.0.0.1/programme/sehen und aufrufen.

Funktionsreferenz zu PHPDie zu Beginn des Index aufgeführte Liste aller in diesem Skript verwendeten PHP-Funktionenmit Referenzen auf die Seiten, auf denen sie eingeführt oder erklärt werden, ist bei weitem nichtvollständig. Sie sollten sich daher möglichst früh angewöhnen, die vollständige Funktionsrefe-renz der Dokumentation von php.net zu verwenden, die Sie unter der Webadresse

http://www.php.net

finden. Selbständiges Arbeiten mit dieser Referenz wird dringend empfohlen.

5.1 Prinzip von PHP-Programmen

5.1.1 Dateiendung .php, PHP-Tag <?php ... ?> und Skriptausführung aufdem Server

Der Quelltext eines PHP-Skripts kann nur über eine HTTP-Anfrage an einen Webserver auf-gerufen werden, der ihn dann über die PHP-Engine, also einen PHP-Interpreter als Unterpro-gramm, ausführt. Ein PHP-Skript muss daher immer im Dokumentenverzeichnis des Webser-vers gespeichert sein (z.B. htdocs bei Apache) und die Extension .php haben: Auf keinen Fallaber .html! Die Datei kann nur von einem Browser aus über HTTP aufgerufen werden, also aufdem eigenen Rechner

http://localhost/. . . oder http://127.0.0.1/. . .

vgl. die Hinweise zur Installation (Seite 52). Warum ist das so? Da ein PHP-Skript ein vomServer ausgeführtes Programm ist, muss der Webserver es als solches erkennen. Mit der Ex-tension .php verschickt er die Datei zunächst nicht über das Internet an den Client zurück,sondern ruft mit ihr den PHP-Interpreter auf, der als Unterprogramm des Webservers läuft undden Programmcode zwischen den Tags <?php und ?> übersetzt und Anweisung nach Anwei-sung ausführt. Dieser Interpreter wird oft als PHP-Engine oder PHP-Modul des Webserversbezeichnet. Das Ergebnis des Programmlaufes, also das, was das PHP-Modul zurückgibt, wirdanstelle des PHP-Codes in die analysierte Datei eingefügt. Das so entstandene Ergebnis schicktder Webserver dann an den Browser.

Page 53: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 53

Kurz gesagt ist also das ursprüngliche Request-Response-Spiel von HTML leicht verändert,der Browser fordert eine PHP-Datei an und erhält dynamisch erzeugtes HTML:

Webserver

PHP-Engine

BrowserAnfrage (.php)

Antwort (HTML)

Der PHP-Quelltext in der Datei ist stets mit dem PHP-Tag <?php . . . ?> zu umschließen,

<?php

... PHP-Quelltext ...

?>

Ein solches PHP-Tag nennt man auch „Markierung nach dem XML-Stil“. Die Dateiendung.php und das PHP-Tag sind beide notwendig, um ein PHP-Skript auszuführen.

Leider funktioniert das alles nicht, wenn man den XML-Vorspann verwendet. Die Ursa-che ist offenbar, dass die aktuellen PHP-Interpreter bereits die beiden Zeichen <? als PHP-Tagsinterpretieren. Daher muss man derzeit den XML-Vorspann bei einem PHP-Dokument vermei-den. In den folgenden Beispielskripten werden wir meistens sowieso auf den Vorspann verzich-ten, die PHP-Skripte laufen auch ohne ihn. Oder man verwendet einfach den HTML-Vorspann<!DOCTYPE html>.

5.2 Ausgaben in PHPWir beginnen (wie bei Einführungen in Programmiersprachen üblich) mit einem Programm,welches „Hello World“ ausgibt.

Beispiel 5.1. Das Programm „Hello World“ in PHP �

1 <!-- Das Programm gibt "Hello World" aus. Dateiname: helloWorld.php -->

2 <!DOCTYPE html>

3 <html>

4 <head><title>Hello World</title></head>

5 <body>

6 <?php

7 echo "<h2> Hello World </h2>";

8 ?>

9 </body>

10 </html>

5.2.1 Ausgabe mit echoMachen wir uns das Prinzip der HTML-Antwort an Beispiel 5.1 klar. Hier sehen wir in Zeile 9den einleitenden <?php-Tag. In Zeile 10 folgt die einzige PHP-Anweisung des Programms:

echo "<h2> Hello World </h2>";

echo ist einer der PHP-Befehle für die Ausgabe. Text, der hinter echo steht, wird ausgegeben,Zeichenketten müssen dabei in Anführungszeichen gesetzt werden. Jede Anweisung in PHPwird mit einem Semikolon beendet. In der nächsten Zeile wird durch ?> die Programmausfüh-rung beendet. Die Server-Software ersetzt also

Page 54: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

54 Andreas de Vries

<?php

echo "<h2> Hello World </h2>";

?>

durch <h2> Hello World </h2> und schickt den so entstandenen Ausgabetext an den Client, waszu der Darstellung in Abbildung 5.1 führt.

Abbildung 5.1: Ausgabe von Beispiel 5.1

Bei einem PHP-Skript wird also das Ergebnis des Programmlaufs auf dem Server an denClient übertragen. Der Browser „weiß“ gar nicht, dass er eine dynamisch erzeugte (d.h. „berech-nete“) Seite darstellt. Für den Browser besteht kein Unterschied zu statischen HTML-Seiten,insbesondere bedarf es keiner besonderen Eisntellungen oder Browser-Plugins, um die Ausga-ben von PHP-Programmen im Browser zu sehen.

Bei einer clientseitigen Skriptsprache wie JavaScript hingegen wird das Programm selberan den Client übertragen. Der Browser führt es nach dem Empfang aus und stellt das Ergebnisder Programmausführung dar. Der Browser muss in diesem Fall den entsprechenden Interpreterals Unterprogramm beinhalten.

5.3 Variablen in PHPBetrachten wir als ein weiteres Beispiel ein Programm, das mit Hilfe von Variablen die Kon-stanten 9 und 10 addiert.

Listing 5.1: Ein erstes Additionsprogramm in PHP1 <!-- Das Programm addiert 9 und 10 (oha!). Dateiname: addition1.php -->

2 <h2>Addition zweier Zahlen</h2>

3 <?php

4 $ersterSummand = 9;

5 $zweiterSummand = 10;

6 $summe = $ersterSummand + $zweiterSummand;

7 echo "Die Summe von $ersterSummand und $zweiterSummand

8 ist $summe";

9 ?>

Zunächst ist zu bemerken, dass Variablen in PHP mit dem $-Zeichen beginnen müssen. Varia-blen sind Namen, um Werte zu speichern und im Verlauf des Programms zu verwenden, alsozu lesen oder zu verändern. Als nächstes ist überraschend, dass wir in PHP keine Variablendeklarieren. Anders als in Compilersprachen wie Java gibt es in PHP dazu keine Möglichkeit.Wenn wir einen Variablennamen in die PHP-Quelle schreiben, erzeugt PHP diese Variable so-fort, es sei denn, die Variable gibt es schon. Zum Schluss des Skripts erfolgt die Ausgabe mitder Anweisung

Page 55: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 55

echo "Die Summe von $ersterSummand und $zweiterSummand

ist: $summe";

Im Gegensatz zu den meisten Programmiersprachen können wir hier Variablen und normalenText in den Anführungszeichen mischen. Der Grund ist, dass der PHP-Interpreter anhand des$-Zeichens erkennt, dass kein normaler Text, sondern der Wert einer Variable auszugeben ist.(Das $-Zeichen selbst wird durch "\$" ausgegeben.)

Man kann in Strings zur Deutlichkeit oder zur Abgrenzung auch geschweifte Klammern umdie Variable verwenden, also

echo "Die Summe von {$ersterSummand} und {$zweiterSummand} ..."

Manchmal kann dies notwendig sein, z.B. wenn man ausgeben möchte "Entfernung {$x}km".Interessant ist der Blick auf den HTML-Text, den der Browser letztendlich vom Server

empfängt. Man kann ihn sich anzeigen lassen, indem man die Funktion „Seitenquelltext anzei-gen“ des Browsers aufruft. Abbildung 5.2 zeigt, dass der Programmcode von dem PHP-Modul

Abbildung 5.2: Die Funktion „Seitenquelltext anzeigen“ des Browsers für das PHP-Skript aus Beispiel 5.1

des Servers ausgeführt wird, nur die Ausgaben über echo werden an den Browser übergeben.Der Browser erhält also reines HTML und kann dies direkt darstellen. Alle Anweisungen einesPHP-Skripts werden von dem Webserver ausgeführt.

5.3.1 Konkatenation von Strings mit dem Punktoperator .

Der Operator zur Verknüpfung (Konkatenation oder Stringaddition) von Zeichenketten ist inPHP der Punkt (.). (Zum Vergleich: In Java ist es das +-Zeichen.) Möchten wir zum Beispiel inunserem obigen Programm auf die Variable $summe verzichten und die Summe bei Ausgabe desStrings zu berechnen, so wäre eine mögliche Variante:

echo "Die Summe von $ersterSummand und $zweiterSummand

ist: " . ($ersterSummand + $zweiterSummand);

Wir werden in Zukunft noch oft den verwandten Operator

.=

verwenden, der der Variablen links von ihm den String rechts von ihm anhängt, oder „konkate-niert“:

$text = "Es gilt $ersterSummand + $zweiterSummand = ";

$text .= $ersterSummand + $zweiterSummand; // Konkatenation

echo $text; // Ausgabe an den Browser

Dies ergibt dieselbe Ausgabe wie unsere originale Version in Listing 5.1.

5.3.2 Regeln und Konventionen für VariablennamenAbschließend noch einige Regeln zu Variablennamen.

Page 56: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

56 Andreas de Vries

• Variablennamen beginnen in PHP mit dem $, auf das $-Zeichen muss ein Buchstabe oderder Unterstrich _ folgen.

• Variablennamen können nach dem ersten Buchstaben Ziffern und Buchstaben in beliebi-ger Reihenfolge enthalten.

• Variablennamen dürfen außer dem Unterstrich _ keine Sonderzeichen enthalten, insbe-sondere Umlaute.

• Variablennamen können beliebig lang sein.

• Groß- und Kleinschreibung spielt eine Rolle ($summe 6= $Summe 6= $suMME 6= $SUMME). Va-riablennamen sollten klein geschrieben werden.

• Variablennamen sollten einen Bezug zu den Daten haben, die sie speichern sollen.

5.4 Kommentare in PHPKommentare werden beim Programmablauf ignoriert. Kommentare sind dazu da, unseren Pro-grammcode verständlicher zu machen.

Listing 5.2: Kommentare in PHP1 <!-- Das Programm addiert zwei einzugebende Zahlen. Dateiname: kommentar.php -->

2 <?php

3 /** Autor: Andreas de Vries

4 * Version: 17.02.2016

5 * Zweck: Addition zweier Zahlen

6 */

7 $ersterSummand = 9;

8 $zweiterSummand = 10;

9 // Aufbereiten der Ausgabe:

10 $text = "Es gilt $ersterSummand + $zweiterSummand = ";

11 $text .= $ersterSummand + $zweiterSummand;

12 echo $text; // Ausgabe an den Browser

13 ?>

In PHP gibt es drei Arten von Kommentaren:

• Sämtlicher Text zwischen /* und */ wird ignoriert. In Beispiel 5.2 wird diese Kommen-tarform benutzt, um einige allgemeine Informationen zum Programm in die Datei aufzu-nehmen.

• Auf // folgender Text wird bis zum Zeilenende ignoriert. In Beispiel 5.2 wird diese Kom-mentarform benutzt, um den Sinn der einzelnen Programmzeilen zu dokumentieren.

• Auf # folgender Text wird bis zum Zeilenende ignoriert.

Für dieses kleine Programm sind die Kommentare sicherlich unnötig. Doch schon bei gering-fügig größeren Programmen sind Kommentare notwendig. Sie dienen Ihnen dazu, Ihr eigenesProgramm auch noch nach einigen Wochen zu verstehen. Anderen erleichtern Kommentare,sich in Ihre Gedanken hinein zu versetzen.

Page 57: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 57

5.5 Zusammenfassung• Die Endung einer PHP-Datei muss .php lauten, damit sie von dem Webserver als PHP-

Skript erkannt und der PHP-Interpreter aufgerufen wird.

• PHP-Code muss stets von dem PHP-Tag <?php und ?> umschlossen sein. Der Interpreterübersetzt („parst“) die Anweisungen innerhalb des Tags und führt jede Anweisung sofortaus.

• Nach jeder Anweisung muss ein Semikolon gesetzt sein.

• Einzeilige Kommentare werden mit // begonnen, mehrzeilige mit /* . . . */ umschlossen.

• Die Ausgabe geschieht mit dem Befehl echo.

• Ruft der Browser eine PHP-Datei auf, so wird das Skript ausgeführt und er erhält alsAntwort HTML, (meist) erzeugt mit echo.

Webserver

PHP-Engine

BrowserAnfrage (.php)

Antwort (HTML)

Man erkennt hier das grundlegende Client-Server-Prinzip mit Request-Response.

• Strings werden mit dem Konkatenationsoperator . verknüpft.

• Variablen beginnen stets mit dem Dollarzeichen $. Sie werden nicht deklariert, sondernerhalten ihren Datentyp jedes Mal neu mit einer Wertzuweisung.

5.6 Variablen, Datentypen und OperatorenViele Programmiersprachen bieten die Möglichkeit, durch eine Deklaration einer Variableneinen Datentyp zuzuweisen und damit festzulegen, welche Dinge auf dieser Variablen abgespei-chert werden können. Skriptsprachen wie PHP bieten diese Möglichkeit nicht. Solche Sprachennennt man untypisiert, oder wie PHP schwach typisiert. Grundsätzlich unterstützt PHP die fol-genden Datentypen:

• Strings (string): Zeichenketten, z.B. "Abc", "Er sagte: \"Ich gehe!\" und ging.". InPHP wird ein String durch die doppelten Anführungszeichen " markiert, aber auch durchApostrophs ’. Da aber Apostrophs einerseits das $-Zeichen nicht als Markierung für eineVariable erkennen und andererseits wir es später für SQL-Befehle verwenden, rate ichvon seiner Benutzung ab.

• Ganze Zahlen (int oder integer) z. B. -1, 1000, 3, 7, 12, -1000

• Reelle oder Fließkommazahlen (double oder real): z.B. -1.2, -100.001, 2.0e-12. Merke:. (Punkt) statt , (Komma) in PHP als Dezimaltrenner.

• Wahrheitswerte (bool): true oder false, bzw. 1 oder 0.

Page 58: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

58 Andreas de Vries

Strings sind gewissermaßen der „Hauptdatentyp“ in PHP, alle Variablen sind prinzipiell Strings,es sei denn sie werden mit numerischen oder logischen Operatoren (s.u.) verknüpft.

In PHP ist es dementsprechend nicht möglich, Variablen zu deklarieren. Man schreibt ein-fach den Namen einer Variablen in ein Programm und PHP erzeugt die Variable. Der Datentypwird abhängig von den Operatoren automatisch zugeordnet.

Will man prüfen, ob der aktuelle Wert einer Variablen $x numerisch ist, so kann man dasmit der Funktion

is_numeric($x)

tun, sie gibt true zurück, wenn $x eine Zahl ist. Beispielsweise ergeben is_numeric(3), is_nu-meric (3.14), is_numeric(.14) oder is_numeric(-3) stets true, is_numeric("3") oder is_nu-meric("A") dagegen false.

Entsprechend gibt es die folgenden Funktionen, mit denen man den Datentyp des aktuellenWerts einer Variablen prüfen kann:

is_bool($x),is_int($x), is_integer($x), is_long($x),is_double($x), is_float($x), is_real($x),

Der Vollständigkeit halber sei erwähnt, dass eine Variable in PHP ansonsten nur noch ein Arrayoder ein Objekt sein kann.

5.6.1 Undefinierte Variablen und isset

Hat eine Variable in einem PHP-Skript noch keinen Wert erhalten, ist also noch undefiniert, sohat sie den Wert null. Will man zu einem bestimmten Zeitpunkt in einem PHP-Skript prüfen, obeine gegebene Variable $x noch undefiniert ist, so kann man dies mit der Anweisung isset($x);

tun.Beschreibt eine Variable $a ein Array, so zeigt isset($a) zwar an, ob das Array selbst

initialisiert wurde, nicht aber, ob es Werte enthält. Diese Information liefert die Funktion empty,d.h. empty($a) ergibt true genau dann, wenn das Array $a leer ist.

5.6.2 KonstantenProgramme benötigen häufig konstante Werte (im folgenden Konstanten genannt), um Berech-nungen durchführen zu können. Eine Konstante kann explizit durch „Hinschreiben“ an jedergewünschten Stelle des Programms „definiert“ werden, also z.B. $brutto = 1.19*$netto. Diesist nicht immer sinnvoll: die Zahl 1.19 hat geringere Aussagekraft als das Wort Mehrwertsteu-ersatz. Nehmen wir an, in Programm benötigt öfter den Mehrwertsteuersatz. Eine (syntaktischrichtige) Lösung wäre, auch in diesem Fall den Mehrwertsteuersatz an jeder Stelle des Pro-gramms, wo er benötigt wird, hinzuschreiben. Ändert der Gesetzgeber den Mehrwertsteuersatz,muss jede Stelle des Programms, wo der Mehrwertsteuersatz vorkommt, geändert werden.

Nahezu alle Programmiersprachen (außer z.B. JavaScript) erlauben es, Konstanten mit Na-men zu definieren und diesen einmalig einen Wert zuzuweisen. In PHP werden Konstanten mitder Syntax

1 define("KONSTANTENNAME", "wert");

gebildet. Konstanten unterscheiden sich von Variablen dadurch, dass sich ihr Wert während desProgrammlaufs nicht ändern kann (Konstanten sind halt konstant). Konstanten dürfen daher nie

Page 59: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 59

auf der linken Seite einer Zuweisung stehen. Beachten Sie: Konstanten in PHP beginnen nichtmit dem $-Zeichen!!

Konstanten werden häufig, obwohl dies nicht vorgeschrieben ist, mit Großbuchstaben be-nannt, um sie „in das Auge springend“ von Variablen zu unterscheiden. Dies hat sich als eineallgemeine Konvention (auch in anderen Programmiersprachen) etabliert.

5.6.3 OperatorenEiner der wichtigsten Operatoren ist der Zuweisungsoperator =, der in der Variablen links vonihm den auf seiner rechten Seite festgelgten oder berechneten Wert speichert:

$x = 1.19 * 1000;

Arithmetische Operatoren

PHP kennt und unterstützt die gängigen arithmetischen Operatoren. Wie auch in der Schulma-thematik besitzen diese Operatoren verschiedenen Vorrang (Punkt- geht vor Strichrechnung).Wie auch in der Mathematik kann man den Vorrang der Operatoren durch Klammerung ändern.

In Tabelle 5.1 sind die arithmetischen Operatoren und ihr Vorrang (Reihenfolge) aufgelistet.Beispiel 5.2 zeigt ein PHP-Skript, Abb. 5.3 seinen Output.

Operator Operation Vorrang() Klammern werden zuerst ausgewertet. Sind Klammern von Klammern

umschlossen, werden sie von innen nach außen ausgewertet.

*, /, %Multiplikation,Division,Modulus

werden als zweites ausgewertet

+, -Addition,Subtraktion werden zuletzt ausgewertet

Tabelle 5.1: Der Vorrang der arithmetischen Operatoren in PHP. Mehrere Operatoren gleichen Vorrangs werdenstets von links nach rechts ausgewertet.

Beispiel 5.2. Arithmetische Operatoren �

1 <!-- Dateiname: arithmetischeOperatoren.php -->

2 <?php

3 $i = 2;

4 $j = 3;

5 $r = 2;

6 $s = 3;

7 $l = $i + $j; // 5;

8 echo "l1: $l <br/>";

9 $l = $i - $j; // -1

10 echo "l2: $l <br/>";

11 $l = $j % $i; // 1 ( modulo-Rechnung )

12 echo "l3: $l <br/>";

13 $l = $i * $j; // 6

14 echo "l4: $l <br/>";

15 $t = $s / $r; // 1.5 ( Division )

16 echo "t : $t <br>";

Page 60: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

60 Andreas de Vries

17 $l = $r + $i * $j; // 8

18 echo "l5: $l <br/>";

19 $l = ($r + $i) * $j; // 12

20 echo "l6: $l <br/>";

21 ?>

Abbildung 5.3: Arithmetische Operatoren

Wie alle C-ähnlichen Sprachen erlaubt PHP in einigen Fällen abkürzende Schreibweisen.

i += j // i = i + j

i -= j // i = i -j

i *= j // i = i * j

i /= j // i = i / j

i %= j // i = i % j

a .= b // a = a . b

i++ // i = i+1

i-- // i = i-1

PHP benutzt den Punkt (.), um zwei Strings miteinander zu verbinden, siehe Beispiel 5.3.

Beispiel 5.3. Der Plus-Operator und der Punkt-Operator bei PHP �

1 <!-- Dateiname: plusOperator.php -->

2 <?php

3 $s1 = "ab";

4 $s2 = "cd";

5 $i = 5;

6 $j = "6";

7 $text = $s1 + $s2 . "<br/>"; // ergibt "0"

8 $text .= $s1 . $s2 . "<br/>"; // ergibt äbcd"

9 $text .= $s1 + $i . "<br/>"; // ergibt "5"

10 $text .= $s1 . $i . "<br/>"; // ergibt äb5"

11 $text .= $j . $i . "<br/>"; // ergibt "65"

12 $text .= $j + $i . "<br/>"; // ergibt "11"

13 echo $text;

14 ?>

Wir sehen, dass auch PHP eigentlich unschöne Dinge tut. Strings, die sich nicht in Zahlenumwandeln lassen, werden bei der Addition auf 0 gesetzt. Es gibt keine Fehlermeldung, dassdiese Operation mit den beteiligten Operanden wenig Sinn macht.

Page 61: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 61

Vergleichsoperatoren

Tabelle 5.2 zeigt die in PHP verfügbaren Vergleichsoperatoren.

Sym- Operator Bei- Bedeutungbol in PHP spiel= == x == y x hat den gleichen Wert wie y6= !=, <> x != y x hat nicht den gleichen Wert wie y= === x === y x und y haben gleichen Datentyp und Wert6= !== x !== y Datentyp oder Wert von x und y sind ungleich> > x > y x ist größer als y< < x < y x ist kleiner als y= >= x >= y x ist größer gleich y5 <= x <= y x ist kleiner gleich y

Tabelle 5.2: Vergleichsoperatoren in PHP. Beispielsweise ist "5" === 5 in PHP false, aber "5"== 5 ist true.

Vergleichsoperatoren werden in Verbindung mit bedingten Anweisungen und Schleifen ge-nutzt. Beide Programmierkonstrukte wurden bisher noch nicht behandelt. Darum wirken diejetzt vorgestellten Beispiele etwas konstruiert. Um die Ergebnisse der Vergleiche zu visualisie-ren, benutze ich implizit Variablen vom Typ Boolean. Solche Variablen können nur zwei Werteannehmen: true oder false.

Besondere Vorsicht ist bei dem Operator == geboten. Er darf keinesfalls mit dem Zuwei-sungsoperator = verwechselt werden. (In einigen Programmiersprachen, z.B. Pascal oder SQL,wird der Vergleichsoperator durch das einfache Gleichheitszeichen dargestellt!) Beispiel 5.4zeigt die Wahrheitswerte einiger Vergleiche und die Boole’sche Werte true und false. Betrach-ten wir das folgende Beispiel.

Beispiel 5.4. Vergleichsoperatoren in PHP �

1 <Dateiname: vergleichsOeratoren.php -->

2 <?php

3 $s1 = "ac";

4 $s2 = "ad";

5 $i = 5;

6 $j = "5";

7

8 echo "$s1 != $s2: " . ($s1 != $i ) . "<br/>";

9 echo "$s1 < $s2: " . ($s1 < $s2 ) . "<br/>";

10 echo "$s1 == $s2: " . ($s1 == $s2) . "<br/>";

11 echo "$s1 = $s2: " . ($s1 = $s2) . "<br/>";

12 echo "$i === $j: " . ($i === $j ) . "<br/>";

13 echo "$j !== $i: " . ($j !== $i) . "<br/>";

14 echo "$i == $j: " . ($i == $j ) . "<br/>";

15 echo "$j != $i: " . ($j != $i ) . "<br/>";

16 echo "$j <> $i: " . ($j <> $i ) . "<br/>";

17 echo "$j = $i: " . ($j = $i ) . "<br/>";

18 echo "$i === $j: " . ($i === $j ) . "<br/>";

19 echo "(5 == 3) === false: " . ((5 == 3) === false) . "<br/>";

20 ?>

Page 62: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

62 Andreas de Vries

Die Ausgabe dieses Skripts ist

ac != ad: 1ac < ad: 1ac == ad:ac = ad: ad5 === 5:5 !== 5: 15 == 5: 15 != 5:5 <> 5:5 = 5: 55 === 5: 1(5 == 3) === false:1

Ein Vergleich wie ($s1 < $s2) ergibt true oder false, je nach zugrunde liegendem Ordnungs-begriff. Die Konstanten true und false (übrigens auch in Groß- und Kleinbuchstaben geschrie-ben, auch wild gemischt!) werden von echo nur als "" (false) oder 1 (true) dargestellt.

Der Operator == wird Gleichheitsoperator genannt, der Operator === Identitätsoperator. Dieerste Bezeichnung ist etwas missverständlich, denn in typisierten Programmiersprachen wie Cund Java versteht man unter dem Gleichheitsoperator das, was in PHP === ist, das „PHP-==“ gibtes in diesen Sprachen gar nicht. Um in PHP den Unterschied zwischen ihnen zu illustrieren, seiauf die Webseite

http://haegar.fh-swf.de/Webtechnologie/equalities.php

verwiesen. Hier erkennt man, dass === die erwartete Gleichheit zeigt (nur die Diagonale istbesetzt, bis auf die in PHP so definierten Identitäten false und true unabhängig von ihrerSchreibung). Auch die „falsy“ Werte, also Werte == false, sind einigermaßen übersichtlich(0, "0", NULL, das leere Array). Aber alles, was nicht false oder falsy ist, ist in PHP „truthy“,also == true, und das ist eine ganze Menge! Übrigens: NAN ungleich NAN ist kein Fehler inPHP, sondern ganz bewusst vom Standard IEEE-754 vorgesehen (http://stackoverflow.com/questions/1565164).

Ansonsten sehen wir, dass sich Vergleichsoperatoren so verhalten, wie wir das erwarten.Eine Ausnahme besteht, wenn wir den Zuweisungsoperator verwenden: Das Ergebnis einerZuweisung ist der Wert der zugewiesenen Variable. Dies wird insbesondere von besondererBedeutung sein, wenn wir uns im nächsten Kapitel mit Kontrollstrukturen (der if-Anweisung)beschäftigen.

Logische Operatoren

Logische Operatoren werden benutzt, um Vergleiche zu verketten oder zu negieren und umlogische Aussagen zu bilden.

• Logisches AND (&& oder AND): Der &&-Operator führt die logische und-Verknüpfung durch.Er ergibt true, wenn seine beiden Operanden true ergeben, ansonsten false.

• Logisches OR (|| oder OR): Der ||-Operator führt die logische oder-Verknüpfung durch.Er ergibt true, wenn einer seiner beiden Operanden true ist, ansonsten false.

Page 63: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 63

• XOR = exklusives ODER (ˆ): Der XOR-Operator ˆ, auch XOR, führt die logische Ver-knüpfung des Exklusiven ODER durch. Hierbei ist A ˆ B bzw. A XOR B wahr, wenn A undB unterschiedliche Wahrheitswerte haben, und falsch, wenn sie gleiche Wahrheitswertehaben.

• Logische Negation (!) Der Negations-Operator ! wird auf nur einen Operanden angewen-det. Er ergibt true, wenn sein Operand false ist und umgekehrt. Beispiel 5.5 zeigt einigedurch logische Operatoren verkettete Vergleiche und deren Ergebnisse.

Die Wahrheitstabellen in Tab. 5.3 zeigen die möglichen Ergebnisse der logischen Operatoren,wobei 0 = false und 1 = true (Tab. 5.3).

a b a && b a || b a ˆ b !a0 0 0 0 0 10 1 0 1 1 11 0 0 1 1 01 1 1 1 0 0

Tabelle 5.3: Wahrheitstabellen für verschiedene logische Operatoren.

Beispiel 5.5. Logische Operatoren in PHP �

1 <!-- Dateiname: logischeOperatoren.php -->

2 <?php

3 $i=5;

4 $j=6;

5 $k=6;

6 $l=5;

7 $ergebnis = ($i == $j) && ($j == $k); // false, da i nicht j

8 $text = "ergebnis1: $ergebnis <br/>";

9 $ergebnis = ($i == $j) || ($j == $k); // true, da j gleich k

10 $text .= "ergebnis2: $ergebnis <br/>";

11 $ergebnis = ($i == $l) && ($j == $k); // true

12 $text .= "ergebnis3: " . $ergebnis . "<br/>";

13 $ergebnis = ($i == $l) || ($j == $k); // true

14 $text .= "ergebnis4: $ergebnis <br/>";

15 $ergebnis = !($i == $j); // true

16 $text .= "ergebnis5: $ergebnis <br/>";

17 $ergebnis = !($i != $j); // false

18 $text .= "ergebnis6: $ergebnis <br/>";

19 $ergebnis = ($i != $j) ^ ($k == $l); // true

20 $text .= "ergebnis7: $ergebnis <br/>";

21 echo $text;

22 ?>

Die Ausgabe dieses Skripts ist

Page 64: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

64 Andreas de Vries

ergebnis1: 0ergebnis2: 1ergebnis3: 1ergebnis4: 1ergebnis5: 1ergebnis6:ergebnis7: 1

Die Zeile

$ergebnis = ($i == $j) && ($j == $k)

ähnelt den Ausdrücken des vorherigen Kapitels stark. Der einzige Unterschied besteht darin,dass wir auf der rechten Seite des Ausdrucks zwei Vergleiche sehen. Beide Vergleiche sinddurch einen logischen Operator (in diesem Beispiel &&) verbunden. Der Interpreter wertet zu-nächst beide logischen Ausdrücke aus und danach die Vernüpfung. Das Ergebnis wird der Va-riable $ergebnis zugewiesen.

Page 65: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

6Kontrollstrukturen in PHP

Kapitelübersicht6.1 Die if-Anweisung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

6.1.1 Alternativen: Verschachtelte if-Anweisungen . . . . . . . . . . . . . . . . . . 666.1.2 Der Bedingungsoperator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

6.2 Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676.2.1 while-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676.2.2 do/while-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 696.2.3 for-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 696.2.4 foreach-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

6.3 Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 696.3.1 Lokale Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

6.4 Auslagern und Einbinden von PHP-Code . . . . . . . . . . . . . . . . . . . . . . . . 716.4.1 require und include . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

6.5 Zeit- und Datumsfunktionen in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . 736.5.1 Erzeugen eines Zeitstempels . . . . . . . . . . . . . . . . . . . . . . . . . . . 736.5.2 Formatierte Zeitangaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

6.1 Die if-AnweisungLösung solcher Probleme ist die if-Anweisung. Sie hat die Form:

if ( bedingung ) {

anweisung;

...

} else {

anweisung;

...

}

bedingung ist ein logischer oder Boole’scher Ausdruck, der einen Wahrheitswert (true oderfalse) annimmt. Vergleiche z.B. sind solche Boole’schen Ausdrücke (vgl. Kapitel 5.6.3).

Ergibt der logische Ausdruck den Wert true, werden die Anweisungen im if-Teil (oder if-Block) ausgeführt, andernfalls (der logische Ausdruck ergibt false) werden die Anweisungenim else-Teil (oder else-Block) ausgeführt.

65

Page 66: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

66 Andreas de Vries

Regeln:

• Vor else darf kein ; stehen.

• if-Anweisungen können beliebig tief geschachtelt werden.

• Der else-Block ist optional. Gibt es den else-Block nicht, ist dies gleichbedeutend mit:Ansonsten tue nichts. Ist ein else-Teil vorhanden, sprechen wir von zweiseitiger Aus-wahl, ansonsten von einseitiger Auswahl.

Prinzipiell können zwar die geschweiften Klammern im if-Block oder im else-Block wegge-lassen werden, wenn der block nur aus einer Anweisung besteht; allerdings ist davon dringendabzuraten, denn insbesondere durch das „dangling-else“-Problem ist dies sehr unübersichtlichund fehleranfällig. Das Problem des dangling else ist die scheinbare Mehrdeutigkeit einer ver-schachtelten if-Anweisung:

$a = 0; $b = 1;

if ($a == 1)

if ($b == 1)

$a = 42;

else

$b = 42;

Ist $b = 1 oder $b = 42?1

6.1.1 Alternativen: Verschachtelte if-AnweisungenZur Verarbeitung von mehrfachen Alternativen (z.B. Monat ist entweder 1 oder 2 oder . . . ) wirdeine Konstruktion verschachteler if-Anweisungen benötigt.

Beispiel 6.1. Anzahl Tage im Monat (if/else) �

1 $monat = 2;

2 $jahr = 2017;

3 if( ($jahr % 4 === 0) && ($jahr % 200 === 0) ) {

4 $schaltjahr = true;

5 } else {

6 $schaltjahr = false;

7 }

8 if ($monat===4 || $monat===6 || $monat===9 || $monat===11) {

9 $tage = 30;

10 } else if ($monat === 2) {

11 if ($schaltjahr) {

12 $tage = 29;

13 } else {

14 $tage = 28;

15 }

16 } else {

17 $tage = 31;

18 }

1 Derelse-Zweiggehörtzuminnerenif,nichtzumäußeren,wieesdieEinrückungsuggeriert;daherist$b=1.

Page 67: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 67

In PHP kann man in diesem Fall sogar elseif statt else if schreiben. Oft wird für Alter-nativen die switch-Anweisung verwendet. Sie ist jedoch logisch ein Spezialfall der if/else-if-Konstruktion und wird daher hier nicht vorgestellt. Für ihre Syntax sei auf die Literatur (z.B.[7]) verwiesen.

6.1.2 Der BedingungsoperatorDer Bedingungsoperator (conditional operator) ist eine sehr kompakte Variante der if-else-An-weisung. Er hat die Form

A ? B : C

mit den drei Operanden A, B, C. Der erste kommt vor das Fragezeichen, der zweite zwischenFragezeichen und Doppelpunkt, der dritte hinter den Doppelpunkt. Der erste Operand A ist eineBedingung, B und C sind jeweils Werte (oder Anweisungen). Ergibt A true, so wird der Wert B(der zweite Operand) angenommen, ansonsten C (der dritte Operand), vgl. Beispiel 6.2.

Beispiel 6.2. Der Bedingungsoperator �

1 <!-- Der Fragezeichenoperator. Dateiname: fragezeichen.php //->

2 <?php

3 $i = 1;

4 $j = 2;

5 $min = ($i < $j) ? $i : $j;

6 echo " min = $min"; // Ausgabe: "min = 1"

7 ?>

Die Wirkung ist also äquivalent zu

if ( $i < $j ) {

$min = $i;

} else {

$min = $j;

}

Ein Operator mit drei Operanden heißt ternärer Operator.

6.2 SchleifenSchleifen oder Loops gehören neben den if-Anweisungen zu den üblichen Kontrollstrukturen.Durch Schleifen kann ein Programmblock mehrfach durchlaufen werden. Die Anzahl der Wie-derholungen kann fest oder variabel definiert werden und hängt von den Bedingungen und derSchleifenstruktur ab.

In PHP gibt es vier Schleifenstrukturen, die abweisende while-Schleife, die nichtabwei-sende do/while-Schleife, die zählergesteuerte for-Schleife, und als letzte die Array-bezogeneforeach-Schleife, die wir in Kapitel 7 kennen lernen.

6.2.1 while-SchleifeDie while-Schleife prüft zunächst eine Bedingung, die Schleifenbedingung. Solange diese er-füllt ist, wird der Anweisungsblock durchlaufen, anschließend wird die Bedingung erneut ge-prüft.

Page 68: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

68 Andreas de Vries

while ( Bedingung ) {

anweisungen;

}

Als Beispiel berechnen wir näherungsweise die Quadratwurzel einer Zahl z mit Hilfe des New-ton’schen Iterationsverfahrens.2 Bei jedem Schleifendurchlauf wird anfangs geprüft, ob dasQuadrat der Wurzel w bereits hinreichend nah bei der Zahl liegt, hier z.B. ob |w2− z|< εz mitε = 1e-12 = 10−12. Ist das Ergebnis nicht genau genug, wird mit der Formel

w ← 12

(w+

zw

)bzw. wk+1 =

12

(wk +

zwk

)(k = 0) die nächste Iteration berechnet. Übrigens: Dieses Verfahren konvergiert extrem schnellfür einen beliebigen Anfangswert und wird zur Berechnung der Quadratwurzel in Programmier-sprachen verwendet.

1 <!-- Das Programm berechnet die Wurzel einer Zahl. Dateiname: wurzel.php -->

2 <h2>Wurzelberechnung nach dem Newton-Verfahren</h2>

3 <?php

4 $zahl = 10;

5 $wurzel = $zahl/2;

6 $epsilon = 1e-12 * $zahl;

7

8 while ( abs($wurzel*$wurzel - $zahl) > $epsilon ) {

9 $wurzel = ($wurzel + $zahl/$wurzel)/2;

10 echo " $wurzel<br/>"; // zum Debuggen

11 }

12 echo " Wurzel von $zahl = $wurzel";

13 ?>

Hierbei liefert die Standardfunktion abs($x) den Absolutbetrag |x| von x. PHP hat weitgehenddieselben mathematischen Standardfunktionen wie z.B. die Klasse Math in Java. Die Ausgabedes Programms zeigt eine immer bessere Näherung an die Quadratwurzel der angegebenenZahl, hier z.B. 10:

3.53.17857142857143.16231942215093.16227766044413.1622776601684

Problematisch bei der while-Schleife ist, dass die Schleifenbedingung unter Umständen immerwahr bleiben kann, damit läge eine Endlosschleife vor. Das ist insbesondere äußerst kritisch,da in diesem Falle der Webserver behindert wäre, der das PHP-Skript ja ausführt. Um diesenEffekt zu verhindern, ist die Laufzeit eines PHP-Skripts auf maximal 30 Sekunden beschränkt.Daher sollten laufzeitintensive Algorithmen nicht in PHP implementiert werden.

2Das angegebene Verfahren zur näherungsweisen Berechnung der Quadratwurzel wird dem griechischen Ma-thematiker Heron von Alexandria (wohl um 100 n. Chr.) zugeschrieben und daher manchmal als Heron’schesVerfahren bezeichnet. Mathematisch ist es jedoch ein Spezialfall des Newton’schen Verfahrens xk+1 = xk −f (xk)/ f ′(xk), und zwar mit f (x) = z− x2.

Page 69: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 69

6.2.2 do/while-SchleifeDie do/while-Schleife führt zunächst seinen Anweisungsblock aus und prüft seine Schleifen-bedingung erst zum Schluss. Solange diese erfüllt ist, wird der Anweisungsblock erneut durch-laufen. Syntax:

do {

anweisungen;

} while ( bedingung );

Wie bei der while-Schleife kann es auch hier zu einer Endlosschleife kommen.

6.2.3 for-SchleifeDie for-Schleife fasst Initialisierungsanweisung (start), Schleifenbedingung (test) und Iterati-onsanweisung (update) in dem Schleifenkopf zusammen.

for (start; check; update) {

anweisungen;

}

Hier bezeichnet start also die einmalig zum Start der Schleife durchzuführenden Initialisierun-gen von Variablen, check die vor jeder Iteration zu überprüfende Schleifenbedingung und up-date stets am Ende des Schleifenrumpfs auszuführenden Anweisungen. Die for-Schleife eignetsich besonders zur Implementierung einer Zählschleife, also einer Schleife, die eine Zählvaria-ble oder einen „Index“ von einem Startwert bis zu einen Endwert hochzählt:

for ($i = 0; $i < 10; $i++) {

echo "$i, ";

}

oder runterzählt:

for ($i = 10; $i > 0; $i--) {

echo "$i, ";

}

In dieser Schleife werden also im Gegensatz zu den while-Schleifen die für die Verwaltung einerSchleife wichtigen Anweisungen übersichtlich im Schleifenkopf aufgelistet. Auch mit diesemSchleifenkonstrukt kann man eine Endlosschleife programmieren, wenn nämlich die Update-Anweisung (und die Anweisungen im Schleifenrumpf) nicht dazu führen, dass die Schleifen-bedingung falsch wird. Beispielsweise: for($i=10; $i>0; $i++) ...

6.2.4 foreach-SchleifeAn dieser Stelle sei auf eine weitere wichtige Schleifenkonstruktion hingewiesen, die allerdingsnur mit der Kenntnis von Arrays oder Objekten zu verstehen ist und daher erst im Abschnitt 7.2auf Seite 77 und mit einer wichtigen Variante in Abschnitt 7.3 ab Seite 79 behandelt wird.

6.3 FunktionenWie in anderen Programmiersprachen ist es in PHP möglich, häufig benutzte Programmteileals Funktionen zu definieren und von anderen Programmteilen oder ganz anderen Programmenaufzurufen. An Funktionen können Parameter übergeben werden, von denen der Ablauf der

Page 70: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

70 Andreas de Vries

Funktion abhängt. Eine Funktion wird mit einer return-Anweisung beendet, wenn sie einenWert an den aufrufenden Programmteil zurückgeben soll. Die Syntax der Deklaration einerFunktion beginnt in PHP mit dem reservierten Wort function, gefolgt von einem Block ingeschweiften Klammern:

function myFunction ($x1, $x2, ...) {

anweisungen;

}

Hierbei können Standardwerte für Eingabeparameter vergeben werden, so dass bei einem Funk-tionsaufruf die Parameter „von hinten beginnend“ weggelassen werden können. Mit diesemKonzept der optionalen Parameter kann man in PHP Funktionen in eingeschränkter Weise„überladen“.3

Betrachten wir als Beispiel für Funktionen das folgende PHP-Skript:

Listing 6.1: Funktionen1 <!-- Einige Funktionen. Dateiname: funktionen.php -->

2 <h2>Einige Funktionen</h2>

3 <?php

4 function f($x) {

5 return $x * $x;

6 }

7

8 function pythagoras($x, $y = 12) {

9 return sqrt($x*$x + $y*$y);

10 }

11

12 /** Text wird gelb grundiert */

13 function gelbHG($text) {

14 return "<span style='background-color:yellow'>$text</span>";

15 }

16

17 echo " f(2) = " . f(2) . ", f(4) = " . f(4) . "<br/>";

18 $x = 3; $y = 4;

19 echo " pythagoras($x,$y) = " . pythagoras($x,$y);

20 $x = 9;

21 echo "<br/> pythagoras($x) = " . pythagoras($x) . "<br/>";

22 echo " Dieser " . gelbHG("Textteil") . " wird gelb grundiert.";

23 ?>

24 </body>

25 </html>

Es sind drei Funktionen deklariert, zwei mathematische und eine, die einen String formatiert.Es wird eine der mathematischen Standardfunktionen von PHP aufgerufen, sqrt. Die Funktionpythagoras ist mit dem zweiten optionalen Parameter $y deklariert, der bei einem Aufruf mitnur einem Parameter mit dem Standardwert 12 belegt wird. Die Ausgabe des Programms imListing 6.1 im Browserfenster ist in Abbildung 6.1 dargestellt. Beachten Sie bei der Analysedes Aufrufs pythagoras(9), dass 92 +122 = 152.

3 In der Programmierung nennt man die Deklaration von Funktionen mit gleichem Namen, aber unterschiedli-cher Parameterliste, ein Überladen der Funktion. Da aufgrund der dynamischen Typisierung von Variablen in PHPeine wohldefinierte Signatur von Funktionen nicht existiert, ist ein echtes Überladen wie in Java nicht möglich.

Page 71: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 71

Abbildung 6.1: Die Browseranzeige von Beispiel 6.1.

6.3.1 Lokale VariablenWird eine Variable in PHP innerhalb einer Funktion verwendet, so ist sie eine lokale Variable,ihr Geltungsbereich ist also nur die Funktion.

1 $temp = 5;

2 function lokalTest($x) {

3 echo "In Funktion (vorher): \$temp = $temp<br/>";

4 $temp = 2*$x;

5 echo "In Funktion (nacher): \$temp = $temp<br/>";

6 }

7

8 lokalTest(50);

9 echo "\$temp = $temp";

Man kann in PHP zwar auch „globale“ Variablen verwenden, indem man sie in der Funktionals global deklariert. Mit global zu arbeiten, ist aus zwei Gründen jedoch nicht ratsam. Erstenssind die so deklarierten Variablen nicht echt global, denn man muss ja in jeder Funktion separatfestlegen, dass sie es sind. (global $x; außerhalb einer Funktion nutzt nichts!) Zum zweitenkann es bei etwas umfangreicheren Systemen dazu kommen, dass in irgendeiner von tausendenvon Funktionen der Programmierer eine Variable globalisiert, deren Namen auch irgendwo imHauptskript verwendet wird. Die Funktion ändert ihren Wert, und die Ursache ist sehr schwerzu finden.

Die einzigen echt globalen Variablen heißen in PHP superglobal. Sie gelten an jeder Stelleeines PHP-Skripts, also auch in Funktionen (und dürfen dort nicht als global deklariert wer-den!). Superglobale Variablen sind meist Arrays, die externe Daten enthalten, die wichtigstensind $_GET, $_POST, $_SERVER, $_FILES, $_ENV, $_SESSION, $_COOKIE.

6.4 Auslagern und Einbinden von PHP-CodeEs können externe PHP-Dateien eingebunden werden. Dies erfolgt mit den Befehlen require_once

oder include_once. Die Wirkung beider Befehle ist identisch, zumindest solange kein Fehlerbeim Laden der Datei auftritt: include_once gibt in diesem Falle lediglich eine Fehlermeldungaus, während require_once das komplette Skript mit einem „fatalen Fehler“ abbricht.

Listing 6.2: Die PHP-Datei zu Beispiel 6.31 <!-- Dateiname: addition2.php -->

2 <h2>Aufsummierung natürlicher Zahlen (Arithmetische Reihe)</h2>

3 <?php

4 require_once("./includes/addition2.inc.php");

5 $zahl = 6;

6 echo "Die Summe bis $zahl ist " . summeBis($zahl);

Page 72: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

72 Andreas de Vries

7 ?>

Die Datei mit der zugehörigen eingebundenen Datei:

Listing 6.3: Die PHP-Datei zu Listing 6.21 <!-- Datei addition2.inc.php im Verzeichnis ./includes/ -->

2 <?php

3 function summeBis($n) {

4 return ($n + 1) * $n / 2;

5 }

6 ?>

Wir erkennen, dass in der eingefügten PHP-Datei ebenfalls die PHP-Tags stehen müssen. DiePHP-Datei heißt addition2.inc.php und befindet sich im Verzeichnis includes unterhalb desVerzeichnisses, in dem die HTML-Datei (addition2.php) beheimatet ist. Deshalb wird im require_once-Befehl der relative Pfad zu addition2.inc.php angegeben. Pfad- und Dateinamen werden inAnführungszeichen und runden Klammern eingeschlossen

Die Extension .inc.php ist nicht zwingend notwendig, hat sich aber eingebürgert. Das Kür-zel .inc weist darauf hin, dass es sich um eine eingebettete Datei handelt, die weitere Extension.php ist dann aus Sicherheitsgründen notwendig. Dateien mit der Extension .inc werden, wennsie alleine aufgerufen werden, vom Server nicht ausgeführt. Errät ein Benutzer aber Pfad undNamen einer solchen Datei, kann er dies als URL direkt im Browser eingeben; der Server führtden Code nicht aus, sondern überträgt ihn als Quelltext an den Browser, der ihn dann darstellt.Endet die Datei aber auf .php, wird sie auf jeden Fall vom Server ausgeführt.

Für eine Auslagerung von PHP-Programmen in eigene Dateien sprechen die folgenden Ar-gumente.

• Allgemeine Funktionen, Variablen oder Standardeinstellungen können von mehreren PHP-Skripten verwendet werden. Beispielsweise kann man Standardeinstellungen wie Userund Passwort für einen Datenbankzugriff als Datei auslagern und kann sie so flexibel undzentral verwalten.

• Die PHP-Datei mit dem Hauptprogramm wird kleiner und besser überschaubar.

• Die Erstellung von HTML- und PHP-Datei kann mit unterschiedlichen Werkzeugen er-folgen.

Code, der nur von einem PHP-Skript genutzt wird, in eine eigene Datei auszulagern, ist jedochnicht immer sinnvoll. Das aufrufende Skript wird zwar besser überschaubar, doch dafür musseine weitere Datei geöffnet werden. Bei kleineren Dateien überwiegt dieser Nachteil. Dochsobald die Seiten größer werden oder wir Programme schreiben, die mehrfach genutzt werdenkönnen, rentiert sich eine Auslagerung des Quelltextes in eigene Dateien.

6.4.1 require und include

Es gibt zwei ähnliche Funktionen zum Einbinden von ausgelagerten Dateien, include undrequire. Sie werden häufig in kleinen Projekten oder einfachen Systemen verwendet. Sie habendieselbe Wirkung wie die „_once“-Varianten, verhindern aber nicht eine Mehrfacheinbindungderselben Datei. In komplexen Systemen mit einer tiefen Einbindunghierarchie kann eine sol-che Mehrfacheinbindung schnell vorkommen; beispielsweise wird in dem Fall

A bindet B und C ein, B bindet C ein,

die Datei C von A zweimal eingebunden. Mit require_once und include_once wird genau dasverhindert. Insbesondere in komplexeren Systemen sind letztere daher zu empfehlen.

Page 73: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 73

6.5 Zeit- und Datumsfunktionen in PHPMehrere PHP-Funktionen arbeiten mit Datums- und Uhrzeitangaben. Meistens erzeugen sieeinen Unix-Zeitstempel (Unix timestamp) oder formatieren einen Unix-Zeitstempel so, dass erfür Menschen lesbar wird.

Ein Unix-Zeitstempel (oder „Systemzeit“) zeigt die Anzahl der Sekunden an, die seit dem(willkürlich gewähltem) Datum 1.1.1970, 0:0:0 Uhr Greenwich Mean Time vergangen sind. Diemeisten Systeme stellen einen Zeitstempel mit einem vorzeichenbehafteten 32-Bit-Integer dar,was einem Datumsumfang vom 13.12.1901 bis 19.1.2038 entspricht, bei Microsoft Windowsnur vom 1.1.1970 bis 19.1.2038. Bei einem Datum außerhalb dieser Bereiche kann es alsoProbleme geben.

6.5.1 Erzeugen eines ZeitstempelsEs gibt im wesentlichen zwei Funktionen, die in PHP einen Zeitstempel erzeugen. Die erste,

int time()

wird stets ohne Parameter aufgerufen und liefert den Zeitstempel der aktuellen Systemzeit. Umden Zeitstempel eines bestimmten Datums zu erzeugen, gibt es die Funktion

int mktime(int stunde, int min, int sek, int monat, int tag, int jahr)

Sie wird in der amerikanischen Datumsschreibweise (Monat/Tag/Jahr) aufgerufen. (PHP fin-det selbständig heraus, ob es sich um Winter- oder Sommerzeit handelt.) Will man also denZeitstempel des 23. Februar 2008, 12 Uhr mittags (Winterzeit) erzeugen, so programmiert man

$zeit = mktime(12, 0, 0, 2, 23, 2008); // ergibt $zeit = 1203764400

Die Funktion geht auch mit Parameterwerten korrekt um, die eigentlich kein korrektes Datumsind, beispielsweise liefert mktime(0, 0, 0, 2, 30, 2008) die Systemzeit des 1.3.2008 0:0:0Uhr, oder mktime(26, 0, 0, 14, 29, 2004) die vom 2.3.2005 2:0:0 Uhr. Auf diese Weise kannman gut Fristen oder Zeiträume addieren oder subtrahieren:

$frist = 10; // 10 Tage Frist

$fristEnde = mktime(12, 0, 0, 2, 23 + $frist, 2008); // ergibt 1204628400

6.5.2 Formatierte ZeitangabenDer Unix-Zeitstempel ist sehr praktisch zum Programmieren, aber er hat kein brauchbares An-zeigeformat. Die Funktion date liefert eine formatierte Ausgabe des Zeitstempels:

int date(string Formatmuster, int zeitstempel)

Hierbei ist das Formatmuster ein String, in dem festgelegte Buchstaben als Parameter übergebenwerden, beispielsweise erzeugt

$zeit = mktime(10, 0, 0, 5, 20, 1964);

echo date("D d.m.Y u\m H:i:s \U\h\\r", $zeit); //=> "Wed 20.05.1964 um 10:00:00 Uhr"

Soll ein Buchstabe ausgegeben werden, der einen Parameter darstellt (wie m, U, h oder r), somuss ein Backslash verwendet werden. Ein ganz fieser Sonderfall sind jedoch die Buchstaben r

und n in diesem Zusammenhang: \r und \n sind Escape-Zeichen, nämlich die Steuerzeichen fürRücksprung und Zeilenumbruch, und daher müssen sie mit zwei Schrägern versehen werden!

Eine vollständige Liste aller Parameter für das Formatmuster finden Sie im PHP-Manualonline unter

http://www.php.net/manual/de/function.date.php

Page 74: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

7Arrays

Kapitelübersicht7.1 Indizierte (numerische) Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 747.2 Die foreach-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 777.3 Assoziative Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 777.4 Mehrdimensionale Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 807.5 Nützliche Funktionen für Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

7.5.1 Debuggen mit print_r oder var_dump . . . . . . . . . . . . . . . . . . . . . . 837.5.2 Funktionen zum Arrayinhalt: count, sizeof, empty . . . . . . . . . . . . . . . 837.5.3 explode und implode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 847.5.4 Sortierfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

7.6 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

Arrays gehören zu den wichtigsten Datenstrukturen der Informatik überhaupt. Ein Array (dt.„Ansammlung“) ist eine indizierte Anordnung von Datenelementen oder Einträgen. D.h., mankann auf einen Eintrag des Arrays, also dessen Dateninhalt, mit Hilfe eines Indexes zugreifen.Ein Array ist also kein einzelner Wert, sondern eine Liste von Werten oder Elementen. Z.B.kann man sich ein Array namens $farbe wie folgt vorstellen.

$farbe

Indexrot grün blau gelb0 1 2 3

(7.1)

Wie in den meisten modernen Programmiersprachen ist der erste Array-Index 0, d.h. die Indizeseines Arrays $daten mit 4 Einträgen laufen von 0 bis 3,

$farbe[0], $farbe[1], $farbe[2], $farbe[3].

In PHP gibt es zwei verschiedene Arten von Arrays, einfache (oder numerische) Arrays undassoziative Arrays. Ein assoziatives Array erweitert gewissermaßen den Begriff des Index undlässt einen Datenzugriff über Strings (und nicht nur numerische Werte) zu.

7.1 Indizierte (numerische) ArraysEin indiziertes oder numerisches Array spricht seine Elemente über einen durchnummeriertenIndex an. Ein Array selber ist durch eine Variable, also ein Dollarzeichen $ und einen Namenansprechbar, also z.B. $farbe.

74

Page 75: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 75

Ein Array kann in PHP durch das Schlüsselwort array() mit den runden Klammern erzeugtwerden. Mit $farbe = array() wird also ein leeres Array erzeugt, dass dann im Verlauf desProgramms gefüllt werden kann.

Um ein Element eines Arrays gezielt anzusprechen, wird sein Index in eckigen Klammernhinter den Arraynamen geschrieben, z.B. $farbe[1] = "grün".

Beispiel 7.1. (3 Arten, Arrays zu bilden)

1 <!-- Ein Array von Farben. Dateiname: farben.php -->

2 <h2>Ein Array von Farben</h2>

3 <?php

4 /* 1. Methode, um ein Farbe-Array zu bilden: */

5 $farbe1 = array();

6 $farbe1[] = "rot";

7 $farbe1[] = "grün";

8 $farbe1[] = "blau";

9 $farbe1[] = "gelb";

10

11 echo "farbe1:";

12 echo "<table border=\"1\">";

13 echo " <tr> ";

14 for( $i=0; $i < sizeof($farbe1); $i++ ) {

15 echo "<td>$farbe1[$i]</td>";

16 }

17 echo " </tr>";

18 echo "</table>";

19

20 /* 2. Methode, um ein Farbe-Array zu bilden: */

21 $farbe2 = array("rot", "grün", "blau", "gelb");

22

23 echo "<hr/>farbe2:";

24 echo "<table border='1'>";

25 echo " <tr> ";

26 foreach ( $farbe2 as $element ) {

27 echo "<td>$element</td>";

28 }

29 echo " </tr>";

30 echo "</table>";

31

32 /* 3. Methode, um ein Farbe-Array zu bilden: */

33 $farbe3 = ["rot", "grün", "blau", "gelb"];

34

35 echo "<hr/>farbe3:";

36 echo "<table border='1'>";

37 echo " <tr> ";

38 foreach ( $farbe3 as $element ) {

39 echo "<td>$element</td>";

40 }

41 echo " </tr>";

42 echo "</table>";

43 ?>

Page 76: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

76 Andreas de Vries

Die Browseranzeige des Skripts sehen Sie in Abb. 7.1. Das Skript zeigt drei Arten, ein

Abbildung 7.1: Die Browseranzeige von Beispiel 7.1.

numerisches Array zu bilden, sowie zwei Wege, ein Array mit einer Schleife zu durchlaufen. Injeder dieser Schleifen erstellen die echo-Befehle eine einzeilige Tabelle, in deren Zellen jeweilsein Array-Eintrag steht. Man erkennt die erste Art, ein Array zu bilden:

$farbe1 = array();

$farbe1[] = "rot";

$farbe1[] = "grün";

$farbe1[] = "blau";

$farbe1[] = "gelb";

Beim Aufbau eines Arrays in PHP werden die Werte bzw. Elemente wie in Regalfächern vonunten nach oben immer höher abgelegt. Die Indexnummer entspricht entspricht einer Fachnum-mer der Regale und wird automatisch beginnend bei 0 gezählt.

Der Aufbau eines Arrays mit expliziter Indexangabe ist natürlich ebenso möglich, also

$farbe1 = array();

$farbe1[0] = "rot";

$farbe1[1] = "grün";

$farbe1[2] = "blau";

$farbe1[3] = "gelb";

Da PHP die Indexverwaltung jedoch automatisch durchführen kann, braucht man diesen Auf-bau normalerweise nicht zu machen. Auch könnten bei einer solchen manuellen Indexssteue-rung Lücken oder doppelte Zuweisungen auftreten. Manchmal kann es aber sinnvoll sein, eineexplizite Indexzuweisung zu machen, oder vielleicht ist dem Einen oder Anderen beim Pro-grammieren wohler, wenn er die Indexzuordnung selber sehen kann.

Das gleiche Array wird in einer Anweisung erzeugt durch eine zweite Art:

$farbe2 = array("rot", "grün", "blau","gelb");

Dieser Aufbau ist sinnvoll, wenn man die Werteliste von Anfang an kennt. Eine weitere Vari-ante, ein Array zu erzeugen, wenn man seine Einträge bei Programmierung des Arrays bereitskennt, ist wie folgt:

$farbe3 = ["rot", "grün", "blau", "gelb"];

Diese Variante mit den eckigen Klammern [...] ist die Syntax eines JSON-Arrays und als„short syntax array“ bekannt.

Page 77: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 77

Gleichgültig wie man ein Array aufgebaut hat, der Zugriff auf ein Element geschieht mitder Indexnummer; so ergäbe z.B. echo $farbe1[3]; die Ausgabe gelb. Die Anzahl der Ele-mente eines Arrays, d.h. die Länge des Arrays, kann man mit der Funktion sizeof oder countbestimmen.

Die Ausgabe des Arrays $farbe1 in dem Beispielskript geschieht mit einer for-Schleife:

for($i=0; $i < sizeof($farbe1); $i++) {

echo "<td>$farbe1[$i]</td>";

}

Der Laufindex ist $i; er beginnt bei 0 und geht bis zum Ende des Arrays, das man mit der Stan-dardfunktion sizeof herausfindet. Da die 0 mitgezählt wird, muss $i vorher aufhören (daheralso $i<sizeof($farbe1) als Endebedingung).

Die Ausgabe des zweiten Arrays $farbe2 zeigt eine weitere komfortablere Möglichkeit,Arrays in PHP zu verarbeiten, die foreach-Schleife.

7.2 Die foreach-SchleifeIn dem Skriptbeispiel 7.1 ist eine spezielle (von Perl geerbte) Schleife, die foreach-Schleife.Sie ist speziell für Arrays anwendbar und hat einen „kürzeren“ Schleifenkopf als die für Arraysverwendete for-Schleife. Ihre Syntax für ein Array namens $array lautet:

foreach ($array as $element) {

anweisungen;

}

Hierbei wird das Array $array von Anfang bis Ende durchlaufen und bei jedem Schleifen-durchlauf wird das aktuelle Element der Variablen $element zugewiesen. Der Variablenname$element ist frei wählbar, er sollte allerdings keine existierende Variable überschreiben. Aufdiese Weise können Sie den Ausgabeteil in Beispiel 7.1 leicht nachvollziehen. Auf eine wichti-ge Erweiterung der foreach-Schleife kommen wir auf Seite 79 zu sprechen.

7.3 Assoziative ArraysAssoziative Arrays werden nicht über einen durchnummerierten Index verwaltet, sondern überStrings, so genannte Schlüssel (keys). Dieser Schlüssel muss das jeweilige Element eindeutigbeschreiben. Damit entsteht eine assoziative Verbindung zwischen Schlüssel und Wert.

Beispiel 7.2. (Adresse als assoziatives Array)

1 <!-- Ein Adressen als Array Dateiname: adresse1.php -->

2 <html>

3 <head><title>Adresse</title></head>

4 <body>

5 <h2>Eine Adresse als Array</h2>

6 <?php

7 $adresse = array();

8 $adresse["vorname"] = "Andreas";

9 $adresse["nachname"] = "de Vries";

10 $adresse["email"] = "[email protected]";

11 $adresse["web"] = "www2.fh-swf.de/fbtbw/deVries.htm";

Page 78: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

78 Andreas de Vries

12 $adresse["strasse"] = "Haldener Straße 182";

13 $adresse["plz"] = "D-58095";

14 $adresse["ort"] = "Hagen";

15

16 echo "<table border=\"1\"> \n";

17 echo " <tr> \n";

18 foreach ( $adresse as $key => $value ) {

19 if ( $key == "email" ) {

20 echo " <td><a href=\"mailto:$value\">$value</a></td>\n";

21 } else if ( $key == "web" ) {

22 echo " <td><a href=\"http://$value\">$value</a></td>\n";

23 } else {

24 echo " <td>$value</td> \n";

25 }

26 }

27 echo " </tr>\n";

28 echo "</table>";

29 ?>

30 </body>

31 </html>

Das PHP-Skript ergibt die Ausgabe Abb. 7.2 im Browser. Interessant ist der von dem PHP-

Abbildung 7.2: Die Browseranzeige von Beispiel 7.2.

Skript erzeugte HTML-Code in Abb. 7.3, den man in der Quelltextanzeige des Browsers sehenkann.

Aus dem Skript wird ersichtlich, wie man assoziative Arrays erzeugen kann, nämlich indemman einfach den Schlüssel in eckige Klammern nach dem Arraynamen setzt und die Werte derElemente diesem zuordnet:

$adresse = array();

$adresse["vorname"] = "Andreas";

$adresse["nachname"] = "de Vries";

$adresse["email"] = "[email protected]";

$adresse["web"] = "www2.fh-swf.de/fbtbw/deVries.htm";

Entsprechend kann auf jeden Array-Wert mit seinem Schlüssel zugegriffen werden:

echo $adresse[nachname]; ergibt de Vries

Page 79: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 79

Abbildung 7.3: Die Browseranzeige des HTML-Quelltextes von Beispiel 7.2.

Ähnlich der Array-Erzeugung eines numerischen Arrays in einem Schritt wie bei $farbe2 kannman auch assoziative Arrays mit einer einzigen Anweisung erzeugen. Dazu wird der Assoziati-onsoperator verwendet:

$adresse = array(

"vorname" => "Andreas",

"nachname" => "de Vries",

"email" => "[email protected]",

"web" => "www2.fh-swf.de/fbtbw/deVries.htm",

"strasse" => "Haldener Straße 182",

"plz" => "D-58095",

"ort" => "Hagen"

);

Alle Schlüssel-Wert-Paare (key-value pairs) werden nacheinander aufgeführt, d.h. das Aufbau-prinzip ist stets

$myArray = array(

"key_0" => "value_0",

...

"key_n" => "value_n"

);

Die foreach-Schleife kann man auch auf ein assoziatives Array anwenden. Zuende überlegtist sie sogar die einzige Schleifenkonstruktion, die man zum Durchlaufen eines assoziativenArrays verwenden kann! (Denn keine der anderen Schleifen hat bei nichtnumerischen Arrayseine Chance, an die Schlüssel zu kommen. . . ) Zusätzlich hat man mit der foreach-Schleife sogardie Möglichkeit, auf die Schlüssel zuzugreifen, und zwar mit Hilfe des Assoziationsoperators:

foreach ($myArray as $key => $element) {

anweisungen;

}

Wir werden im nächsten Skriptbeispiel eine Anwendung kennen lernen.

Page 80: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

80 Andreas de Vries

7.4 Mehrdimensionale ArraysMehrdimensionale Arrays sind Arrays in Arrays. Ein zweidimensionales Array kann man sichvorstellen als eine Tabelle oder Matrix, in der eine Spalte ein Array von Reihen ist, und eineReihe wiederum ein Array von Zellen. Z.B. stellt das Array

$tabelle = array(

array("A", "B", "C"),

array("D", "E", "F")

);

eine 3×2-Tabelle dar:

j↓

A B CD E F

← i

Auf einen bestimmten Wert des Arrays greift man entsprechend mit mehreren Indizes zu, also

$tabelle[i][ j].

Hierbei bezeichnet i die Nummer der Zeile (beginnend bei 0!) und j die Spalte, wie in derTabelle angedeutet. D.h. in unserem Beispiel:

echo $tabelle[0][2]; ergibt C.

Man kann i und j auffassen als Koordinaten, die jeweils den Ort einer Datenzelle angeben, soähnlich wie A-2 oder C-5 Koordinaten eines Schachbretts (oder des Spielfeldes von Schiffe-versenken oder einer Excel-Tabelle usw.) sind. In einem assoziativen Array nehmen die Koor-dinaten die Werte der Schlüssel an.

Höherdimensionale Arrays werden entsprechend gebildet. Ein dreidimensionales Array istein Array von Arrays von Arrays von Elementen; man kann es sich vorstellen als einen Quadervon Würfeln als Zellen. Jede Zelle kann durch 3 Koordinaten angesprochen werden,

$quader[i][ j][k]

Zwar kann man sich Arrays mit mehr als 3 Dimensionen nicht mehr geometrisch vorstellen,aber formal lassen sie sich genau so aufbauen.1 Man braucht dann genau so viele Indizes, wieman Dimensionen hat.

Das folgende Beispielskript erzeugt ein zweidimensionales Array von Adressen und gibt esals Tabelle aus, wie Abb. 7.4 zeigt. Zu beachten ist, dass der Tabellenkopf die Schlüssel desinneren Arrays enthält. Das PHP-Skript bindet eine separate Datei ein, die das 2-dimensionaleArray erzeugt.

Beispiel 7.3. Erzeugung eines zweidimensionalen Arrays in externer Datei

1 <?php

2 // Dateiname: adressen.inc.php

3 /* Es wird ein zweidimensionales Array von Adressen aufgebaut */

4 $adresse =

5 array(

1 In der Physiker und den Ingenieurwissenschaften ist der Begriff des Tensors geläufig, der ist als ein mehrdi-mensionales Array darstellbar.

Page 81: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 81

Abbildung 7.4: Die Browseranzeige von Beispiel 7.1.

6 array(

7 "vorname" => "Bernd",

8 "nachname" => "Blümel",

9 "email" => "[email protected]",

10 "web" => "www.fh-bochum.de/fb6/personen/bluemel/",

11 "strasse" => "Lennershofstraße 140",

12 "plz" => "D-44801",

13 "ort" => "Bochum"

14 ),

15 array(

16 "vorname" => "Andreas",

17 "nachname" => "de Vries",

18 "email" => "[email protected]",

19 "web" => "www3.fh-swf.de/fbtbw/deVries.htm",

20 "strasse" => "Haldener Straße 182",

21 "plz" => "D-58095",

22 "ort" => "Hagen"

23 ),

24 array(

25 "vorname" => "Ingo",

26 "nachname" => "Schröder",

27 "email" => "[email protected]",

28 "web" => "www3.fh-swf.de/fbtbw/Schroeder.htm",

29 "strasse" => "Haldener Straße 182",

30 "plz" => "D-58095",

31 "ort" => "Hagen"

32 ),

33 array(

34 "vorname" => "Volker",

35 "nachname" => "Weiß",

36 "email" => "[email protected]",

37 "web" => "www3.fh-swf.de/fbtbw/Weiss.htm",

38 "strasse" => "Haldener Straße 182",

39 "plz" => "D-58095",

40 "ort" => "Hagen"

41 )

42 );

Page 82: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

82 Andreas de Vries

43 ?>

Der Source-Code des Skripts selber lautet wie folgt.

Listing 7.1: Adressen als zweidimensionales Array1 <!-- Adressen als 2-dimensionales Array. Dateiname: adresse2.php -->

2 <h2>Adressen als 2-dimensionales Array</h2>

3 <table border="1">

4 <?php

5 require_once( "./adressen.inc.php" );

6

7 // Tabellenkopf:

8 echo " <tr>\n";

9 foreach ( $adresse[0] as $key => $value ) {

10 echo " <th>$key</th>\n";

11 }

12 echo " </tr>\n";

13

14 // Tabelleneinträge:

15 foreach ( $adresse as $adressEintrag ) {

16 echo " <tr>\n";

17 foreach ( $adressEintrag as $key => $value ) {

18 if ( $key == "email" ) {

19 echo " <td><a href=\"mailto:$value\">$value</a></td>\n";

20 } else if ( $key == "web" ) {

21 echo " <td><a href=\"http://$value\">$value</a></td>\n";

22 } else {

23 echo " <td>$value</td> \n";

24 }

25 }

26 echo " </tr>\n";

27 }

28 ?>

29 </table>

Die inneren Arrays sind die assoziativen Adress-Arrays, die wir aus dem vorigen Abschnittkennen. Das äußere Array $adresse ist, wie der aufmerksame Leser erkennt, ein numerischesArray. Direkt nach der Erzeugung des zweidimensionalen Arrays folgt seine Ausgabe. Dabeiist zu beachten, dass das table-Element vor den PHP-Markierungen geöffnet wurde.

<body>

<h2>Adressen als 2-dimensionales Array</h2>

<table border="1">

<tr>

<?php

...

Der Tabellenkopf wird mit einer foreach-Schleife eingeleitet,

foreach ( $adresse[0] as $key => $value ) {

echo " <th>$key</th>\n";

Page 83: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 83

}

echo "</tr>\n<tr>\n";

Was passiert hier? Mit dem Index 0 wird auf das erste Element des Arrays $adresse zugegriffen,also eine Adresse, die ein assoziatives Array ist. Da wir für den Tabellenkopf die Schlüsseldieses Arrays benötigen, machen wir sie uns mit der „Maske“ $adresse[0] as $key => $value

als Variable $key zugänglich – um sie dann als table head innerhalb der <th>-Tags auszugeben.

7.5 Nützliche Funktionen für ArraysPHP liefert einige nützliche Standardfunktionen für Arrays, sie sind vollständig in der PHP-Do-kumentation http://php.net/manual/de/ref.array.php verfügbar. Die wichtigsten davon wer-den in diesem Abschnitt beschrieben.

Beispielsweise mit in_array überprüfen, ob ein bestimmter Wert in einem Array existiert,oder mit array_search, welchen Schlüssel ein gegebener Wert in dem Array hat.2

7.5.1 Debuggen mit print_r oder var_dump

Sehr nützlich beim Programmieren mit Arrays in PHP sind die Funktionen print_r, und var_dump,die eine lesbare Kurzdarstellung von Arrays (und übrigens auch Objekten) liefern und direkt imBrowserfenster ausgeben. Allerdings ist diese Ausgabe nicht in HTML formatiert, sondern inreinem Text, man sollte sie sich also im Browser als Quelltext anschauen. Ein kleines Programmzur Demonstration dazu lautet:

1 <?php

2 $array = array("a", "b", "", "d", null, "f");

3 print_r($array);

4 var_dump($array);

5 echo "count: " . count($array) . ", sizeof: " . sizeof($array); // => 6

6 if (empty($array)) echo " leer!"; else echo " gefuellt!";

7 ?>

7.5.2 Funktionen zum Arrayinhalt: count, sizeof, emptyUm die Größe eines Arrays zu bestimmen, gibt es die Funktionen count und sizeof. Zwar istin PHP sizeof ein Alias von count, letztere also „das Original“, aber vom Sinn her klarer undauch in besserem Einklang mit ähnlichen Funktionen in anderen Programmiersprachen und -konventionen ist sizeof und m.E. zu bevorzugen. Beide Funktionen zählen die eingetragenenenElemente des Arrays, auch wenn diese ein leerer String oder null sind.

1 <?php

2 $array = array("a", "b", "", "d", null, "f");

3 print_r($array);

4 var_dump($array);

5 echo "count: " . count($array) . ", sizeof: " . sizeof($array); // => 6

6 if (empty($array)) echo " leer!"; else echo " gefuellt!";

2array_search liefert false zurück, wenn der gesuchte Wert gar nicht in dem Array existiert. Da nun dergesuchte Wert durchaus mit dem Index 0 in dem Array sein könnte, in PHP jedoch false und 0 nur schwerzu unterscheiden sind, sollten Abfragen auf den Misserfolg der Suche unbedingt mit dem Identitätsoperator ===

erfolgen.

Page 84: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

84 Andreas de Vries

7 ?>

Mit der Funktion empty kann man prüfen, ob das Array leer ist.

7.5.3 explode und implode

Zwei sehr nützliche Standardfunktionen für Arrays sind explode und implode, die einen Stringin ein Array umwandeln bzw. umgekehrt. Sie eignen sich insbesondere zum Export oder Importvon csv-Dateien (comma separated values), die von Excel und anderen Tabellenkalkulations-programmen erstellt oder gelesen werden können.

Funktion Beispiel Beschreibungexplode() $arr=explode(";",$str); zerlegt den übergebenen String (hier $str)

an bestimmten Trennzeichen (hier Semiko-lons ";") und gibt das Ergebnis als Array zu-rück

implode() $str=implode(";", $arr); verbindet alle Array-Elemente des übergebe-nen Arrays (hier $arr) zu einem String, indem sie durch die übergebenen Trennzeichen(hier Semikolons ";") unterteilt sind.

Listing 7.2: implode und explode, label=bsp-imexplode1 <!-- implode und explode. Dateiname: imexplode.php -->

2 <?php

3 // erstelle Adressen als csv-Format:

4 require( "./adressen.inc.php" );

5 foreach ($adresse as $adressEintrag ) {

6 $adressEintrag = implode(";", $adressEintrag) . "\n";

7 echo $adressEintrag;

8 }

9 ?>

In dem Skript wird unser zweidimensionales Adress-Array aus Beispiel 7.1 eingelesen, und ineiner foreach-Schleife wird jeder Adresseintrag (wieder ein Array!) mit implode in das csv-Format konvertiert. Zu beachten ist, dass in diesem Format die Datenzellen einer Zeile stan-dardmäßig durch ein Semikolon getrennt sind, während die Zeilen wiederum durch einen Zei-lenumbruch (\n) getrennt sind. Die Ausgabe im Browser sieht hier nicht so gut aus, da wir keineHTML-Formatierungen ausgeben. Aber in der Quelltextanzeige des Browsers erkennt man gutdie csv-Struktur.

7.5.4 SortierfunktionenFür die Sortierung von Arrays stehen neun Funktionen zur Verfügung. Sortiert werden kannvorwärts (aufsteigend), rückwärts oder mit Hilfe einer individuell festgelegten Funktion. Fürnumerische Arrays, Schlüssel von assoziativen Arrays und Inhalte assoziativer Arrays werdenunterschiedliche Funktionen verwendet.

Array vorwärts rückwärts funktionsabhängignumerisch sort($array) rsort($array) usort($array)

assoziativ (Schlüssel) ksort($array) krsort($array) uksort($array)

assoziativ (Inhalt) asort($array) arsort($array) uasort($array)

Page 85: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 85

Zu beachten ist, dass die Vorwärtssortierung Großbuchstaben vor Kleinbuchstaben sortiert, alsoZ < a. Daneben gibt es die Sortierfunktionen natsort und natcasesort: beide sortieren „na-türlich“, d.h. Zahlen werden als Zahlen und nicht als Ziffernfolgen sortiert. sort sortiert 125< 34, natsort und natcasesort sortieren 34 < 125. Sie werden wie sort($array) aufgerufen.natcasesort sortiert außerdem ohne Berücksichtigung der Groß- und Kleinschreibung.

Listing 7.3: Namen sortieren1 <!DOCTYPE html>

2 <html><head><meta charset="UTF-8"/></head><body>

3 <!-- Dateiname: sortListe.php -->

4 <?php

5 $liste = array("Schröder", "Blümel", "de Vries", "Weiß");

6 echo implode(", ", $liste) . "<br/>";

7 natcasesort($liste);

8 echo implode(", ", $liste);

9 ?>

10 </body></html>

In dem Beispielskript wird eine unsortierte Namensliste als String sortiert, indem sie zunächstmit explode in ein Array konvertiert wird, welches dann mit natcasesort sortiert und schließlichmit implode wieder in einen String verwandelt wird.

7.6 Zusammenfassung• Es gibt zwei Arten von Arrays in PHP, numerische Arrays à la $farbe[0], $farbe[1], . . . ,

und assoziative Arrays, $adresse["nachname"], $adresse["vorname"], . . . , ansprechbarüber Schlüssel (keys),

• Numerische Arrays können in einem Schritt erzeugt werden mit der array-Funktion

$myArray = array("value_0", "value_1", ... );

oder mit eckigen Klammern (der „short syntax“ Notation)

$myArray = ["value_0", "value_1", ... ];

Sie können aber auch sukzessive (als „Regalstapel“) gefüllt werden,

$myArray = array();

$myArray[] = "value_0";

$myArray[] = "value_1";

...

(wobei der Index auch auftreten kann, $myArray[2] = "blau"];).

• Assoziative Arrays werden entsprechend mit dem Assoziationsoperator => durch

$myArray = array(

"key_0" => "value_0",

...

"key_n" => "value_n"

);

oder sukzessive durch

Page 86: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

86 Andreas de Vries

$myArray = array();

$myArray["key_0"] = "value_0";

$myArray["key_1"] = "value_1";

...

• Sehr geeignet für Arrays ist die foreach-Schleife,

foreach ($myArray as $element) {

anweisungen;

}

Auf die Schlüssel in einem assoziativen Array kann man mit dem Assoziationsoperator=> zugegriffen werden,

foreach ($myArray as $key => $element) {

anweisungen;

}

• Zur Konvertierung eines Strings mit Trennzeichen in ein Array und zurück gibt es diebeiden nützlichen Funktionen explode und implode.

• Es gibt eine Reihe nützlicher Sortierfunktionen für Arrays, (S. 84). Vorsicht bei der Sortie-rung von Zahlen mit sort, es sortiert 124 < 35 und Z < a. Abhilfe schaffen die speziellenSortierfunktionen natsort (Sortierung „Zahlen-statt-Ziffern“) und natcasesort (Sortie-rung „Zahlen-statt-Ziffern“ + A < a < B).

Page 87: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

8Eingaben

Kapitelübersicht8.1 Eingaben in ein PHP-Skript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 888.2 Eingabe und Verarbeitung in einem einzigen Skript . . . . . . . . . . . . . . . . . . . 89

8.2.1 Euro-Dollar-Umrechnung . . . . . . . . . . . . . . . . . . . . . . . . . . . . 908.3 Eingabe und formatierte Ausgabe von Kommazahlen . . . . . . . . . . . . . . . . . . 928.4 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

Die Eingabe von Daten durch den Anwender in ein PHP-Programm geschieht über HTML-Formulare. In PHP kann man über die folgenden superglobalen Variablen feststellen, ob undwelche Daten mit einer Anfrage übermittelt werden.

• $_GET: Diese Variable enthält die vom Browser übermittelten Daten einer GET-Anfrageüber ein Formular mit dem Attribut method="GET" oder über den URL, wobei direkt hin-ter die Adresse des Skripts ein Fragezeichen gefolgt von durch ein Kaufmanns-Und (&)getrennte Schlüssel-Wert-Paare, also z.B.:

?polynom=x^2-4&x=2

• $_POST: Diese Variable enthält die vom Browser übermittelten Daten einer POST-Anfrageüber ein Formular mit dem Attribut method="POST".

• $_COOKIE: Diese Variable enthält die vom Browser übermittelten Cookie-Informationen.

• $_FILES: Diese Variable enthält Informationen über die vom Browser per POST-Anfragehochgeladenen Dateien.

Alle diese Felder sind assoziative Arrays und enthalten die übermittelten Daten unter demSchlüssel, der bei $_GET und $_POST von dem <input>-Tag des aufrufenden Formulars abhängt.Bei der Übertragung des Formulars mit der GET-Methode (method="GET") liegen die Daten allermit Namen versehenen Eingabeelemente (außer den Buttons) also in der $_GET-Variablen vor.Nach Abschicken des Formulars aus obigem Beispiel könnten wir in dem im action-Attributbestimmten PHP-Skript also die Werte

$_GET["anmeldename"], $_GET["passwort"], $_GET["farbe"], $_GET["groesse"],$_GET["datum"], $_GET["zeit"], $_GET["beitrag"],

87

Page 88: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

88 Andreas de Vries

Entsprechend kann der Wert eines Eingabeelements bei Übertragung per method="POST" mit derVariablen $_POST ermittelt werden.

Betrachten wir das folgende Beispielskript, das von obigem Formular wegen des action-Attributs aufgerufen wird. Es macht nichts anderes, als die Daten, die es empfangen hat, demBrowser zu spiegeln.

Listing 8.1: Ein einfaches Spiegelskript1 <!-- Spiegelt die empfangenen Daten. Dateiname: request-response.php -->

2 <p>Folgende Daten wurden empfangen:</p>

3 <?php

4 echo "\$_GET: <pre>"; print_r($_GET); echo "</pre>";

5 echo "<br/>\$_POST: <pre>"; print_r($_POST); echo "</pre>";

6 ?>

Hier wird mit $value der Inhalt des <input>-Tags mit Namen $key ausgegeben, also z.B. von$_GET[anmeldename], den der Benutzer in das Formular eingetragen hat.

Bei der Datenübertragung mit HTTPS werden die Parameterdaten aller HTTP-Methoden,insbesondere für $_GET, verschlüsselt. Vgl. dazu

https://https.cio.gov/faq/#what-information-does-https-protect.

8.1 Eingaben in ein PHP-SkriptAls erstes einfaches Beispiel betrachten wir eines unserer ersten Programme, die Addition vonZahlen. Der Benutzer soll über seinen Browser die Zahlen eingeben, unser Programm soll dieSumme der eingegebenen Zahlen ausrechnen und das Ergebnis ausgeben. Wir erstellen zunächsteine HTML-Seite, die ein Formular enthält, in das wir die beiden Summanden eingeben können.

Listing 8.2: Eingabeformular für zwei Zahlen1 <!-- Datei addition-2.html -->

2 <form action="./addition-2.php" method="POST">

3 x = <input type="text" name="x" size="3" /> <br/>

4 y = <input type="text" name="y" size="3" /> <br/><br/>

5 <input type="submit" value="Rechne!"/>

6 </form>

Wie wir bereits gelernt haben, führt das Klicken auf den Submit-Button dazu, dass der Inhalt derEingabefelder an den Server übertragen wird, der Server das im action-Attribut des form-Tagsangegebene Programm startet und diesem Programm die Inhalte der Eingabefelder übergibt.Bleibt also noch, diese PHP-Datei zu implementieren.

Listing 8.3: Berechnung der Eingaben von Beispiel 8.21 <!-- Datei addition-2.php -->

2 <?php

3 if (isset($_POST["x"]) && isset($_POST["y"])) {

4 $x = $_POST["x"];

5 $y = $_POST["y"];

6 echo "$x + $y = " . ($x + $y);

7 }

8 ?>

Page 89: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 89

Woher „weiß“ das PHP-Programm, welche Zahlen ich in die Eingabefelder eingegeben habe?Schauen wir uns dazu die Definition der beiden Eingabefelder in Beispiel 8.2 an:

<input type="text" name="x" size="3"/>

<input type="text" name="y" size="3"/>

Betrachten wir die name-Attribute der input-Tags. Hier werden den Eingabefeldern Namen ge-geben. Diese Namen werden als Schlüssel eines der superglobalen Arrays $_GET oder $_POST,abhängig von der Übertragungsmethode des Formulars, und mit den durch das Eingabefeldfestgelegten Werte an das aufgerufene PHP-Skript übergeben. Bei der Übertragung des For-mulars mit der POST-Methode liegen die Daten aller Input-Felder (außer den Buttons) in dem$_POST-Array vor:

<input ... name="x" value="7"/> ⇒ $_POST["x"] = "7"

Um Interaktivität in PHP zu realisieren, müssen wir also offenbar zwei Dateien programmieren:eine Seite, in der die Benutzer ihre Eingaben machen können, und eine Seite, die die Eingabenverarbeitet. Tatsächlich geht es aber auch mit nur einer einzigen PHP-Datei, wie wir im nächstenAbschnitt 8.2 sehen werden.

8.2 Eingabe und Verarbeitung in einem einzigen SkriptDurch das if-Kommando können wir unsere PHP-Programme vereinfachen. Bislang haben wir,wenn wir in PHP Benutzereingaben lesen wollten, immer zwei Dateien benötigt: Eine mit einemFormular, in das wir unsere Daten eingeben konnten und eine, die dann die Aktionen durchge-führt hat. Dies können wir nun ändern. Betrachten wir dazu das folgende Beispiel, in dem zweieinzugebende Zahlen dividiert werden, jedoch der Fall der Division durch 0 abgefangen wird.

Listing 8.4: Division in PHP, Eingabe und Ablauflogik in einem einzigen Skript1 <!-- Das Programm dividiert 2 Zahlen. Dateiname: division.php -->

2 <?php

3 if(!empty($_POST)) { // Daten über POST, d.h. Formular abgeschickt?

4 if($_POST['nenner'] == 0) { // Division durch 0 oder NaN?

5 echo "Versuch durch Null zu teilen!";

6 } else {

7 $quotient = $_POST['zaehler'] / $_POST['nenner'];

8 echo " $_POST[zaehler] / $_POST[nenner] = $quotient";

9 }

10 } else { // keine Daten über POST, d.h. das Skript wird erstmals aufgerufen

11 ?>

12 <form name="division" action="./division.php" method="post">

13 Zaehler: <br/>

14 <input type="text" name="zaehler" size="5"/> <br/>

15 Nenner: <br/>

16 <input type="text" name="nenner" size="5"/> <br/>

17 <input type="submit" value="Abschicken"/>

18 </form>

19 <?php

20 }

21 ?>

Neues beginnt schon in Zeile 3:

Page 90: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

90 Andreas de Vries

if(!empty($_POST))

Hier wird festgestellt, ob aus dem Formular Daten in der $_POST-Variablen übermittelt wurden.Ist dies nicht der Fall, handelt es sich um den ersten Aufruf der Seite und die Variable ist null,was als Bedingung false bedeutet.1 Da der if-Zweig nur in dem Fall durchgeführt wird, wennDaten in $_POST enthalten sind, können wir über die Namen der Input-Felder der Formulare aufdie Eingaben der Benutzer zugreifen und die Berechnung durchführen. Im else-Zweig dagegenwird das Formular erzeugt. Hier werden die PHP-Anweisungen durch ?> beendet, und es folgtreines HTML. Man kann PHP in einer Datei also beliebig oft an- und abschalten, sogar inner-halb von geschweiften Klammern. Die HTML-Zeilen erzeugen den Rest unseres Formulars,der Browser verarbeitet den Text original, der PHP-Interpreter „weiß“ gar nichts von ihm. DieAusführung von PHP-Code setzt erst wieder mit den Zeilen

<?php

}

ein. Die geschweifte Klammer schließt den else-Block ab und muss daher wieder im <?php

... ?>-Tag stehen. Natürlich kann man das gesamte Formular auch über echo-Befehle ausge-ben, nur wird in diesem Fall der Quelltext unübersichtlicher, insbesondere wegen der vielenAnführungszeichen in HTML, die ja dann alle als \" geschrieben werden müssten (oder ’, wasaber nicht XML-konform ist).

Machen wir uns noch einmal den zeitlichen Ablauf der Anwendung klar. Wird das PHP-Skript zum ersten Mal aufgerufen, so sind in $_POST noch gar keine Daten, und es wird der else-Zweig ausgeführt. Schickt der Anwender dagegen das Formular ab, so enthält $_POST wegenmethod = "post" nun Daten (übrigens auch, wenn die Werte alle leere Strings sein sollten), undda im action-Attribut des Formulars das Skript selbst angegeben ist, ruft es sich selber wiederauf. d.h. der if-Zweig wird durchgeführt und der Quotient wird berechnet.

8.2.1 Euro-Dollar-UmrechnungWir wollen nun ein Programm schreiben, das Eurobeträge in Dollarbeträge und umgekehrt um-rechnet. In das Eingabeformular soll der Anwender die Zielwährung aus einer select-Box aus-wählen können, nach dem Abschicken soll dann das Ergebnis der Umrechnung angezeigt wer-den, und das Formular soll eine erneute Eingabe ermöglichen. Die Lösung des Problems in PHPist in Beispiel 8.5 dargestellt.

Listing 8.5: Umrechnung Euro-Dollar1 <!-- Euro-Dollar Umrechnung. Dateiname: euro.php //->

2 <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="POST">

3 Kurs: <br/> <input type="text" name="kurs" value="1.10"/> ($ / &euro;)

4 <br/>

5 Betrag: <br/> <input type="text" name="betrag"/>

6 Zielwaehrung:

7 <select name="zielwaehrung">

8 <option value="euro" selected="selected">&euro;</option>

9 <option value="dollar">$</option>

10 </select>

11 <br/>

1 Oft wird auch einfach nur if($_POST) abgefragt, was bei den aktuellen PHP-Versionen zwar dieselbe Wirkunghat, aber strenggenommen eine ungenaue Bedingung ist und von der technischen Implementierung eines Arraysabhängt.

Page 91: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 91

12 <input type="submit" value="Abschicken"/>

13 </form>

14

15 <?php

16 if (!empty($_POST)) { // Gibt es Daten ueber POST?

17 $kurs = $_POST['kurs'];

18 if ($_POST['zielwaehrung'] === "dollar") {

19 $zielbetrag = round( $kurs * $_POST['betrag'], 2);

20 $zielsymbol = "\$";

21 $symbol = "&euro;";

22 } else if ($_POST['zielwaehrung'] === "euro" ) {

23 $zielbetrag = round( (1/$kurs) * $_POST['betrag'], 2);

24 $symbol = "\$";

25 $zielsymbol = "&euro;";

26 }

27 echo "$_POST[betrag] $symbol entsprechen $zielbetrag $zielsymbol";

28 }

29 ?>

Neu für uns ist die elegante Möglichkeit, den Dateinamen des ausgeführten Skripts nicht alsKonstante einzugeben (wie "./division.php" im obigen Beispiel), sondern dynamisch ermit-teln zu lassen. Das geschieht mit einer weiteren superglobalen Variablen, $_SERVER?. Das istein Array und enthält recht viele Informationen zur Anfrage, zum Skript, zu den Pfaden und zuden Headern. Den Pfad des PHP-Skriptes ermittelt man dabei, indem man den Array-EintragPHP_SELF aus $_SERVER in eckigen Klammern aufruft,

$_SERVER[’PHP_SELF’]

Je nach Einstellung des Webservers kann es in dieser Konstellation zu Fehlermeldungen kom-men, wenn man die Anführungszeichen ’...’ weglässt. Daher ist die Version wie angezeigt mitden einfachen Anführungszeichen empfohlen. Die wichtigsten Array-Einträge von $_SERVER

sind:

• HTTP_HOST: Server-URL, z.B. haegar.fh-swf.de

• HTTP_USER_AGENT: Informationen zum anfragenden Browser, z.B. Mozilla/4.0 ...

• PHP_SELF: Der Dateiname des aktuell ausgeführten PHP-Skripts relativ zum Homever-zeichnis der Website, z.B. /php/euro.php

• REMOTE_ADDR: IP-Adresse der Anfrage, z.B. 193.132.49.193

• REQUEST_METHOD: Methode der Anfrage, z.B. POST

• SERVER_ADDR: IP-Adresse des Webservers, z.B. 194.94.2.20

• SERVER_PORT: Port der Anfrage, normalerweise 80 (http) bzw. 443 (https)

• SERVER_SOFTWARE: verwendete Webserver-Software, z.B. Apache/1.3.27 (Unix)

Page 92: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

92 Andreas de Vries

8.3 Eingabe und formatierte Ausgabe von KommazahlenKommazahlen haben bei Ein- und Ausgaben zweierlei Arten von Problemen zur Folge. Ei-nerseits ist ihr internes Datenformat, wie in allen Programmiersprachen, mit einem Punkt alsBruchtrennzeichen, also 3.1415, aber die Eingabe von Kommazahlen geschieht oft mit demKomma. Andererseits sollen sie oft entsprechend mit Komma ausgegeben werden, zusätzlichaber auch mit einer festen Nachkommastellen, beispielsweise bei Geldbeträgen mit 2 Nach-kommastellen, bei großen Beträgen mit dem Punkt oder Leerzeichen als Tausendertrenner.

Zur Konvertierung einer Float-Zahl, die mit einem Komma eingegeben wurde, verwendetman zweckmäßigerweise die Stringfunktion str_replace

string str_replace( mixed nadel, mixed ersatz, mixed heuhaufen )

Die Eingabeparameter sind Strings oder Arrays, wobei darauf zu achten ist, dass nadel undersatz gleiche Struktur haben. Für Strings ist der erste Parameter der zu ersetzende Teilstring,der zweite die stattdessen erwünschte Ersetzung, und der dritte der String, in dem ersetzt wer-den soll. Es werden alle Vorkommen von nadel in heuhaufen durch ersatz ersetzt. So kannbeispielweise ein eingegebenes Komma in einer Zahl zu einem Punkt gewandelt werden:

$x = str_replace(",", ".", "3,1415") // ergibt $x = 3.1415

Ob der Anwender jedoch überhaupt eine Zahl eingegeben hat, kann diese Funktion natürlichnicht prüfen, das kann nur is_numeric. Die Variante mit Arrays al Eingabeparameter kann dazudienen, mit nur einem Aufruf alle Eingabefelder zu verändern:

$nadeln = array(",", " ");

$ersatz = array(".", "_");

$_POST = str_replace($nadeln, $ersatz, $_POST);

Dabei sollten die zu ersetzenden Strings in dem $nadeln-Array in entsprechender Reihenfolgemit den ersetzenden Strings in $ersatz stehen. Auf diese Weise wird in jedem Eintrag von$_POST jedes Komma durch einen Punkt und jedes Leerzeichen durch einen Unterstrich ersetzt.

Zur formatierten Ausgabe von Kommazahlen stellt PHP die Funktion number_format zurVerfügung,

string number_format( float x, int stellen, string dezimaltrenner, string tausendtrenner )

Der erste Parameter x ist die zu formatierende Kommazahl, danach kommt als int die Anzahlder Nachkommastellen, dann jeweils als String das Dezimal- und das Tausendertrennzeichen.Beispielsweise ergibt

$x = 3.1415;

number_format($x, 3, ",", "."); // ergibt: "3,142"

8.4 Zusammenfassung• Benutzer-Eingaben können nur über ein HTML-Formular erfolgen und mit den superglo-

balen Variablen $_GET und $_POST ermittelt werden, abhängig von der Aktionsmethodedes Formulars.

• Dabei wird der Wert eines Input-Feldes durch Anhängen seines Namens in eckigen Klam-mern an die Variable abgegriffen.

Page 93: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 93

• Man braucht nicht unbedingt zwei Dateien (eine HTML-Datei für das Formular und einePHP-Datei für die Verarbeitung der Eingabedaten), sondern kann sie in einer einzigenPHP-Datei zusammenfassen. Allerdings muss man dazu geeignete Einträge des $_GET

bzw. des $_POST-Arrays abfragen, um zu entscheiden, ob das Skript erstmalig aufgerufenwurde oder ob Eingabedaten zur Verarbeitung übermittelt wurden.

• Um sich den aktuellen Namen des Skripts für diesen Fall automatisch in das action-Attribut des Eingabeformulars schreiben zu lassen, kann man den Wert von

$_SERVER["PHP_SELF"]

verwenden.

Page 94: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

9Cookies

Kapitelübersicht9.1 Cookies und HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94

9.1.1 Spezifikation von HTTP-Cookies . . . . . . . . . . . . . . . . . . . . . . . . 959.2 Cookies in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

9.1 Cookies und HTTP

Ein Cookie (Keks, Plätzchen) bzw. Magic Cookie ist eine kleine Datei, üblicherweise ASCII-Text, mit der ein Programm Daten seines aktuellen Zustands auf einem anderen Rechner spei-chert, um diesen Zustand bei einen späteren Aufruf wiederherstellen zu können. Mit den ge-speicherten Daten des Cookies kann nur das Programm etwas anfangen, das es gesetzt hat. Mankann ein Cookie vergleichen mit der Garderobenmarke einer öffentlichen Garderobe in Muse-en, Theatern oder Konzertsäälen, das ein Besucher bei der Abgabe seines Mantels erhält. Mitder Information auf der Marke kann nur das Garderobenpersonal etwas anfangen, am Ende desBesuchs kann es damit den korrekten Mantel zurück geben.

Entsprechend ist ein HTTP-Cookie ein Cookie, das der Webserver nach einem Aufruf ei-ner Webseite als Schlüssel-Wert-Paar name=content durch den Browser auf dem Clientrechnerspeichern lässt und das der Browser bei einem späteren HTTP-Request an den Server sendet.Der prinzipielle Ablauf des Setzens und Übermittelns eines Cookies ist in Abbildung 9.1 sche-

Browser Server

<html>......

Browser Server

x=1<html>......

Browser Server

x=1<html>......

1. Aufruf

Set-Cookie

x=1

2. Aufrufx=1

Abbildung 9.1: Prinzipieller Ablauf einer Cookie-Speicherung auf dem Browser: Nach ersten Aufruf einergeeignet programmierten Webseite speichert die HTTP-Response ein Cookie im Browser, hier x=1. Bei einemspäteren Aufruf der Seite wird das Cookie dann zum Server übertragen.

matisch skizziert.So kann ein HTTP-Cookie unter Anderem dazu dienen, dem Anwender eine Sitzung (Ses-

sion) zu ermöglichen (siehe S. 98). Prinzipiell können Cookies jedoch auch dazu verwendet

94

Page 95: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 95

werden, ein Profil des Internetverhaltens eines Anwenders zu bestimmen. So erstellen beispiels-weise Google und Facebook individuelle Identitätsnummern (PREF oder datr, siehe Abbildung

Name: PREF

Content: ID=bba15bb608d9fb3c:U=721091ae03c13bd6:FF=0:

LD=de:TM=1398977134:LM=1420280903:S=LfdiR9cwQus_J4k7

Domain: .google.de

Pfad: /

Senden für: Jede Verbindungsart

Für Skript zugänglich: Ja

Erstellt: Samstag, 3. Januar 2015 11:28:23

Läuft ab: Montag, 2. Januar 2017 11:28:23

Abbildung 9.2: Cookies von Facebook und Google, im Firefox (links) und im Chrome (rechts). Die Cookiedatensind in beiden Browsern über (Erweiterte) Einstellungen→ Datenschutz einsehbar.

9.2), die bei jedem Aufruf des jeweiligen Servers übermittelt werden und somit dort eine ein-deutige Spur der aufgerufenen Seiten über die Zeit hinterlassen.

Die Übermittlung von Cookiedaten an den Webserver geschieht ohne die explizite Betä-tigung des Anwenders, allerdings werden Cookies generell vom Browser verwaltet. So sindCookies nicht versteckt oder geheim, sondern sie können vom Anwender über seinen Brow-ser jederzeit eingesehen und auch gelöscht werden (Abbildung 9.2). Auch kann in den Da-tenschutzeinstellungen des Browsers das Speichern von Cookies teilweise oder komplett ab-geschaltet werden. Das Verhalten von Google und Facebook ist demnach laut der aktuellenRechtsprechung in Europa und den USA nicht rechtswidrig.

9.1.1 Spezifikation von HTTP-Cookies„An HTTP cookie is opaque data that can be assigned by the origin server to a user agent byincluding it within a Set-Cookie response header field, with the intention being that the useragent should include the same cookie on all future requests to that server until it is replacedor expires.“ [3, §6.3.4.2] Gemäß RFC 6265 (http://tools.ietf.org/html/rfc6265) der IETFenthält ein Cookie Text einer Länge von maximal 4 Kilobyte (4096 Byte) und besteht aus ei-nem Namen und Attributen, also Schlüssel-Wert-Paaren. Bei der Definition eines Cookies mussmindestens ein Attribut angegeben werden.

"Set-Cookie: Name=" Wert (";" key "=" value)+

Name und Wert sind Folgen von ASCII-Zeichen, wobei einige Sonderzeichen ausgeschlossensind. Die Syntax von Name verwendet einen eingeschränkten Zeichensatz, wie er auch bei an-deren HTTP-Kopfzeilen gemäß RFC 2616 verwendet wird. Für Wert sind Semikolon, Komma,Leerraum-Zeichen und Backslash als Zeichen ausgeschlossen. Um beliebige Daten als Cookie-Wert zu speichern, kann eine Kodierung wie Base64 oder die URL-Kodierung mit %xx ver-wendet werden. Im linken Beispiel in Abbildung 9.2 hat der Domainserver facebook.com zurDefinition des Cookies den folgenden HTTP-Header gesendet:

Set-Cookie: Name=datr;Content=6ccVVW4MOX5pBSx4UPgR-0ZO;Domain=facebook.com;

Path=/;Expires=Sun, 26-Mar-2017 23:13:13 CEST

Daraufhin hat der Browser das Cookie lokal gespeichert.Das Attribut HttpOnly soll den Zugriff auf Cookies mittels JavaScript verhindern. Dies stellt

einen möglichen Schutz gegenüber XSS dar, sofern der jeweils genutzte Browser dieses Attributunterstützt.

Page 96: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

96 Andreas de Vries

Der Browser Firefox stellt Add-On zum Editieren von Cookies bereit, beispielsweise Coo-kies Manager+: https://addons.mozilla.org/de/firefox/addon/92079

9.2 Cookies in PHPCookies werden in PHP über das superglobale assoziative Array $_COOKIE implementiert. EinCookie wird mit der Funktion

setcookie(Name,Wert,Verfallszeit,Pfad,Domäne,https,httponly)

gesetzt, wobei die ersten beiden und der vierte Parameter Strings sind und nur der erste ob-ligatorisch ist. Name und Wert bezeichnen hier den Inhalt des Cookies, Verfallszeit ist einUNIX-Zeitstempel, Pfad und Domain bestimmen den Gültigkeitsbereich des Cookies, (stan-dardmäßig wird der aufgerufene URI verwendet), https ist ein Boole’scher Wert, der bei trueeine HTTPS-Verbindung erfordert, und httponly ist ein Boole’scher Wert, der bei true nur überdas HTTP(S)-Protokoll ausgelesen wird und nicht beispielsweise per JavaScript. Eine möglicheWertbelegung aller Parameter ist wie folgt:

setcookie("Sprache", "englisch", time()+3600, "", "", false, true);

Hier bewirken die leeren Strings als Pfad und Domain, dass der aufgerufene URI (Subdo-mäne und Pfad) als für das Cookie gültig verwendet wird. Mit einer Low-Level-Domain wieexample.com und dem Pfad "/" wäre das Cookie für alle Verzeichnisse aller Subdomänen gül-tig. In Listing 9.1 wird das Setzen und das Auslesen von Cookies an einem einfachen Beispielgezeigt.

Listing 9.1: Cookies setzen und auslesen1 <?php

2 setcookie("Autor", "de Vries");

3 setcookie("Titel", "WebTech");

4

5 if (isset($_COOKIE['Autor'])) {

6 echo $_COOKIE['Autor'] . ": " . $_COOKIE['Titel'];

7 } else {

8 echo " -- kein Cookie! --";

9 }

10 ?>

Es ist bei der Programmierung von Cookies sehr hilfreich, sich die jeweils aktuellen Werte derexistierenden Cookies mit den Anweisungen

echo "<br/>\$_COOKIE: <pre>"; print_r($_COOKIE); echo "</pre>";

am Ende des PHP-Skripts anzeigen zu lassen.

Wie löscht man ein Cookie?

Das Löschen von Cookies ist in PHP grundsätzlich nicht möglich. Die Ursache ist, dass PHP jaauf dem Server läuft, das Cookie aber auf dem Browser gespeichert ist. Durch den in Abbildung9.1 skizzierten Mechanismus kann man mit PHP allerdings ein eventuell existierendes Cookieauf dem Browser überschreiben, indem eines mit gleichem Namen gesetzt wird. Damit hat manes eigentlich zwar nicht gelöscht; setzt man allerdings die Verfallszeit des neuen Cookies aufirgendeinen positiven Wert echt kleiner die aktuelle (Browser-) Zeit, so entfernt der Browser

Page 97: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 97

es augenblicklich. Möchten wir beispielsweise das Cookie "test_cookie" auf dem Browser„löschen“, so erreichen wir dies mit dem Befehl

setcookie("test_cookie", "Stirb", 1);

Hier wurde die Verfallszeit auf den 1.1.1970 um 0 Uhr und eine Sekunde gesetzt. Damit sollteein Browser in jeder beliebigen Zeitzone der Welt die Verfallszeit des Cookies in der Vergan-genheit sehen und es daher sofort löschen.

Page 98: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

10Sitzungen (Sessions)

Kapitelübersicht10.1 Eigenschaften von Sitzungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9810.2 Sitzungen in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9910.3 Sitzungen ohne Cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10010.4 Sicherheitsapekte: Erneuerung der Session-ID . . . . . . . . . . . . . . . . . . . . . . 10010.5 Gegenüberstellung Cookies und Sessions . . . . . . . . . . . . . . . . . . . . . . . . 101

10.1 Eigenschaften von SitzungenEine Session oder Sitzung bezeichnet in der Informatik eine stehende Verbindung zwischenzwei oder mehreren Kommunikationspartnern. In einem Client-Server-System besteht eine Sit-zung üblicherweise zwischen einem Client und einem Server, also im Internet zwischen einemBrowser und einem Webserver. Der Anfang einer Sitzung geschieht dabei über ein explizitesLogin des Clients oder einfach mit dem Aufruf einer Seite. Während der Sitzung können Infor-

offenöffnen schließen

senden

Abbildung 10.1: Zustandsdiagramm einer Sitzung.

mationen zwischen den Kommunikationspartnern übermittelt werden. Eine Sitzung kann durcheine vorgegebene maximale Sitzungsdauer zeitlich begrenzt sein, wird üblicherweise aber voneinem der Kommunikationspartner beendet, beispielsweise durch einen Logout. Ein expliziterLogout einer Browsersitzung geht dabei meist vom Client aus, bei zeitlich begrenzten Sitzungenoder im Fehlerfall auch vom Server.

Da im Web eine stehende Verbindung über das zustandslose Protokoll HTTP nicht möglichist (Abbildung 10.2), ist eine Sitzung hier eine Verbindung aus mehreren logisch zusammen-gehörenden Aufrufen (HTTP-Requests) und muss in einer auf HTTP basierenden Anwendungimplementiert werden, also über der Anwendungsschicht des Protokollstacks. Die für die Sit-zung und deren jeweiligen Zustand notwendigen Daten müssen dabei Client und Server zu

98

Page 99: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 99

HTTP(S) −→ zustandslos, d.h. keine Sitzungen möglichTCP −→ verbindungsorientiert, d.h. „kennt“ SitzungenIP −→ zustandslos, d.h. keine Sitzungen möglich...

Abbildung 10.2: Die TCP/IP-Familie und Sitzungen, vgl. §1.6 ab Seite 13.

jedem Zeitpunkt bekannt sein. Ganz grundsätzlich können dabei die Sitzungsdaten vom Clientallein, vom Server allein, oder koordiniert von beiden verwaltet werden. Wird die Verwaltungder Sitzungsdaten vollständig dem Client übertragen, der sie mit jedem Request über einen URImit den Nutzdaten übermittelt und abhängig von der Response verändert, so heißt die Imple-mentierung „REST-konform“.

Meist werden die Sitzungsdaten jedoch vom Webserver verwaltet und über eine eindeutigeSession-ID hergestellt, die entweder auf dem Client und dem Server koordiniert (meist mit Hilfevon Cookies) oder auf dem Server allein gespeichert sind. Beide Varianten der serverseitenSitzungsverwaltung bietet PHP standardmäßig an.

10.2 Sitzungen in PHPEine Sitzung in PHP wird mit dem Aufruf session_start() gestartet. In diesem Moment suchtPHP anhand der übermittelten Session-ID, ob die Sitzung existiert, oder erzeugt eine neue.Jede Sitzung hat in PHP einen Namen (PHPSESSID), eine eindeutige ID und das supergloba-le assoziative Array $_SESSION, in dem die weiteren von bisherigen Sitzungen erzeugten Sit-zungsdaten als Schlüssel-Wert-Paare gespeichert sind. Wie bei Cookies sollten Sie die Funkti-on session_start() aufrufen, bevor irgendein Text (noch nicht einmal ein Leerzeichen) an denBrowser versendet wird,1 auf jeden Fall aber vor der ersten Anweisung mit einem Abruf derSitzungsdaten. Nach Beginn einer Sitzung können Name und ID mit den Funktionen

session_name() und session_id()

ausgelesen werden. Eine Sitzung wird automatisch mit dem Schließen des Browserfensters be-endet. Die eigentlichen Nutzdaten der Sitzung können nun mit Hilfe des superglobalen Ar-rays $_SESSION erstellt und gespeichert werden, indem ein Schlüssel-Wert-Paar key="value" als$_SESSION["key"]="value" gespeichert wird,

key="value" ⇒ $_SESSION["key"]="value"

Ein einfaches Beispiel, das als Zustand einer Sitzung die Anzahl der bisherigen Aufrufe anzeigt,ist durch das folgende Beispielprogramm gegeben:

Listing 10.1: Eine Sitzung starten und Werte speichern1 <?php

2 session_start();

3

4 if (!isset($_SESSION["aufrufe"])) {

5 $_SESSION["aufrufe"] = 1; // erster Aufruf: Initialisierung

6 } else {

1 Zwar wird die gesamte Sitzungsverwaltung durch die PHP-Engine abgewickelt und kommt im Wesentlichenohne Modifikationen der HTTP-Header aus, jedoch wird je nach Variante zu Sitzungsbeginn ein Cookie gesendet.Je nach Servereinstellung kann das allerdings auch eine separat geschickte Response sein, womit die Position derFunktion im Skript dann wieder keine Rolle spielt.

Page 100: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

100 Andreas de Vries

7 $_SESSION["aufrufe"]++; // weitere Aufrude: hochzählen ...

8 }

9 echo "Sitzungszaehler: " . $_SESSION["aufrufe"];

10 echo "<br/>Sitzung: Name = ".session_name().", ID = ".session_id();

11 ?>

Die Zustandsvariable ist hier aufrufe und wird als Eintrag im Array $_SESSION gespeichert.

10.3 Sitzungen ohne CookiesFür den Fall, dass der Client keine Cookies zulässt, müssen die Sitzungsdaten über den URIübermittelt werden, also über GET, oder aber über POST. Das sind die einzigen (!) Möglich-keiten, Informationen an den Server zu übermitteln. Ein Beispiel ist das folgende Programm, indem die Session-ID dem Client per als Hyperlink mitgegeben wird und die der Anwender beimAnklicken übermittelt.

Listing 10.2: Eine Sitzung ohne Cookies1 <?php

2 ini_set("session.use_cookies", false);

3 ini_set("session.use_only_cookies", false);

4 session_start();

5

6 if (!isset($_SESSION["aufrufe"])) {

7 $_SESSION["aufrufe"] = 1;

8 } else {

9 $_SESSION["aufrufe"]++;

10 }

11 echo "Anzahl Aufrufe dieser Sitzung: " . $_SESSION["aufrufe"] . "<br/>";

12 echo "<a href='$_SERVER[PHP_SELF]?".session_name()."=".session_id().

13 "'>Sitzung aufrechterhalten</a>";

14 ?>

Mit den beiden Aufrufen der Funktion ini_set wird der PHP-Interpreter so konfiguriert, dasser keine Cookies zur Sitzungsdatenverwaltung verwendet. Zur Aufrechterhaltung der Sitzungmuss allerdings der Link angeklickt werden. (Zumindest beim zweiten Aufruf, danach könnteman die Reload-Funktion des Browsers nutzen, da der URI von da an die Session-ID enthält.)

10.4 Sicherheitsapekte: Erneuerung der Session-IDDa die Übermittlung einer Session-ID generell eine bekannte Sicherheitslücke darstellt, dieSession Fixation, sollte die Session-ID mit der Funktion

session_regenerate_id(true)

bei jedem Seitenaufruf stets neu generiert werden, so dass die Kenntnis der vorherigen Session-IDs für einen Angreifer wertlos werden.

Listing 10.3: Eine Sitzung ohne Cookies mit erneuerter Session-ID1 <?php

2 ini_set("session.use_cookies", false);

3 ini_set("session.use_only_cookies", false);

Page 101: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 101

4 session_start();

5 session_regenerate_id(true);

6

7 if (!isset($_SESSION["aufrufe"])) {

8 $_SESSION["aufrufe"] = 1;

9 } else {

10 $_SESSION["aufrufe"]++;

11 }

12 echo "Anzahl Aufrufe dieser Sitzung: " . $_SESSION["aufrufe"] . "<br/>";

13 echo "<a href='$_SERVER[PHP_SELF]?".session_name()."=".session_id().

14 "'>Sitzung aufrechterhalten</a>";

15 ?>

Allerdings büßt die Webanwendung durch diese Maßnahme etwas an Bedienbarkeit ein, da derBenutzer zur Aufrechterhaltung der Sitzung dann nicht den Zurück-Button seines Browsersverwenden darf, sondern nur noch über Hyperlinks oder Submit-Buttons.

10.5 Gegenüberstellung Cookies und Sessions

Zwar gibt es gewisse Gemeinsamkeiten können Sessions auf Cookies basieren, dennoch sindihr Funktionsprinzip und ihre Funktionalität ganz verschieden. Gemeinsam ist Cookies undSessions in PHP, dass die Nutzdaten, also die Daten, die nicht zum notwendigen technischenOverhead gehören, in einer superglobalen Variablen gespeichert werden. Bei Cookies ist diesdas Array $_COOKIES, bei Sessions das Array $_SESSION. Gemeinsam ist beiden ebenso, dass dieVerwaltung der Daten wie Lesen, Ändern oder Löschen durch den Server geschieht.

Der wesentliche Unterschied zwischen Cookies und Sessions allerdings ist der Speicherortder Nutzdaten. Die Daten von Cookies werden bei dem Browser persistent (d.h. hier über dieLaufzeit des PHP-Skripts hinaus) gespeichert, die Nutzdaten von Sessions dagegen auf demServer. Dieser Sachverhalt wird in Abbildung 10.3 skizziert. Daraus ergeben sich zwangsläufig

Cookies Sessions

Browser Server

x=1

<?php......?>

Browser Server

x=1

<?php$_COOKIE["x"]...?>

Browser Server<?php$_SESSION["x"]=1;...?>

setcookie("x","1")

Aufrufx=1

Aufruf

PHPSESSID=...

PHPSESSID=...

Abbildung 10.3: Die Nutzdaten werden bei Cookies im Browser gespeichert, bei Sessions auf dem Server.

alle weiteren Unterschiede zwischen Cookies und Sessions in PHP. So wird bei Cookies eineVariable, beispielsweise x, durch setcookies("x", 1, ...) mit einem Wert (hier 1) initialisiert,bei Sessions dagegen durch Einführung einer neuen Sessionvariablen mit $_SESSION["x"]=1.Bei Cookies kann PHP über das Array $_COOKIE die aktuell übertragenen Cookies nur auslesen,die originalen Cookiedaten auf dem Browser aber nur durch ein neues Setzen mit setcookieändern. Das ist bei Sessionvariablen ganz anders, sie können – wie andere Variablen in PHPauch – einfach geändert werden, z.B. mit $_SESSION["x"]++. Ein weiterer Unterschied ist dieVerfallszeit der Nutzdaten: Während sie bei Cookies frei einstellbar ist und mehrere Jahre indie Zukunft reichen kann, ist sie bei Sessions auf die Dauer der aktuellen Browsersitzung be-schränkt, endet also mit Schließung des Browserfensters. Zusammengefasst erhalten wir diefolgende Gegenüberstellung der Eigenschaften von Cookies und Sessions in PHP.

Page 102: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

102 Andreas de Vries

Eigenschaft Cookies SessionsPHP-Variable $_COOKIE $_SESSION

Datenverwaltung Server ServerSpeicherort (Nutzdaten) Browser ServerVerfallszeit (Nutzdaten) frei einstellbar Ende BrowsersitzungDateninitialisierung x=1 setcookie("x", 1, ...); $_SESSION["x"] = 1

Datenänderung x++ setcookie("x", $_COOKIE["x"]+1, ...); $_SESSION["x"]++;

Page 103: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

11Objekte

Kapitelübersicht11.1 Das Konzept eines Objekts in der Programmierung . . . . . . . . . . . . . . . . . . . 10311.2 Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10511.3 Traits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10611.4 Vergleich von Objekten und Arrays in PHP . . . . . . . . . . . . . . . . . . . . . . . 107

11.1 Das Konzept eines Objekts in der ProgrammierungEin Objekt im Sinne der Objektorientierung ist eine programmiertechnische Speichereinheitvon zusammengehörigen und strukturierten Daten sowie von auf sie operierenden Funktionen.Die Daten heißen dabei Attribute, die Funktionen Objektmethoden oder nur kur Methoden.In der objektorientierten Programmierung ist die grundlegende Programmiereinheit dafür dieKlasse, die den Datentyp oder Bauplan der aus ihr erzeugten Objekte darstellt und die Attri-bute und Objektmethoden definiert. Für die Darstellung oder den Entwurf einer Klasse ist einKlassendiagramm sehr nützlich, das in drei abgeteilten Bereichen eines Rechtecks den Klas-sennamen, die Attribute und die Methoden auflistet:

Klasseattribute. . .methoden(). . .

In Objekten können somit komplexe Einheiten von Daten und Funktionen programmiert undfür Andere zur Wiederverwendung verfügbar gemacht werden. So sind viele PHP-Frameworksobjektorientiert programmiert und können nur als Objekte verwendet werden, so zum Bei-spiel die Template-Engine Smarty (http://smarty.net) oder die PDF-Bibliothek FPDF (http://fpdf.org).

Die Syntax von PHP zur Programmierung von Klassen und Objekten ist ähnlich wie in Javaoder C++, allerdings gibt es ein paar wesentliche Unterschiede, beispielsweise:

• Klassen dürfen in PHP nicht public sein.

103

Page 104: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

104 Andreas de Vries

• Attribute müssen einen Modifizierer haben, also private, protected oder public; emp-fohlen ist protected, wenn das Attribut vererbbar sein soll, ansonsten private. (Einpublic Attribut widerspricht zwar der Idee der Datenkapselung, also einer der Grund-ideen der Objektorientierung, wird aber oft in Objekten der API oder der Frameworksverwendet.)

• Methoden und Konstruktoren sind Funktionen.

• Es kann maximal einen Konstruktor geben, und er muss dann __construct(...) heißen(egal wie die Klasse heißt).

• Die Referenzierung auf Attribute und Objektmethoden muss mit dem Pfeiloperator ->

geschehen (Der Punkt ist in PHP ja schon für die Stringkonketanation vorgesehen!)

• Demgegenüber müssen statische Attribute (Konstanten) oder Methoden (Klassenfunktio-nen) mit dem Doppel-Doppelpunktoperator :: referenziert werden.

• Attribute müssen in Objektmethoden mit $this->attribut referenziert werden;

• public Methoden werden von außen mit $objekt->methode(...) aufgerufen, ebenso public

Attribute.

Das folgende Programm möge die Syntax für Klassen und Objekte erläutern:

Listing 11.1: Die Klasse Gasthaus1 <!DOCTYPE HTML><html lang="de-DE"><head><meta charset="UTF-8"></head><body>

2 <!-- Gasthaus.php -->

3 <?php

4 class Gasthaus {

5 protected $name;

6 protected $betten;

7 protected $frei;

8

9 public function __construct($name, $betten = 2) {

10 $this->name = $name;

11 $this->betten = $betten;

12 $this->frei = $betten;

13 }

14 public function __toString() {

15 return "$this->name, $this->frei freie Betten";

16 }

17 public function buchen($betten) {

18 if ($this->frei >= $betten) {

19 $this->frei -= $betten;

20 return "Buchung von $betten Betten in $this->name bestätigt!";

21 } else {

22 return "Nicht genügend Betten frei!";

23 }

24 }

25 }

26

27 $herberge = new Gasthaus("Jugendherberge A", 250);

Page 105: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 105

28 $pension = new Gasthaus("Pension B");

29 echo "$herberge,<br/> $pension<br/>";

30 echo $herberge->buchen(2);

31 echo "<br/>$herberge,<br/> $pension";

32 ?>

33 </body></html>

Das Klassendiagramm dieser Klasse lässt sich also wie folgt darstellen:

Gasthausnamebettenfrei__toString()buchen(integer)

Die Ausgabe des Programms lautet entsprechend:

Jugendherberge A, 250 freie Betten,

Pension B, 2 freie Betten

Buchung von 2 Betten in Jugendherberge A bestätigt!

Jugendherberge A, 248 freie Betten,

Pension B, 2 freie Betten

11.2 VererbungEin wichtiges Programmierkonzept der Objektorientierung ist die Vererbung. Durch Vererbungwird eine Basisklasse (Superklasse) erweitert um zusätzliche Attribute und Funktionen.

Listing 11.2: Die Klasse Hotel1 <!DOCTYPE HTML><html lang="de-DE"><head><meta charset="UTF-8"></head><body>

2 <!-- Hotel.php -->

3 <?php

4 require_once("Gasthaus.php");

5 class Hotel extends Gasthaus {

6 protected $zimmer;

7

8 public function __construct($name, $zimmer) {

9 parent::__construct($name, 2*$zimmer);

10 $this->zimmer = $zimmer;

11 $this->frei = $zimmer;

12 }

13 public function __toString() {

14 return "$this->name, $this->frei freie Zimmer";

15 }

16 public function buchen($zimmer) {

17 if ($this->frei >= $zimmer) {

18 $this->frei -= $zimmer;

19 return "Buchung von $zimmer Zimmern in $this->name bestätigt!";

20 } else {

21 return "Nicht genügend Zimmer frei!";

Page 106: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

106 Andreas de Vries

22 }

23 }

24 }

25

26 $hotel = new Hotel("Hotel C", 450);

27 $pension = new Gasthaus("Pension D");

28 echo "<br/><br/>$hotel,<br/> $pension<br/>";

29 echo $hotel->buchen(1) . "<br/>";

30 echo "$hotel,<br/> $pension";

31 ?>

32 </body></html>

Die Ausgabe dieses Programms lautet:

Hotel C, 450 freie Zimmer,

Pension D, 2 freie Betten

Buchung von 1 Zimmern in Hotel C bestätigt!

Hotel C, 449 freie Zimmer,

Pension D, 2 freie Betten

11.3 TraitsÄhnlich wie eine Klasse ist ein Trait eine benannte Gruppe von Methoden, Konstanten undKlassenvariablen. Anders als von einer Klasse kann von einem Trait jedoch kein Objekt in-stanziiert werden, und es können keine Subklassen gebildet werden. Traits werden in PHP ver-wendet, um Namensräume für statische Methoden und Konstanten zu erstellen oder Mixins zuprogrammieren, d.h. Einheiten von Objektmethoden und Objektvariablen, die man mit use ineine Klasse „hineinmischen“ (mix in) kann, so dass deren Objekte diese Methoden auch ver-wenden können:

Listing 11.3: Ein Trait1 <!-- Traits.php -->

2 <?php

3 trait Mathematik {

4 public function mehrwertsteuer($brutto) {

5 return 0.19/1.19 * $brutto;

6 }

7 }

8

9 class Rechnung {

10 use Mathematik;

11 }

12

13 $rechnung = new Rechnung();

14 echo $rechnung->mehrwertsteuer(29.90);

15 ?>

Prinzipiell ist damit in PHP die Mehrfachvererbung von Verhalten möglich, allerdings bemerktder PHP-Interpreter eine solche Mehrfachvererbung und verlangt die explizite Angabe der zuverwendenden Methode [9, §9.14.2].

Page 107: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 107

11.4 Vergleich von Objekten und Arrays in PHPIn Bezug auf die Datenhaltung haben Objekte gewisse Ähnlichkeit mit assoziativen Arrays.Betrachten wir dazu die Klasse Gasthof von oben ohne die Methoden:

Gasthausnamebettenfrei

Mit der Klasse

class Gasthaus {

public $name;

public $betten;

public $frei;

public function __construct($name, $betten = 2) {

$this->name = $name;

$this->betten = $betten;

$this->frei = $betten;

}

}

können wir damit zwei Objekte $_herberge und $_pension erzeugen:

$herberge = new Gasthaus("Jugendherberge A", 250);

$pension = new Gasthaus("Pension B");

Äquivalente Dateneinheiten könnten wir aber auch mit Arrays erstellen:

$herberge = array("name" => "Jugendherberge A", "betten" => 250, "frei" => 250);

$pension = array("name" => "Pension B", "betten" => 2, "frei" => 2);

Auf die Attributwerte können wir dann jeweils wie folgt zugreifen:

Array Objekt$herberge["name"] $herberge->name

$herberge["betten"] $herberge->betten

$herberge["frei"] $herberge->frei

(11.1)

Solange man also die Objektmethoden außer Acht lässt, unterschieden sich Objekte in PHPkaum von assoziativen Arrays. Aber natürlich sind genau die Objektmethoden einer der großenVorteile der Objektorientierung: Hier können prinzipiell komplexe Abläufe und Algorithmenauf Werte von Attributen mit einem einfachen Aufruf ausgeführt werden (so wie hier der Kon-struktor), während sie für ein Array „von außen“ ausgeführt werden müssen. Es ist also wenigerdie rein technische Datenspeicherung, die Objekte und Arrays unterscheidet, als vielmehr dieSicht auf Daten.

Page 108: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

12Datenbankzugriffe übers Web: HTML &

PHP & SQL

Kapitelübersicht12.1 Zugriff von PHP auf MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

12.1.1 Verbindung zum Datenbanksystem: new mysqli(...) . . . . . . . . . . . . . . 11012.1.2 Abfragen mit $mysqli->query . . . . . . . . . . . . . . . . . . . . . . . . . . 11212.1.3 Übernahme der Daten nach PHP . . . . . . . . . . . . . . . . . . . . . . . . . 113

12.2 Anzeigen von Daten im Browser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11412.2.1 Die wesentlichen Schritte des PHP-Skripts . . . . . . . . . . . . . . . . . . . 11512.2.2 Formatierte Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

12.3 Informationen über gerade abgesetzte SQL-Befehle . . . . . . . . . . . . . . . . . . . 11612.4 SQL Injection entschärfen mit escape_string . . . . . . . . . . . . . . . . . . . . . . 11712.5 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

In diesem Kapitel werden wir die verschiedenen Fäden, die wir in den vergangenen Kapitelngesponnen haben, zu einer Gesamtheit zusammen knüpfen. Wir haben PHP als eine Program-miersprache kennen gelernt, die auf einem Webserver läuft und dessen Ressourcen nutzen kann.Als Modul des Webservers kann PHP insbesondere die Schnittstellen zu einem Client des Web-servers nutzen, d.h. einem Browser. Das PHP-Modul muss also PHP-Code als HTML-Code

Abbildung 12.1: Die drei Schichten einer datenbankbasierten Webanwendung

108

Page 109: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 109

ausgeben und durch den Webserver an den Browser senden.Nun wollen wir unser HTML-PHP-System erweitern und eine relationale Datenbank an-

binden. Die Programmiersprache für Zugriffe auf eine solche Datenbank ist SQL. Jetzt kehrensich die Rollen in unserem System gewissermaßen um, PHP ist nunmehr der Client für denDatenbankserver, der auf SQL-Befehle reagiert und mit Daten antwortet.

echo

Browser

$mysqli−>querySQL (als String)

HTML (als String)

PHPMySQL

Datenbank

Abbildung 12.2: PHP als Schnittstelle, die über reinen Text kommuniziert

Somit stellt PHP eine Schnittstelle zwischen Browser (WebClient) und einer MySQL Daten-bank (DB-Server) dar. In einem PHP-Skript kann natürlich weder HTML- noch SQL-Code ver-arbeitet werden. Beides kann nur dynamisch als String erzeugt werden und entweder per echoan den Browser oder, nach geeigneteter Vorbereitung, per $mysqli->query() an die Datenbankgeschickt werden.

12.1 Zugriff von PHP auf MySQLUm auf Daten einer allgemeinen Datenbank zuzugreifen, also nicht nur auf eine lokale Da-tenbank wie Access, sondern auch einen Datenbankserver wie MariaDB, MySQL, Oracle oderMSSQL, benötigt man im Wesentlichen die folgenden Schritte.

1. Verbindung zur Datenbank eines Datenbankservers erstellen;

2. Abfrage (query) zur Datenbank per SQL absetzen;

3. Datensätze von Auswahlabfragen (result) aus der Datenbank in eine geeignete Daten-struktur von PHP umformen.

Für eine Webanwendung in PHP, die Zugriffe auf eine MySQL-Datenbank aus dem Web er-möglichen soll, müssen wir diese Schritte programmieren können. Dazu stehen in PHP Funk-tionen zur Verfügung, die wir im folgenden kennen lernen werden. Listen wir hier einmal dieSchritte für einen Datenzugriff auf und erwähnen die dazu verwendeten PHP-Funktionen; inden nächsten Abschnitten werden wir sie näher betrachten.

Aktionsschritt PHP-Anweisung1. Verbindung zur Datenbank erstel-

len$mysqli = new mysqli(...)

2. SQL-Abfrage zur Datenbank sen-den

$result = $mysqli->query(...)

3a. Abfrageergebnis als Objekt inPHP einlesen

$result->fetch_object()

3b. Abfrageergebnis als assoziativesArray in PHP einlesen

$result->fetch_assoc()

3c. Abfrageergebnis als numerischesArray in PHP einlesen

$result->fetch_row()

Page 110: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

110 Andreas de Vries

Die Schritte 3a, 3b und 3c der Ergebniseinlesung nach PHP sind hierbei als Alternativen anzu-sehen, sie unterscheiden sich lediglich in der Datenstruktur, in der die Datensätze der Ergebnis-menge der Datenbankabfrage in PHP gespeichert werden.

Hat man die Verbindung zu einer Datenbank eingerichtet, so hat man u.a. die folgendenAbfragefunktionen über SQL zur Verfügung:

1. Eintragen von Daten mit INSERT. Die Syntax dazu lautet:

INSERT INTO tabelle (spalte1, spalte2, ...)

VALUES ('wert1', 'wert2', ...)

oder

INSERT INTO tabelle SET

spalte1 = 'wert1',

spalte2 = 'wert2',

...

2. Ansehen gespeicherter Daten mit SELECT:

SELECT spalte_x, spalte_y FROM tabelle # WHERE bedingung ...

Will man alle Daten einer Tabelle erhalten, so kann man statt der einzelnen Spaltennamenauch einfach die Wildcard * angeben.

3. Ändern von gespeicherten Daten mit UPDATE:

UPDATE tabelle SET

spalte1 = 'neuerWert1',

spalte2 = 'neuerWert2',

...

WHERE Primärschlüssel = 'x'

4. Löschen gespeicherter Daten mit DELETE:

DELETE FROM tabelle WHERE bedingungen

(Achten Sie auf die WHERE-Klausel, sonst ist alles gelöscht . . . )

12.1.1 Verbindung zum Datenbanksystem: new mysqli(...)

Der Verbindungsaufbau zu einer einer Datenbank geschieht durch die Erzeugung eines mysqli-Objekts, $mysqli = new mysqli(...), eines Standardobjekts in PHP:

$mysqli = new mysqli("localhost", "user", "passwort", "db");

Der Konstruktor des PHP-Objekts mysqli erwartet vier Eingabeparameter:

1. Den Namen des Datenbankservers: Dies ist hier "localhost". Hiermit wird der Rech-ner, auf dem das PHP-Programm selber läuft, angesprochen. Alternativ kann hier dieIP-Adresse eines anderen Rechners stehen; allerdings muss das Serversystem dazu ent-sprechend konfiguriert sein.

2. Den Namen des Benutzers, hier "user". Hier kann der Name eines jeden beim Daten-bankserver registrierten Nutzers stehen.

Page 111: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 111

3. Das Passwort des Benutzers, hier: "passwort".

4. Den Namen der Datenbank, hier "db".

Optional kann als fünfter Parameter der Port des Datenbankservers angegeben werden, seinStandardwert ist 3306 und funktioniert dementsprechend bei den üblichen Datenbankinstalla-tionen.

Es ist zu empfehlen, zur besseren Übersicht und zur vereinfachten Einstellung bei etwaiggeänderten Datenbankzugriffen die Aufrufparameter in Variablen zu speichern:

$server = "localhost";

$user = "user";

$password = "passwort";

$database = "datenbank";

$mysqli = new mysqli($server, $user, $password, $database);

$mysqli->set_charset("utf8");

Die letzte Anweisung ist sehr ratsam und lässt die Datenbank Text in der UTF8-Kodierung zuspeichern. Natürlich muss dazu Text aus einem HTML-Formular, der über PHP in der Daten-bank gespeichert werden soll, dieselbe Kodierung haben, d.h. die Webseiten zur Eingabe solltenentsprechend das <meta>-Element

<meta charset="utf-8"/>;

enthalten.Um Fehler beim Zugriff ausgeben zu lassen, was gerade bei der Programmierung eines

Datenbankzugriffs sehr hilfreich sein kann, sollte man nach Erzeugung des mysqli-Objekts undvor Einstellung der Kodierung das Attribut $mysqli->connect_errno verwenden:

$server = "localhost";

$user = "user";

$password = "passwort";

$database = "datenbank";

$mysqli = new mysqli($server, $user, $password, $database);

if ($mysqli->connect_errno) {

echo "Fehler beim Zugriff auf MySQL: (" .

$mysqli->connect_errno . ") " . $mysqli->connect_error;

}

$mysqli->set_charset("utf8");

Das öffentliche Attribut $mysqli->connect_errno gibt die Fehlernummer der aktuellen Daten-bankverbindung an und ist null, wenn der Zugriff erfolgreich war; in der if-Anweisung wirddies von PHP als false betrachtet und die echo-Anweisung daher nicht ausgeführt. Ist jedoch einFehler aufgetreten, so ergibt in PHP die if-Anweisung true und das Attribut $mysqli->connect_errorenthält eine Beschreibung des eingetretenen Fehlers. (Eine solche Fehlerausgabe sollte man beiproduktiv eingesetzten und veröffentlichten Systemen selbstverständlich deaktivieren, denn eingutwilliger Anwender kann damit nichts anfangen, und ein böswilliger Hacker kann wertvol-le Informationen erlangen.) Weitere Hinweise und Informationen finden Sie auf php.net unterdem Stichwort mysqli.1

Eine weitere Empfehlung ist, die Konfigurationsdaten des Zugriffs auf den Datenbankserverin eine eigene Datei auszulagern, z.B. db_login.inc.php, und zu Beginn eines PHP-Skripts per

1 http://php.net/manual/de/mysqli.quickstart.connections.php [2016-11-11]

Page 112: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

112 Andreas de Vries

require_once einzulesen. So können mehrere PHP-Skripte die Einstellungen zentral einlesenund bei etwaigen Änderungen der Zugriffsparameter die aktuellen Werte erhalten, ohne dass sieselbst geändert werden müssen. Da meist verschiedene PHP-Skripte eines Webauftritts zwarauf denselben Datenbankserver zugreifen sollen, aber auf verschiedene Datenbanken, sollte inder Zugriffsdatei zentral eine Funktion definiert werden, die den Namen der Datenbank alsParameter erfordert und das mysqli-Objekt der Datenbankverbindung zurück gibt:

1 <!-- Dateiname: db_login.inc.php -->

2 <?php

3 /** Erstellt eine Datenbankverbindung mit zentralen

4 * Konfigurationsdaten des DB-Servers.

5 * @param $database die Datenbank

6 * @return mysqli-Objekt der Datenbankverbindung

7 */

8 function login($database) {

9 $server = "localhost";

10 $user = "user";

11 $password = "passwort";

12

13 $mysqli = new mysqli($server,$user,$password,$database);

14 if ($mysqli->connect_errno) {

15 echo "Keine DB-Verbindung: ({$mysqli->connect_errno}) "

16 . $mysqli->connect_error;

17 exit(); // beendet das Programm

18 }

19

20 $mysqli->set_charset("utf8");

21 return $mysqli;

22 }

23 ?>

Diese Funktion kann dann von einem beliebigen PHP-Skript importiert werden, um eine Da-tenbankverbindung zu erstellen:

require_once("db_login.inc.php");

$mysqli = login("AdressDB");

Danach ist bei erfolgreichem Zugriff auf den Datenbankserver und die Datenbank ein mysqli-Objekt über die Variable $mysqli verfügbar. Bei einem Verbindungsfehler allerdings wird hierwegen der Funktion exit das Skript sofort abgebrochen.

12.1.2 Abfragen mit $mysqli->queryMit der Objektmethode $mysqli->query wird ein SQL-Kommando an die Datenbank geschicktund dort ausgeführt. Die Methode erwartet als Eingabeparameter das SQL-Kommando, dasvom Datenbank-System ausgeführt werden soll, in Form eines Strings. Ein Beispiel für dasAbschicken einer SELECT-Anweisung:

$result = $mysqli->query("SELECT * FROM adressen");

Der SQL-Befehl selektiert alle Datensätze der Tabelle adressen. Natürlich ist der SQL-Befehlfür PHP lediglich ein String, also ohne weitere Bedeutung. Ähnlich wie PHP ein HTML-Dokument auch nur als einen String aufbaut und per echo an den Browser schickt, muss ein

Page 113: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 113

SQL-Befehl als String an die Datenbank geschickt werden. Genau das macht $mysql->query:es schickt die Abfrage an die Datenbank, die sie dort als SQL interpretiert und ausführt. DieErgebnismenge (result set) wird üblicherweise in einer Variablen $result gespeichert.

Eine weitere Variante, die oft in der Literatur oder in Programmbeispielen zu sehen ist, istdie Methode mysqli_query() nach dem „prozeduralen Stil“. Sie hat als obligatorischen Parae-ter eine gültige Datenbankverbindung und erlaubt damit den Zugriff auf mehrere Datenbankeninnerhalb eines PHP-Skripts, ohne sie immer wieder neu aufbauen zu müssen. Weitere Infor-mationen dazu siehe unter http://php.net/manual/en/mysqli.query.php.

12.1.3 Übernahme der Daten nach PHPEs gibt mehrere Objektmethoden der Ergebnismenge $result einer erfolgreichen Auswahlab-frage einer Datenbank, um auf deren Datensätze zuzugreifen. Die wichtigsten sind:

$result->fetch_object()

und

$result->fetch_assoc()

Die erste Methode liefert die Ergebnismenge der Datenbankabfrage als Objekt zurück, diezweite als assoziatives Array. Hierbei wird der jeweils nächste Datensatz der Ergebnismenge$result gelesen und in einem Objekt mit den Spalten als Attributnamen bzw. einem assoziati-ven Array mit den Bezeichnungen der Tabellenspalten als Schlüssel gespeichert.

Die beiden Methoden sind hierbei als Alternativen anzusehen. Ihre Wirkung ist fast gleichund am besten anhand eines einfachen Beispiels zu erklären: Hat man nach einer Datenbankab-frage eine Ergebnismenge $result mit der Spalte spalte und dem Eintrag $eintrag, so erzeugtdie Anweisung $result->fetch_object() je Datensatz ein Objekt

$wert = $a->spalte

Entsprechend erzeugt die Anweisung $result->fetch_assoc() je Datensatz ein assoziatives Ar-ray

$wert = $a["spalte"]

Wir werden im Folgenden oft die früher weit verbreitete Variante mit assoziativen Arrays ver-wenden, auch wenn die objektorientierte Variante eleganter und beim Programmieren leichterhinzuschreiben ist.

Eine weitere Möglichkeit der Konvertierung der Ergebnismenge einer Auswahlabfrage derDatenbank ist mit der Anweisung $result->fetch_row()

$result->fetch_row()

gegeben, die ein numerisches Array liefert, in dem jedoch die Spaltennamen der Datenbank-tabelle nicht mehr verfügbar sind. Der Zugriff auf die Datenbankinhalte geschieht hier überIndizes 0, 1, . . . . Die assoziative Variante bzw. die fetch_object-Methode sind flexibler, da sieauch nach späteren eventuellem Einfügen neuer Felder in die Datenbanktabelle korrekte Resul-tate liefern.

Um nach einem SELECT-Befehl die Ergebnismenge zu durchlaufen, kann man eine der fol-genden Schleifenkonstrukte verwenden:

while ($datensatz = $result->fetch_object()) {

$datensatz->spalte ... // $datensatz ist ein Objekt

}

Page 114: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

114 Andreas de Vries

oder

while ($datensatz = $result->fetch_assoc()) {

$datensatz["spalte"] ... // $datensatz ist ein assoz. Array

}

oder

while ($datensatz = $result->fetch_row()) {

$datensatz[0] ... // $datensatz ist ein numerisches Array

}

Bei allen Varianten wird jeweils der nächste Datensatz in der Ergebnismenge $result als Ob-jekt bzw. Array eingelesen, solange es einen solchen gibt. Nach dem letzten Datensatz liefertdie Zuweisung ein leeres Ergebnis, d.h. sie ist false, und die Schleife wird beendet. Ist dieErgebnismenge leer oder enthält sie eine Fehlermeldung, so wird die Schleife gar nicht erstbegonnen.

12.2 Anzeigen von Daten im BrowserDas folgende Programmbeispiel erweitert das obige Adressbeispiel, indem es die verfügbarenAdressen aus einer Datenbank liest und anzeigt. Voraussetzung ist, dass bereits eine Daten-bank mit einigen Einträgen existiert, siehe Abb. 12.3. Um den Inhalt der Datenbank als Tabelle

Abbildung 12.3: Die Struktur der Adressdatenbank (links) und einige Einträge (rechts), mit phpMyAdminbetrachtet.

im Browser darzustellen, muss also mit einem SELECT-Befehl als SQL-Statement auf die Da-tenbank zugegriffen werden, die Ergebnismenge mit $mysqli->fetch_assoc als Array in PHPtransformiert und in HTML als Tabelle erzeugt werden.

Wir werden zwei Versionen eines PHP-Skripts betrachten. Die erste zeigt den Datenbankin-halt einfach zeilenweise im Browser an und erläutert konkret die notwendigen Programmzeileneines allgemeinen PHP-Skripts zur Datenanzeige. Das zweite wird dann eine formatierte Anzei-ge in einer Tabelle vornehmen und die Feldnamen als Spaltenbezeichnung verwenden. Fernerwird die foreach-Schleife eingesetzt, um die Datensatzfelder automatisch zu durchlaufen.

Listing 12.1: Einträge einer Datenbank anzeigen1 <!-- Adressen aus DB. Dateiname: adresseDB.php -->

2 <?php

3 $mysqli = new mysqli("localhost", "user", "c5dDC8VJemscKPQS", "AdressDB");

4 if ($mysqli->connect_errno) {

5 echo "Failed to connect to MySQL: ({$mysqli->connect_errno}) $mysqli->connect_error";

6 }

Page 115: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 115

7 $result = $mysqli->query("SELECT * FROM adressen");

8 while ($adresse = $result->fetch_assoc()) {

9 echo "$adresse[name], $adresse[vorname], $adresse[email]<br/>";

10 }

11 ?>

12.2.1 Die wesentlichen Schritte des PHP-SkriptsSchauen wir uns die wesentlichen Programmschritte an, um den aktuellen Inhalt einer Daten-bank im Browser darzustellen. Zunächst wird die Verbindung zur Datenbank AdressDB auf demDatenbankserver localhost erstellt. Die if-Abfrage bewirkt hier, dass im Falle eines Fehlersbei der Verbindungserstellung eine Fehlermeldung erscheint. Als nächstes wird eine SQL-Anweisung, hier ein SELECT, an den Datenbankserver geschickt und das das Ergebnis in derVariable $result gespeichert. Somit enthält $result die vollständige Ergebnismenge der SQL-Anweisung. Die Ergebnismenge kann je nach Abfrage und Datenbank tausende von Einträgenenthalten, oder vielleicht leer sein, oder aber einen Fehlercode liefern. Die für die Anzeige derDatensätze aus der Datenbank nächste wesentliche Anweisung ist die folgende Schleife:

while ( $adresse = mysql_fetch_assoc($result) ) {

echo "$adresse[Name] ... <br/>";

}

Die while-Schleife wiederholt sich hier, solange noch ein nächster Datensatz in der Ergebnis-menge $result existiert. Falls nicht, so gibt die Anweisung in der while-Klammer nämlichfalse zurück, und der Schleifenrumpf wird nicht weiter ausgeführt.

Während eines Schleifendurchlaufs steht also in der Variablen $adresse ein bestimmter Da-tensatz aus der Datenbank als assoziatives Array, mit den Feldnamen der Datenbanktabelle alsSchlüssel und den Datenbankeinträgen des Datensatzes als Inhalte.

12.2.2 Formatierte AusgabeZum Anzeigen der Daten reichen die obigen Anweisungen völlig aus.

Beispiel 12.1. Formatierte Ausgabe von Adressen aus Datenbank �

1 <!-- Adressen aus DB. Dateiname: adresseDB1.php -->

2 <?php

3 $mysqli = new mysqli("localhost", "user", "c5dDC8VJemscKPQS", "AdressDB");

4 if ($mysqli->connect_errno) {

5 echo "Failed to connect to MySQL: ({$mysqli->connect_errno}) $mysqli->connect_error";

6 }

7 ?>

8

9 <h2>Adressen als 2-dimensionales Array</h2>

10 <table border="1">

11 <?php

12 $result = $mysqli->query("SELECT * FROM adressen");

13

14 // Tabellenkopf mit den Feldnamen als Spaltenbezeichnungen:

15 echo " <tr>\n";

Page 116: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

116 Andreas de Vries

16 while ( $field = $result->fetch_field() ) {

17 echo " <th>$field->name</th>\n";

18 }

19 echo " </tr>\n";

20

21 // Tabelleneinträge aus der Datenbank, spezielle Ausgabe für email und web:

22 while ( $adresse = $result->fetch_object() ) {

23 echo " <tr>\n";

24 foreach ( $adresse as $key => $value ) {

25 if ( $key === "email" ) {

26 echo " <td><a href=\"mailto:$value\">$value</a></td>\n";

27 } else if ( $key === "web" ) {

28 echo " <td><a href=\"http://$value\">$value</a></td>\n";

29 } else {

30 echo " <td>$value</td> \n";

31 }

32 }

33 echo " </tr>\n";

34 }

35 ?>

36 </table>

Im Unterschied zum vorigen Beispiel werden hier die Datensätze in einer Tabelle ausgegeben.Die foreach-Schleife läuft das Array sukzessive durch und ermöglicht den Zugriff auf die In-halte über die Variable $value. In dem Beispiel wird der Wert von $value in ein <td>-Tag vonHTML gepackt, so dass jeder Datensatz in <tr>-Elementen steht und so als eine Tabellenzeileim Browser angezeigt wird.

Ermittlung der Feldnamen aus der Datenbank

Möchte man zusätzlich, so wie in diesem Beispiel, die Feldnamen der Datenbank als Spaltenbe-zeichner anzeigen, so muss man irgendwie an die Bezeichnungen der Felder aus der Datenbankgelangen. Die Information ist aber bereits in der Ergebnismenge einer erfolgreich abgeschlosse-nen SELECT-Anweisung enthalten, in unserem Falle also in der Variablen $result. Der elegantes-te Weg, an diese Information zu kommen, ist mit Hilfe der Funktion $result->fetch_field().Sie liefert ein Objekt zurück, dessen Attribute die Metadaten des jeweils nächsten Feldes derDatenbanktabelle(n) ist, wie z.B. Feldname oder Feldtyp. So kann man sich also mit der An-weisung

while ($spaltenname = $result->fetch_field()->name) {

echo "$spaltenname<br/>";

}

die Feldnamen anzeigen lassen.

12.3 Informationen über gerade abgesetzte SQL-BefehleIn diesem Abschnitt werden zwei sehr nützliche öffentliche Attribute des mysqli-Objekts bzw.der Ergebnismenge vorgestellt, die Informationen über den jeweils letzten abgesetzte SQL-Befehl speichern.

Page 117: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 117

• $mysqli->affected_rows speichert die Anzahl der durch die jeweils letzte SQL-Anfragean den Server betroffenen Datensätze. Beispielsweise findet man wie folgt die Anzahlgelöschter Datensätze heraus:

$mysqli->query("DELETE FROM mytable WHERE id < 10");

$anzahl = $mysqli->affected_rows;

echo "$anzahl Datensätze gelöscht";

Die prozedurale Variante davon, mysqli_affected_rows($link), ist eine Funktion undbenötigt als Parameter die Verbindungskennung $link; Näheres dazu siehe unter http:

//php.net/manual/de/mysqli.affected-rows.php.

• $result->num_rows speichert die Anzahl der Datensätze einer Ergebnismenge $result.Dieses Attribut ist nur gültig nach einem SELECT-Befehl.

$result = $mysqli->query("SELECT * FROM table1");

$num_rows = $result->num_rows;

echo "$num_rows Zeilen\n";

Direkt nach einer SELECT-Anfrage mit $mysqli->query() ergibt $result->num_rows das-selbe wie $mysqli->affected_rows.

12.4 SQL Injection entschärfen mit escape_string

Ein Sicherheitsrisiko jeder Webdatenbank ist die „SQL-Injektion“, also der Versuch eines An-greifers, über eine Formulareingabe die Datenbank abzufragen oder gar zu manipulieren. EinSchutz vor solchen Angriffen ist nicht trivial, allerdings bietet PHP mit der Funktion escape_string

einen einfachen Abwehrmechanismus an, siehe http://php.net/manual/en/mysqli.real-escape-string.

php; die Funktion ist ein Alias der Funktion real_escape_string. Sie durchläuft den übergebe-nen String und ersetzt sicherheitskritische Zeichen, die zu einer SQL-Injektion führen könnten.Man sollte generell alle Eingaben analog folgendem Mechanismus entschärfen:

$eingabe = $mysqli->escape_string($_POST["eingabe"]);

// irgendeine SQL-Anweisung:

$sql = "SELECT * FROM tabelle WHERE spalte='$eingabe'";

$result = $mysqli->query($sql); // zur Datenbank senden

12.5 Zusammenfassung

• Ein netzwerkbasiertes System, das Datenbankzugriffe über das Internet ermöglicht, kannmit HTML, PHP und SQL programmiert werden.

• Insgesamt stellt PHP eine Schnittstelle zwischen Browser (WebClient) und einer MySQLDatenbank (DB-Server) dar.

• Merke: In einem PHP-Skript kann weder HTML- noch SQL-Code verarbeitet werden.Beides muss als String erzeugt werden und entweder per echo an den Browser oder per$mysqli->query an die Datenbank geschickt werden.

Page 118: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

118 Andreas de Vries

echo

Browser

$mysqli−>querySQL (als String)

HTML (als String)

PHPMySQL

Datenbank

• Die Funktionen zur Durchführung der drei wesentlichen Schritte zum Datenzugriff aufeine Datenbank via PHP sind:

1. $mysqli = new mysqli(...) — erstellt die Verbindung zur Datenbank auf einemDatenbankserver

2. $mysqli->query(...) — sendet SQL-Befehle zur Datenbank (SELECT, INSERT, UPDATE,DELETE)

3. $result->fetch_object(), $result->fetch_assoc(), $result-> fetch_row() — liestdie Ergebnismenge einer SQL-Abfrage als Objekt bzw. als assoziatives oder nume-risches Array in PHP ein

• Der Zugriff auf eine Datenbank sollte der Übersichtlichkeit und Wartbarkeit halber mitVariablen parametrisiert werden:

$server = "localhost";

$user = "user";

$password = "passwort";

$database = "datenbank";

$mysqli = new mysqli($server, $user, $password, $database);

$mysqli->set_charset('utf8');

Zudem sollten diese Anweisungen in eine eigene Datei ausgelagert werden, so dass meh-rere PHP-Skripte die Einstellungen einlesen können.

• Zum Anzeigen von Informationen aus einer Datenbanktabelle benötigt man mindestensdie zwei Schritte

$result = $mysqli->query("SELECT * FROM Tabelle");

zur Selektion der Daten und die Schleife

1 while ( $eintrag = $result->fetch_assoc() ) {

2 foreach ($eintrag as $value) {

3 echo "$value<br/>";

4 }

5 }

Page 119: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

13Datenbankinteraktionen mit dem Browser

Kapitelübersicht13.1 Eintragen-Skript mit unformatierten Ausgaben . . . . . . . . . . . . . . . . . . . . . . 120

13.1.1 Der Ablauf des Skripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12113.1.2 Das Eingabeformular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12213.1.3 Das Abspeichern der Daten . . . . . . . . . . . . . . . . . . . . . . . . . . . 12213.1.4 Die Anzeige . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

13.2 Eintragen-Skript mit Funktionen und Formatierungen . . . . . . . . . . . . . . . . . . 12313.3 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

Üblicherweise besteht eine Webanwendung aus einer Interaktion mit einer Datenbank, alsoaus enem komplexen Ablauf von Aus- und Eingabeaktionen, die jeweils von den vorherigenAktionen abhängen. Ablauf und Logik aus Sicht des Anwenders müssen aufgrund der star-ren Request-Response-Architektur des Webs in dem PHP-Skript umgeschrieben werden. DieSchwierigkeit von PHP liegt abstrakt gesprochen darin, dass PHP nur auf einen einkommendenRequest reagieren kann, aber keinen permanenten Prozess darstellt, der den Ablauf begleitet.Ein PHP-Skript muss also den aktuellen Zustand des Ablaufs jedesmal von Neuem feststellen.Oft ist dazu die Information notwendig, welchen Button der Anwender eigentlich gedrückt hat.Mit dieser Problematik beschäftigen wir uns in diesem Kapitel.

Wir möchten dazu im Folgenden ein Skript schreiben, das nicht nur das Ansehen der Datenin der Adressdatenbank ermöglicht, sondern auch das Eintragen neuer Daten über den Browser.Grob soll dabei folgender Ablauf stattfinden:

1. Beim ersten Aufruf soll der aktuelle Inhalt der Datenbank gezeigt werden. Allerdings solles nun einen Submit-Button geben, siehe Abb. 13.1 (links).

2. Anklicken dieses Buttons ruft dasselbe Skript auf, das nun aber ein Eingabeformularzeigt, in das die neuen Daten eingetragen werden können, siehe Abb. 13.1 (rechts).

3. Das Anklicken des Submit-Buttons soll erneut das Skript aufrufen, um nun die Formular-daten in die Datenbank zu speichern.

119

Page 120: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

120 Andreas de Vries

Abbildung 13.1: Die Seite beim Aufruf und beim Drücken des Eintragen-Buttons.

13.1 Eintragen-Skript mit unformatierten AusgabenWir werden zunächst ein PHP-Skript betrachten, das zwar alle geforderten Funktionalitätenliefert, aber die Browserausgaben nicht formatiert.

Beispiel 13.1. Adressen aus Datenbank, mit Einfügemöglichkeit �

1 <!-- Adressen in DB eintragen. Dateiname: adresseDB2.php -->

2 <form action="<?php echo $_SERVER['PHP_SELF']?>" method="POST">

3 <?php

4 $mysqli = new mysqli("localhost", "user", "c5dDC8VJemscKPQS", "AdressDB");

5 if ($mysqli->connect_errno) {

6 echo "Failed to connect to MySQL: ({$mysqli->connect_errno}) $mysqli->connect_error";

7 }

8 $mysqli->set_charset("utf8");

9

10 if (isset($_POST['eintragen'])) { // -- Eingabeform und Speichern-Button erstellen

-

11 ?>

12 Vorname: <input type="text" name="vorname"/><br/>

13 Name: <input type="text" name="name"/><br/>

14 PLZ: <input type="text" name="plz" size="7"/>

15 Ort: <input type="text" name="ort"/> <br/>

16 Strasse: <input type="text" name="strasse"/><br/>

17 Web: <input type="text" name="web"/><br/>

18 e-mail: <input type="text" name="email"/><br/>

19 <input type="submit" name="speichern" value="Speichern"/>

20 <?php

21 } else {

22 if (isset($_POST['speichern'])) { // -- Formulardaten speichern --

23 $name = $mysqli->escape_string($_POST["name"]);

24 $vorname = $mysqli->escape_string($_POST["vorname"]);

25 $plz = $mysqli->escape_string($_POST["plz"]);

26 $ort = $mysqli->escape_string($_POST["ort"]);

27 $strasse = $mysqli->escape_string($_POST["strasse"]);

28 $web = $mysqli->escape_string($_POST["web"]);

29 $email = $mysqli->escape_string($_POST["email"]);

30

31 $sql = "INSERT INTO adressen ";

Page 121: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 121

32 $sql .= "(name, vorname, plz, ort, strasse, web, email)";

33 $sql .= " VALUES ";

34 $sql .= "('$name','$vorname','$plz','$ort','$strasse','$web','$email')";

35 $mysqli->query($sql); // an Datenbank abschicken

36 } // -- Ende speichern ------------------------------

37

38 //auflisten + Eintragen-Button:

39 $sql = "SELECT * FROM adressen ORDER BY Name";

40 $result = $mysqli->query($sql);

41

42 while ($adresse = $result->fetch_assoc()) {

43 echo "$adresse[name], $adresse[vorname], $adresse[email]<br/>";

44 }

45 ?>

46 <input type="submit" name="eintragen" value="Adresse eintragen"/>

47 <?php

48 } //-- Ende else ------------------------------------

49 ?>

50 </form>

51 </body>

52 </html>

Zunächst fällt auf, dass das gesamte Skript durch ein Form-Tag umschlossen wird, so dasses sich beim Submit selbst wieder aufruft.

13.1.1 Der Ablauf des Skripts

Der eigentliche Ablauf des Skripts aus Sicht des Benutzers wird durch die if-Anweisungengesteuert. Sie haben die folgende Struktur:

1 if (isset($_POST['eintragen'])) {

2 ... Eingabeformular und Speichern-Button erstellen ...

3 } else {

4 if (isset($_POST['speichern'])) {

5 ... Eingabedaten in DB speichern ...

6 }

7 ... DB-Inhalt auflisten und Eintragen-Button erstellen ...

8 }

Wie läuft das Skript also aus Benutzersicht ab? Ruft er es das erste Mal auf, so ist sind $_POST["ein-

tragen"] und $_POST["speichern"] undefiniert. In dem Skript werden also nur die nach deminneren if-Zweig ausgeführt, so dass der Benutzer den aktuellen Datenbankinhalt und denEintragen-Button sieht.

Klickt er nun auf den Eintragen-Button, so wird das Skript erneut aufgerufen, doch diesmalist der Inhalt von $_POST["eintragen"] definiert (wesentlich ist hierbei, dass der Eintragen-Button auch den Namen eintragen hat!). Somit werden die Anweisungen des äußeren if-Zweigs ausgeführt und das Eingabeformular für die Daten sowie der Speichern-Button ange-zeigt.

Schickt der Benutzer nun dieses Formular ab, so wird das Skript ein drittes Mal aufgeru-fen, diesmal ist jedoch $_POST mit den Eingabedaten gefüllt und $_POST["speichern"] ist nun

Page 122: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

122 Andreas de Vries

ebenfalls definiert. Daher wird der innere if-Zweig ausgeführt, der Benutzer sieht den aktuellenStand der Datenbank.

13.1.2 Das EingabeformularDas Eingabeformular wird aufgebaut, wenn zuvor der Submit-Button namens eintragen ge-drückt worden ist. Jedes Input-Element hat als Namen den entsprechenden Feldnamen aus derDatenbanktabelle. Damit hat man stets eine direkt verständliche Verbindung zwischen den Fel-dern und den Textfeldern und erleichtert so die Programmierung und spätere Verwaltung auf-grund etwaiger Änderungen der Datenbankstruktur.

Wesentlich für den korrekten Ablauf des Skripts ist, dass der Submit-Button dieses Einga-beformulars speichern heißt, denn die steuernden if-Anweisungen benötigen zum korrektenAblauf des Skripts diesen Namen.

13.1.3 Das Abspeichern der DatenZum Abspeichern der Daten aus dem Eingabeformular muss ein INSERT-Befehl in SQL aufdie Datenbank abgesetzt werden. (Hier erkennt man einen der Vorteile, wenn man die Input-Elemente des Formulars gleich nennt wie die Felder der Tabelle!) Ein häufig gemachter Fehlerist das Fehlen der Apostrophs bei der Wertzuweisung.

Der SQL-Befehl wird zunächst in eine String-Variable $sql gespeichert. (Zu beachten sinddabei die Leerzeichen bei Zeilenumbrüchen!). Das hat einerseits den Vorteil, dass man den rela-tiv langen Befehl übersichtlich aufbauen kann. Andererseits kann man im Fehlerfall leicht denSQL-Befehl anzeigen („debuggen“) lassen, um zu prüfen, ob es sich um einen SQL-Fehlerhandelt. Debugging ist das zeilenweise Verfolgen der Werte eines Programms während derLaufzeit. Es gibt dafür, ähnlich wie für andere Programmiersprachen, einige ausgereifte Tools,jedoch in so einfachen Umfeldern wie hier reicht auch ein einfaches Ausgeben der Werte.Damit kann man sich also in unserem Falle während des Skriptablaufs anzeigen lassen, wel-ches SQL-Statement genau abgesetzt worden ist. Oft kann man auf diese Weise Syntaxfehlerin SQL schnell entdecken, insbesondere das Vergessen der Apostrophs (’). Empfehlenswertist in diesem Zusammenhang auch das Debuggen mit etwaigen Fehlerausgaben der Funktionmysqli_error nach einer SQL-Anfrage:

$result = $mysqli->query($sql);

if ($mysqli->error) {

echo "SQL error: " . $mysqli->error;

}

Mit der if-Bedingung wird die echo-Anweisung nur im Fehlerfall aufgerufen.Wie auch immer, am Ende muss ein SQL-Befehl natürlich auch mit $mysqli->query an

die Datenbank gesendet werden. Genau dieser Fehler wird erfahrungsgemäß oft gemacht, dasseine geniale SQL-Anweisung erzeugt wird, sie aber nicht abgesetzt wird. Denken Sie immer anAbbildung 12.2, PHP ist nur das Medium!

13.1.4 Die AnzeigeDie Anzeige des aktuellen Inhalts der Datenbank wird angezeigt durch eine SELECT-Anweisung.Sie lautet in unserem Beispiel 13.1

SELECT * FROM adressen ORDER BY Name

und liefert eine nach Namen sortierte Ergebnismenge $result.

Page 123: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 123

13.2 Eintragen-Skript mit Funktionen und FormatierungenMit Funktionen kann man das eigentliche PHP-Skript, im folgenden auch „Hauptskript“ ge-nannt, relativ kurz gestalten.

Beispiel 13.2. Adressen aus Datenbank, mit Einfügemöglichkeit �

1 <!-- Adressen in DB eintragen. Dateiname: adresseDB3.php -->

2 <form action="<?php echo $_SERVER['PHP_SELF']?>" method="POST">

3 <?php

4 require("./adressDBFunktionen.inc.php");

5

6 $mysqli = new mysqli("localhost", "user", "c5dDC8VJemscKPQS", "AdressDB");

7 if ($mysqli->connect_errno) {

8 echo "Failed to connect to MySQL: ({$mysqli->connect_errno}) $mysqli->connect_error";

9 }

10 $mysqli->set_charset("utf8");

11

12 if (isset($_POST['eintragen'])) {

13 eintragen($mysqli);

14 } else {

15 if (isset($_POST['speichern'])) {

16 speichern($mysqli, "adressen", $_POST);

17 }

18 auflisten($mysqli);

19 }

20 ?>

21 </form>

Im Wesentlichen wird also ein Formular erzeugt und nach dem Aufbau der Datenbankver-bindung je nach Inhalt der $_POST-Variablen eine der Funktionen auflisten, eintragen oderspeichern aufgerufen. Diese Funktionen sind ausgelagert in der Datei

adressDBFunktionen.inc.php

in der gleichen Verzeichnisebene wie das PHP-Skript, zu erkennen am Pfad des require-Befehls.Bevor wir uns diese näher anschauen, betrachten wir den Ablauf des Skripts eingehender.

Betrachten wir nun die aufgerufenen Funktionen etwas näher.

Beispiel 13.3. Funktionen der Adressdatenbank �

1 <!-- Funktionen der Adress-DB. Dateiname: adressDBFunktionen.inc.php //->

2 <?php

3 function auflisten($mysqli) {

4 ?>

5 <h2>Adressen als 2-dimensionales Array</h2>

6 <table border="1">

7 <?php

8 $sql = "SELECT * FROM adressen ORDER BY Name";

9 $result = $mysqli->query($sql);

10

Page 124: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

124 Andreas de Vries

11 // Tabellenkopf mit den Feldnamen als Spaltenbezeichnungen:

12 echo " <tr>\n";

13 while ( $attribut = $result->fetch_field() ) {

14 echo " <th>$attribut->name</th>\n";

15 }

16 echo " </tr>\n";

17

18 // Tabelleneinträge aus der Datenbank, spezielle Ausgabe für email und web:

19 while ( $adresse = $result->fetch_assoc() ) {

20 echo " <tr>\n";

21 foreach ( $adresse as $key => $value ) {

22 if ( $key == "email" ) {

23 echo " <td><a href=\"mailto:$value\">$value</a></td>\n";

24 } else if ( $key == "web" ) {

25 echo " <td><a href=\"http://$value\">$value</a></td>\n";

26 } else {

27 echo " <td>$value</td> \n";

28 }

29 }

30 echo " </tr>\n";

31 }

32 ?>

33 </table>

34 <p style="text-align:center">

35 <input type="submit" name="eintragen" value="Adresse eintragen"/>

36 </p>

37 <?php

38 } // Ende function auflisten

39

40 function eintragen($mysqli) {

41 ?>

42 <table border="0">

43 <tr><td>Vorname: </td><td><input type="text" name="vorname"/></td></tr>

44 <tr><td>Name: </td><td><input type="text" name="name"/></td></tr>

45 <tr>

46 <td>PLZ/Ort: </td>

47 <td>

48 <input type="text" name="PLZ" size="7"/>

49 <input type="text" name="Ort"/>

50 </td>

51 </tr>

52 <tr><td>Strasse: </td><td><input type="text" name="strasse"/></td></tr>

53 <tr><td>Web: </td><td><input type="text" name="web"/></td></tr>

54 <tr><td>e-mail: </td><td><input type="text" name="email"/></td></tr>

55 </table>

56 <p><input type="submit" name="speichern" value="Speichern"/></p>

57 <?php

58 } // Ende function eintragen

59

Page 125: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 125

60 function speichern($mysqli, $tabelle, $daten) {

61 $spalten = array();

62 $werte = array();

63 foreach ( $daten as $key => $value ) {

64 if ( $key != "speichern" ) {

65 $spalten[] = $key;

66 $werte[] = "'" . $mysqli->escape_string($value) . "'";

67 }

68 }

69 $sql = "INSERT INTO $tabelle ";

70 $sql .= "(" . implode(",", $spalten ) . ")";

71 $sql .= " VALUES ";

72 $sql .= "(" . implode(",", $werte ) . ")";

73 $mysqli->query($sql);

74 }

75 ?>

Die Funktion auflisten entspricht im Wesentlichen dem Beispielskript 12.1. Einzige Än-derungen sind das SELECT-Statement, das jetzt

SELECT * FROM adressen ORDER BY Name

lautet und eine nach Namen sortierte Ergebnismenge $result liefert. Außerdem ist nun einSubmit-Button namens eintragen eingefügt, der an sich nichts anderes bewirkt, als dass dasHauptskript wieder aufgerufen wird. Die $_POST-Variable enthält nun als einziges Datenfeld$_POST[eintragen], ist also nicht mehr leer.

Damit wird nun in dem Skript der zweite if-Zweig durchlaufen, d.h. die Funktion eintragen

aufgerufen. Diese Funktion baut nun ein einfaches Eingabeformular auf, in dem die Adressdateneingegeben werden können. Der Submit-Button heißt hier nun speichern, und damit wird nachAnklicken das Hauptskript wieder aufgerufen.

Diesmal wird der dritte if-Zweig durchlaufen und die Funktion speichern aufgerufen. DieseFunktion übernimmt die Dateninhalte der $_POST-Variablen des Eingabeformulars, um darausein INSERT-Statement zu bilden. Mit $mysqli->query wird dieser SQL-Befehl an die Datenbankgeschickt, in der dann der Datensatz gespeichert wird. Diese Variante bildet zwei Arrays, je einsmit den Spaltennamen und eins mit den Inhalten, und verwendet den implode-Befehl, um darausdie Klammerausdrücke für ein INSERT zu erzeugen. Nachdem dieser INSERT-Befehl als Stringgebildet worden ist, wird er mit $mysqli->query an die Datenbank geschickt, dort von demDatenbanksystem als SQL interpretiert und ausgeführt (wenn denn kein Syntaxfehler in SQLvorliegt ...). Danach wird direkt die Funktion auflisten aufgerufen, die die nun aktualisierteTabelle an den Browser schickt. Violà!

13.3 Zusammenfassung• Der Ablauf eines Skripts, das sich mehrmals selbst aufruft, wird mit if-Anweisungen

gesteuert, die den Inhalt der Submit-Buttons prüfen. Wesentlich ist also in diesem Fall,dass jeder Submit-Button einen eigenen Namen trägt.

• Der zeitliche Ablauf des Skripts aus Sicht des Benutzers entspricht nicht der Strukturder if-Anweisungen, denn zuerst werden spezielle Belegungen der Submit-Buttons ab-gefragt, dann erst kommt der allgemeine Teil.

Page 126: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

126 Andreas de Vries

• Die Anzeige des aktuellen Datenbankinhalts sollte erst am Ende des Skripts erfolgen,nachdem etwaige Änderungen in der Datenbank erfolgt sind. Würde man in Beispiel 13.1die Anzeige der Datenbankinhalte vor der Speicherung der Eingabedaten programmieren,wäre zwar der neue Eintrag korrekt in der Datenbank gespeichert, der Anwender sähe aberirreführenderweise noch den alten Stand der Datenbank.

• Man sollte die Namen der <input>-Tags in einem Eingabeformular genauso nennen wiedie entsprechenden Feldnamen der Datenbanktabelle. Das erleichtert einerseits die Pro-grammübersicht, andererseits die Synchronisation und Verwaltung bei Änderungen derDatenbankstruktur.

• Erstellt man ein SQL-Statement als einen String (z.B. namens $sql), so muss er irgend-wann mit $mysqli->query an die Datenbank gesendet werden. ;-)

Page 127: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

14Informationssicherheit

Kapitelübersicht14.1 SQL-Injektion: Angriffe auf Daten . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127

14.1.1 Einfaches Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12814.1.2 Gegenmaßnahmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128

14.2 Session Fixation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12914.2.1 Gegenmaßnahmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

14.3 CSRF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13014.3.1 XSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131

Informationssicherheit bezeichnet Eigenschaften eines informationsverarbeitenden Systems, dieseine Vertraulichkeit, Verfügbarkeit und Integrität schützen. Informationssicherheit dient insbe-sondere dem Schutz vor Gefahren bzw. Bedrohungen, der Vermeidung von wirtschaftlichenSchäden und der Minimierung von Risiken.

Jedes Informationssystem hat Schwachstellen und ist damit verwundbar. Ein Angriffsvektorbezeichnet einen möglichen Angriffsweg oder eine Angriffstechnik, die ein unbefugter Ein-dringling nehmen kann, um ein fremdes System zu kompromittieren, das heißt unbefugt ein-zudringen und es danach entweder zu übernehmen oder zumindest für eigene Zwecke zu miss-brauchen. Meist werden dazu bekannte Sicherheitslücken des angegriffenenen Systems ausge-nutzt. Ein solches Ausnutzen bezeichnet man als Exploit.

14.1 SQL-Injektion: Angriffe auf Daten

Unter einer SQL-Injektion versteht man das Absetzen von SQL-Befehlen über ein Texteinga-befeld, wie z.B. für Benutzername oder Passwort, oder über die GET-Methode. Der Angreiferversucht damit, eigene Datenbankbefehle über das Eingabeformular einzuschleusen und so dieKontrolle über die SQL-Datenbank oder gar den Datenbankserver zu erlangen.

Wie kann das gelingen? Kern dieser Angriffe sind die Funktionszeichen in SQL, ;, \ und ’

und die Kommentarzeichen -- oder #, sowie (bei SQL-Injektion über GET) die URL-Codierungbestimmter Sonderzeichen (%20 für das Leerzeichen).

127

Page 128: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

128 Andreas de Vries

14.1.1 Einfaches BeispielNehmen wir an, wir hätten ein einfaches Eingabeformular mit zwei Textfeldern namens name

und passwort als Login-Maske, welches nach dem Absenden ein Skript aufruft, das die folgendeSQL-Anweisung ausführt:

$sql = "SELECT * FROM user";

$sql .= "WHERE name = ’$_POST[name]’";

$sql .= "AND password = ’$_POST[password]’";

Wenn dieses SQL-Kommando ohne weitere Prüfung an die Datenbank geschickt wird, kannein Angreifer sich ohne Kenntnis eines Usernamens oder Passwortes in das Systen einloggen,indem er einfach in das Textfenster eingibt:

User: ’ OR 1=1 # (14.1)

Daraus setzt das aufgerufene PHP-Skript dann die folgende SQL-Anweisung zusammen:

SELECT * FROM user WHERE name = ’’ OR 1=1 #’ AND password = ”

Damit werden alle User der Datenbanktabelle mit ihrem Passwort angezeigt! Denn nun lautetdie WHERE-Bedingung einfach name = ”, was sicher falsch ist, oder 1=1, was sicher wahr ist, unddamit lautet das SQL-Kommando effektiv SELECT * FROM user.

Auf ähnliche Weise kann es einem Angreifer gelingen, Kontrolle über die Datenbank zubekommen und Daten zu manipulieren oder gar die ganze Datenbank zu löschen. Fatalerweisewäre es beispielsweise möglich, die Preise für in einem Webshop angebotene Artikel zu verän-dern und ihn dann zu bestellen.

14.1.2 GegenmaßnahmenEs ist nicht schwer, PHP-Programme vor SQL-Injektionen zu schützen. Wie so oft ist das haupt-sächliche Problem die Unwissenheit oder Arglosigkeit des Programmierers über diese Art vonAngriffen. Eine Möglichkeit, sich in PHP gegen SQL-Injektionen zu schützen, ist die Verwen-dung der Funktion

$mysqli->escape_string(string).

Diese Funktion stellt den folgenden Zeichen einfach einen Backslash voran: NULL, \x00, \n, \r,\, ’, " und \x1a. Diese Voranstellung heißt Maskierung (esacping). Damit lautet eine sichereVariante der obigen Erstellung einer SQL-Anweisung:

1 $sql = "SELECT * FROM user";

2 $sql .= "WHERE name = '" . $mysqli->escape_string($_POST[name]) . "' ";

3 $sql .= "AND password = '" . $mysqli->escape_string($_POST[password]) . '";

Die Eingabe (14.1) läuft nun ins Leere, sie ergibt nun nach dem Absenden

SELECT * FROM user WHERE name = ’\’ OR 1=1 #’ AND password = ”

Einen User mit dem Namen \’ OR 1=1 # ohne Passwort wird es jedoch wohl kaum geben, undso klappt die Anmeldung auf diese Weise nicht.

Ein kleines Programm, das die Wirkung der Maskierung demonstriert, lautet wie folgt.

Page 129: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 129

Listing 14.1: Schutz vor SQL-Injektionen1 <h1>Demonstration SQL-Injektion</h1>

2

3 <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">

4 User: <input type="text" name="user"/>

5 Passwort: <input type="text" name="passwort"/>

6 <input type="submit" value="Anmelden"/>

7 </form>

8

9 <p style="color:red">

10 <?php

11 require_once("db_login.inc.php");

12 $mysqli = login("login");

13

14 if (!empty($_POST["user"]) && !empty($_POST["passwort"])) {

15 $user = $_POST["user"];

16 $passwort = $_POST["passwort"];

17

18 $sql = "SELECT * FROM users WHERE user='$user' AND passwort='$passwort'";

19 echo "$sql<br/>";

20

21 /*22 $user = $mysqli->escape_string($_POST["user"]);

23 $passwort = $mysqli->escape_string($_POST["passwort"]);

24

25 $sql = "SELECT * FROM users WHERE user='$user' AND passwort='$passwort'";

26 echo "SQL mit Maskierung: $sql<br/>";

27 // */

28 }

29 ?>

30 </p>

Ähnliche Gegenmaßnahmen gibt es in anderen Programmiersprachen. In Java sollte man stattder üblichen Klasse Statement die Klasse PreparedStatement verwenden,

1 String sql = "SELECT spalte1 FROM tabelle WHERE spalte2 = ?";

2 PreparedStatement pstmt = con.prepareStatement(sql);

3 pstmt.setString(1, spalte2Wert);

4 ResultSet rset = pstmt.executeQuery();

Weitere Informationen unter http://de.wikipedia.org/wiki/SQL-Injektion.

14.2 Session FixationSession Fixation (etwa: „Sitzungsfestlegung“) ist ein Angriff auf eine verbindungsbehaftete Da-tenkommunikation zwischen zwei Computern, die auf einer Session-ID basiert. Der Angriffbesteht aus drei Schritten [9, §8.2.2]:

1. Der Angreifer verschafft sich eine gültige Session-ID.

2. Er schiebt die Session-ID einem anderen Benutzer unter.

Page 130: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

130 Andreas de Vries

3. Authentifiziert sich nun der Benutzer mit der untergeschobenen Session-ID bei dem anzu-greifenden Rechner, so kann der Angreifer dort über die Session-ID mit dessen RechtenZugriff erlangen, solange diese gilt.

Der schwierigste Schritt dieses Angriffs ist die Unterschiebung der Session-ID an den unschul-digen Benutzer. In dem Fall, dass die Session-ID über einen Link übertragen wird, muss derAngegriffene dazu gebracht werden, diesen Link anzuklicken, beispielsweise indem der Linkohne die Session-ID angezeigt wird:

<a href="http://example.com/login.php?session_id=3f5z73">example.com</a>

Falls die Session ausschließlich über Cookies identifiziert wird, sind entsprechende Links überHeader-Response bzw. clientseitiger Funktionen möglich, siehe https://owasp.org/index.php/

Session_fixation. Um den Inhalt und insbesondere die Parameter des URL zu verschleiern,könnte der Angreifer auf einen Kurz-URL-Dienst zurückgreifen. Der URL kann dem Opfer bei-spielsweise per E-Mail zugesendet als Link oder als Ziel (action-Wert) eines HTML-Formularsauf einer Webseite hinterlegt werden. Bei diesen Methoden des Unterschiebens ist der Angreiferaber immer darauf angewiesen, dass sein Opfer den URL öffnet bzw. ein Formular absendet.

14.2.1 Gegenmaßnahmen

Eine wirksame Gegenmaßnahme gegen die Session Fixation ist, dass der Server die Session-IDeines Benutzers bei einem Login direkt ändert. So müsste ein Angreifer die neue Session-IDkennen, die untergeschobene und ihm bekannte Session-ID wäre damit wertlos.

Auch eine Verbindung über HTTPS verhindert Session Fixation, denn in diesem Falle würdeder Dienstanbieter feststellen, dass die Identitäten von Opfer und Angreifer unterschiedlichsind.

14.3 CSRF

Cross-Site Request Forgery, CSRF oder XSRF (etwa „webseitenübergreifende Anfragenfäl-schung“), ist ein Angriff auf ein webbasiertes Informationssystem, bei dem der Angreifer sicheines Opfers bedient, das bei einer Webanwendung bereits angemeldet ist. Dem Webbrowserdes Opfers wird ohne dessen Wissen eine bösartige HTTP-Anfrage untergeschoben, so dass esvermeintlich nur die von ihm gewünschte Aktion ausführt, jedoch die untergeschobene Anfragenicht bemerkt. Ein einfaches Beispiel eines CSRF-Angriffs ist die folgende HTML-Seite:

1 <h1>CSRF</h1>

2 Hier erscheint kein Bild,

3 <img src="http://haegar.fh-swf.de/spiegel.php?konto=MARIA&betrag=100000"

4 width="0" height="0" border="0"/>

5 sondern es wurde ein Skript aufgerufen!

Egal, wo diese Seite gehostet ist, wird automatisch das Skript im img-Element aufgerufen, ohnedass der Aufrufende dies bemerkt.

Es gibt mehrere Angriffsvektoren, die man unter CSRF zusammenfassen kann, zum BeipielXSS, das die Anfragenfälschung mit Hilfe von Scriptprogrammen durchführt.

Page 131: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 131

14.3.1 XSSCross-Site-Scripting XSS (etwa „webseitenübergreifendes Scripting“) bezeichnet das Ausnut-zen einer Computersicherheitslücke in Webanwendungen, indem Informationen aus einem Kon-text, in dem sie nicht vertrauenswürdig sind, in einen anderen als vertrauenswürdig eingestuftenKontext durch ein Scriptprogramm eingefügt werden. Aus diesem vertrauenswürdigen Kontextkann dann ein Angriff gestartet werden. Ziel von XSS ist meist, an sensible Daten des Benut-zers zu gelangen, um beispielsweise seine Benutzerkonten zu übernehmen (Identitätsdiebstahl).Siehe https://owasp.org/index.php/XSS.

XST oder CST

Cross-Site-Tracing (XST oder CST) ist ein Angriff auf Internetbenutzer, der XSS, ein client-seitiges Programm und die HTTP-Methode TRACE (siehe Tabelle 1.2) verwendet. Bei einemXST-Angriff wird über ein Client-seitiges Programm eine TRACE-Anfrage mit Authentifizie-rungsdaten und Cookie-Informationen des Opfers abgesendet und die Antwort an den Angreiferweitergeleitet.1 Ein Beispiel mit Cookies ist wie folgt gegeben.

1. Ein Benutzer wird auf eine vom Angreifer vorbereitete HTML-Seite gelockt.

2. Die Seite enthält JavaScript-Code, der eine TRACE-Anfrage zu einer Website sendet, vonder der Angreifer die Cookie-Daten des Benutzers erhalten will.

3. Der Server sendet die Anfrage des Clients samt Cookies an den Client zurück, wo sievom JavaScript-Code ausgewertet wird.

4. Das JavaScript-Programm filtert die Cookies aus und sendet diese an den Angreifer.

Siehe auch https://owasp.org/index.php/XST.

1 http://www.kb.cert.org/vuls/id/867593

Page 132: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

15Dateien

Kapitelübersicht15.1 Zugriffsrechte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13215.2 Lesen und Schreiben von Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13315.3 CSV-Dateien abspeichern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13415.4 Hochladen von Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

15.4.1 Auswahl und Abschicken der Datei . . . . . . . . . . . . . . . . . . . . . . . 13515.4.2 Empfangen und Abspeichern der Datei . . . . . . . . . . . . . . . . . . . . . 136

15.5 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

Für das Lesen und Schreiben von Dateien gibt es in PHP zahlreiche Funktionen. Hier offenba-ren sich gleichzeitig die Vorteile und die Risiken eines serverseitig ablaufenden Programms. ImGegensatz zu clientseitigen Programmen wie JavaScript oder Java-Applets kann man mit PHPlesend und schreibend auf das Dateisystem des Servers zugreifen. Das ist einerseits eine enormeErleichterung, da sehr oft Daten gespeichert werden müssen, um auf sie dauerhaft zugreifen zukönnen (alle Daten, mit denen wir bisher zu tun hatten waren ja nur zur Laufzeit des Skriptsim RAM des Servers, sie sind nach seiner Beendigung unwiederbringlich dahin). So könnenbeispielsweise Logdateien geschrieben werden, die Abläufe und Nutzerbewegungen protokol-lieren, oder dynamische Daten in Webseiten aufgenommen werden, die Nutzer als Textdateioder Grafiken hochgeladen haben.

Andererseits stellen Zugriffe auf das Dateisystem des Servers eine Sicherheitslücke dar.Man kann zwar viele dieser Lücken skriptseitig abfangen, jedoch ist das Wesentliche über dieDateizugriffsrechte des Servers zu regeln.

15.1 ZugriffsrechteIn den Dateisystemen aller modernen Server-Betriebssysteme, insbesondere Unix-Systemen,wird der Zugriff auf Verzeichnisse und Dateien über ein 3-Bit-Flag gesetzt: Das erste Bit ent-scheidet über das Leserecht (r wie read) der Datei oder des Verzeichnisses, das zweite über dasSchreibrecht (w für write, beinhaltet das Erstellen und Löschen) und das dritte über Ausführ-barkeit (x für executable, das bedeutet für Verzeichnisse das Öffnungsrecht). Für einen Userbedeuten damit z.B.

r-, bzw. rwx,

132

Page 133: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 133

dass er die Datei nur lesen darf bzw. dass er alle Rechte auf sie hat.Wichtig zu wissen ist, dass die Rechte auf das Verzeichnis, in dem sich die HTML-Dateien

auf dem Webserver befinden, für die User r- (bzw. für Unterverzeichnisse r-x) lauten, sie al-so nur Leserechte haben. Damit können sie keine Dateien in das Verzeichnis schreiben oderlöschen (was ja auch sinnvoll ist).

Um Dateien zu erstellen oder hochzuladen, benötigt das PHP-Skript Schreibrechte auf dasVerzeichnis, in das die Dateien gespeichert werden sollen. Es empfiehlt sich daher, dazu eineigenes Verzeichnis anzulegen, das Schreibrechte für alle User einrichtet. In dem Vorlesungs-skript ist dies das Verzeichnis namens uploads direkt in dem Homeverzeichnis des Webservers.Diese Einstellungen können nur von dem Systemadministrator durchgeführt werden.

Sehr empfehlenswert ist außerdem, den Speicherplatz für Uploads zu begrenzen und/oderauf bestimmte Nutzer per Passwort einzuschränken.

15.2 Lesen und Schreiben von DateienDer Zugriff auf eine Datei erfolgt mit Hilfe eines so genannten Datei-Handles. Ein solchesHandle stellt die Verbindung zwischen dem Programm und dem Dateisystem dar. Es arbeitetmit verschiedenen Dateimodi, nämlich Lesen (r), Schreiben (w) und Anfügen (a, für append)und einem Dateizeiger, der die aktuelle Lese- und Schreibposition innerhalb der Datei markiert.

Die wichtigsten PHP-Funktionen zum Lesen und Schreiben von Dateien sind:

• $fh = fopen( $dateiname, $modus )

fopen öffnet eine Datei und gibt ein Handle $fh (wie file handle) zurück. Falls die Dateinicht geöffnet werden kann, wird false zurückgegeben. Der Dateiname kann ein relativeroder ein absoluter Pfad sein, aber auch eine FTP- oder HTTP-Datenquelle. So kann auchder Inhalt einer Webseite oder eines XML-Dokuments als Datei gelesen werden. Für denZugriffsmodus $modus gibt es sechs Auswahlvarianten:

– "r": Lesemodus

– "r+": Lese- und Überschreibmodus

– "w": Schreibmodus; falls die Datei noch nicht existiert, wird eine neue angelegt,andernfalls wird die bestehende Datei neu geschrieben und der alte Inhalt gelöscht.

– "w+": wie bei "w", zusätzlich kann aber gelesen werden

– "a": wie bei "w", jedoch wird eine bestehende Datei nicht gelöscht, sondern amEnde weiter geschrieben

– "a+": wie bei "a", zusätzlich sind Leseoperationen möglich

• fclose( $fh )

fclose schließt eine Datei. Wichtig ist, dass als Parameter nicht der Dateiname, sonderndas Datei-Handle übergeben wird. Da beim Beenden eines PHP-Skripts offene Dateienautomatisch geschlossen werden, ist ein explizite Schließen einer Datei zwar nicht zwin-gend erforderlich, aber zur Vermeidung von Zugriffskonflikten während des Skriptablaufsdringend zu empfehlen.

• fwrite( $fh, $string, [, $laenge] )

fwrite schreibt eine Zeichenkette (hier $string) in eine Datei; auch hier ist nicht derDateiname als Parameter zu übergeben, sondern das Datei-Handle. Der Parameter $laen-ge ist dabei optional und begrenzt die Anzahl der Zeichen. Die Funktion gibt die Anzahlder geschriebenen Zeichen zurück.

Page 134: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

134 Andreas de Vries

• $string = fread( $fh, $laenge )

fread liest eine durch $laenge bestimmte Anzahl von Bytes, maximal bis zum Datei-ende. Die vollständige Datei wird durch die folgende Anweisung eingelesen: $string =

fread($fh, filesize($fh));

• readfile( $dateiname )

readfile öffnet die Datei $dateiname, schreibt den kompletten Inhalt in das Browserfens-ter (bzw. die Standardausgabe) und schließt die Datei wieder.

• array file( $dateiname )

öffnet die Datei $dateiname, liest sie zeilenweise in ein Array und schließt sie wieder. Beieiner Textdatei steht dann jeweils eine Zeile in einem Array-Element. Mit der Anweisung

$string = implode("", file( $dateiname ));

wird der gesamte Textinhalt in den String $string gespeichert. Die Wirkung dieser An-weisung entspricht also readfile, nur dass der Ausgabestring nicht direkt in der Stan-dardausgabe landet.

15.3 CSV-Dateien abspeichernBetrachten wir zunächst ein Beispielprogramm, das ein PHP-Array als CSV-Datei auf demWebserver abspeichert.

Listing 15.1: implode und csv-Export1 <!-- Export als csv-Datei Dateiname: csv.php //->

2 <!DOCTYPE html>

3 <html>

4 <head>

5 <title>csv-Export</title>

6 </head>

7 <body>

8 <h2>CSV-Export eines 2-dimensionalen Arrays mit <code>implode</code></h2>

9 <?php

10 require( "./adressen.inc.php" );

11 $datei = "../uploads/adressen.csv";

12 $fh = fopen($datei, "w+"); // erstelle/überschreibe Datei

13 foreach ($adresse as $adressEintrag) {

14 $adressEintrag = implode(";", $adressEintrag) . "\n";

15 fwrite($fh, $adressEintrag);

16 }

17 fclose($fh);

18 echo " $datei gespeichert: <hr/>";

19 readfile( $datei);

20 ?>

21 </body>

22 </html>

Zum Export eines Arrays in eine csv-Datei wird zunächst das Array erzeugt (was in der ein-gebundenen Datei per require geschieht) und sodann der Pfad der zu schreibenden Datei als

Page 135: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 135

Variable $datei gespeichert. Das Datei-Handle $fh wird mit $fopen erzeugt, wobei eine bereitsexistierende Datei gelöscht würde. Dann wird in einer foreach-Schleife jeder Adresseintragdes Adress-Arrays per implode als String erzeugt und als Zeile in die Datei geschrieben, (dasSteuerzeichen \n bewirkt einen Zeilenwechsel) bevor die Datei sauber geschlossen wird und zurKontrolle mit einer einfachen readfile-Anweisung den Dateiinhalt unformatiert an das Brow-serfenster übergibt.

15.4 Hochladen von Dateien

Eine sehr nützliche Möglichkeit eines serverseitigen Skripts ist das Hochladen (upload) vonDateien auf der lokalen Festplatte des Clients auf ein Verzeichnis des Webservers. Der Dateitypkann dabei im allgemeinen beliebig sein, einige können erkannt werden und eine spezifischeVerarbeitung folgen. So können Sie Bilder hochladen und ggf. weiter verarbeiten lassen, PDF-Dokumente ins Web stellen usw.

Betrachten wir zunächst den groben Ablauf eines Uploads. Insgesamt ist das ein nichttrivia-ler Prozess, an dem die drei Systeme Client (Browser), Webserver und Dateisystem des Serversbeteiligt sind. Daher läuft der Prozess grob in vier Schritten ab:

Schritt Aktion beteiligtes System1. Auswahl der Datei Browser2. Abschicken der Datei Browser3. Empfangen der Datei Webserver4. Abspeichern der Datei Dateisystem des Servers

Damit wird sofort klar, dass die Aktionen der Dateiauswahl und des Verschickens der Dateinicht von einem serverseitigen PHP-Skript gesteuert werden kann. Gehen wir die Aktionensukzessive durch.

15.4.1 Auswahl und Abschicken der Datei

Wie bringt man den Browser dazu, die beiden clientseitigen Aktionen Auswahl und Abschickender Datei durchzuführen? Die Antwort ist, wie bei jeder User-Interaktion im Web, ein Formular,und zwar für ein Upload mit dem Input-Typ file. Das Formular für einen Upload sieht wie folgtaus.

1 <form method="post" enctype="multipart/form-data" action="/...php">

2 <table border="0" align="center">

3 <tr>

4 <td> <input type="file" name="datei" size="40"/> </td>

5 </tr>

6 <tr>

7 <td> <input type="reset" value="reset"/> </td>

8 <td style="text-align:right">

9 <input type="submit" value="Datei senden"/>

10 </td>

11 </tr>

12 </tabel>

13 </form>

Page 136: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

136 Andreas de Vries

Die Attribute des form-Elements müssen für ein Upload als method = "post" gesetzt sein, dader Browser nur so die Datei hochladen kann, und enctype="multipart/form-data", um denverschickten Dateityp anzugeben, und wie üblich der URL zum aufzurufenden PHP-Skript alsWert für action.

Das Formular zeigt im Browser, neben den Buttons reset und Datei senden , ein Text-feld (hier der Länge 40 Zeichen), in das der Pfad der hochzuladenden Datei geschrieben werdenkann, und dahinter einen Button durchsuchen... , mit dem man auch per Mausklick die Dateiauswählen kann. Per submit wird die Datei an das PHP-Skript verschickt.

15.4.2 Empfangen und Abspeichern der DateiDer Webserver, auf dem das aufgerufene PHP-Skript liegt, speichert die abgeschickte Dateizunächst in einem temporären Verzeichnis. Diese wird aber nach Ablauf des Skripts sofortgelöscht. Erst jetzt kommt das PHP-Skript zum Zuge, es muss nun das Dateisystem ansprechenund die Datei in das Zielverzeichnis kopieren.

Die zentralen Informationen über die Datei stehen dabei in dem zweidimensionalen asso-ziativen Array $_FILES zur Verfügung, einer globalen Standardvariablen. Es enthält als Array-Elemente alle mit der Anfrage hochgeladenen Dateien als Arrays, wobei jede Datei als Key denNamen aus dem entsprechenden Input-Feld hat (in unserem Beispiel also nur ein Element mitdem Key datei, $_FILES["datei"]). Jedes dieser Datei-Arrays ist wieder ein assoziatives Arraymit fünf Elementen:

Key Inhalt"name" Dateiname (ohne Pfad)"type" Dateityp"tmp_name absoluter Pfad zur temporären Datei"error" Fehlernummer (0 = OK)"size" Größe der Datei in Byte

Um eine Datei zu kopieren gibt es in PHP die Funktion copy( $datei1, $datei2 ), die den Pfad(oder allgemein den URL) der zu kopierenden Datei als String $datei1 als ersten Parametererhält und als zweiten den Pfad der kopierten Datei.

Eine Schwierigkeit stellen Dateinamen mit Sonderzeichen dar. In den verschiedenartigenBetriebssystemen des Clients ist es möglich, solche Dateinamen zu vergeben, im Web oder imDateisystem des Webservers sind sie nicht immer ohne weiteres darstellbar. Abhilfe schafft dieFunktion urlencode,

urlencode($string)

die einen String im ASCII-Zeichensatz und „webkonform“ erstellt. Die Umkehrfunktion isturldecode.

Auch wenn man damit leben kann, dass Umlaute vielleicht falsch dargestellt werden, soreicht urlencode allein dennoch nicht aus. Notwendigerweise müssen Leerzeichen modifiziertwerden, denn ein Leerzeichen im Dateinamen bringt das Skript zum Absturz(!), muss also aufjeden Fall abgefangen werden. Eine einfache Lösung ist die Ersetzung aller Leerzeichen durchden Unterstrich _ mit Hilfe der Funktion

strtr($string, $str1, $str2)

(für string-trim). Sie ersetzt in dem String $string alle Teilstrings $str1 durch den String $str2.Als letztes Problem sollte man leere Dateinamen ("") und leere Dateien (mit 0 Byte Größe)

verhindern.

Page 137: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 137

Als minimalen Algorithmus zum Hochladen der Dateien können wir also folgende Schleifebenutzen.

1 foreach ($_FILES as $datei) {

2 $name = strtr( $datei[name], " ", "_" ); // Leerzeichen ersetzen

3 $name = urlencode($name); // optional: verändert Umlaute

4 if ( $datei[name] != "" && $datei[size] > 0 ) {

5 $geklappt = copy( $datei[tmp_name], "../uploads/$name" );

6 if ($geklappt) {

7 echo " Datei empfangen!";

8 }

9 }

10 }

Fügen wir das alles zu einem Skript zusammen, so erhalten wir das folgende Beispielskript.

Listing 15.2: Datei hochladen1 <h2>Datei hochladen</h2>

2 <?php

3 $uploadPfad = "../uploads/"; // Pfad des Upload-Verzeichnisses

4 if (!$_FILES) { // Dateien noch nicht verschickt?

5 ?>

6 <form action="<?php echo $_SERVER['PHP_SELF'];?>"

7 method="POST" enctype="multipart/form-data">

8 Dateipfad:

9 <input type="file" name="datei"/>

10 <br/> <br/>

11 <input type="submit" value="Datei hochladen"/>

12 </form>

13 <?php

14 }

15 else {

16 foreach ($_FILES as $datei) {

17 echo " Datei $datei[name] wird geladen ... <br/>";

18 $name = strtr($datei[name], " ", "_"); //Leerzeichen ersetzen

19 echo " ... und nach $uploadPfad$name gespeichert ... <br/>";

20 if ( $datei[name] != "" && $datei[size] > 0 ) {

21 $geklappt = copy( $datei[tmp_name], "$uploadPfad$name" );

22 if ($geklappt) {

23 echo " Datei empfangen!";

24 }

25 } else echo "Datei(name) nicht ok!";

26 }

27 }

28 ?>

15.5 Zusammenfassung• Mit PHP-Skripten kann man auf das lokale Dateisystems des Webservers zugreifen. Dafür

müssen systemseitig Zugriffsrechte auf bestimmte Verzeichnisse und Dateien eingerichtet

Page 138: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

138 Andreas de Vries

werden.

• Dateien werden i.a. durch ihren URL angesprochen, d.h. durch relative oder absolutePfade, oder vollständige Webadressen (http://www... oder ftp://...).

• Zentraler Begriff für die Verarbeitung von Dateien ist das Datei-Handle. Es wird in PHPmit der Funktion fopen erzeugt. Erst dann kann eine Datei gelesen (fread) oder geschrie-ben (fwrite) werden.

• Mit implode kann ein Array als csv-Datei gespeichert werden.

• Das Hochladen von Dateien ist ein komplexes Zusammenspiel von Client und Server.Zum Verschicken einer Datei benötigt der Browser das Input-Element vom Typ "file"eines Formulars, das PHP-Skript die Daten des $_FILES-Arrays und die copy-Funktion zumkopieren der temporären hochgeladenen Datei. Zu achten ist ggf. auf eine Modifikationder Dateinamen, da insbesondere Leerzeichen zum Abbruch des PHP-Skriptes führen.

Page 139: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Teil III

Clientseitige Programmierung mitJavaScript

139

Page 140: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

16JavaScript

Kapitelübersicht16.1 Einleitende Beispiele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

16.1.1 Das <script>-Tag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14216.1.2 Anweisungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14316.1.3 Ausgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14316.1.4 Eingabe von Daten in JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . 144

16.2 Grundsätzliche Syntaxregeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14516.3 Dynamisch und implizite Typisierung . . . . . . . . . . . . . . . . . . . . . . . . . . 14516.4 Prototypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14616.5 Mathematische Funktionen und Konstanten . . . . . . . . . . . . . . . . . . . . . . . 14816.6 Kontrollstrukturen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

16.6.1 Die if-Anweisung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14916.6.2 Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

16.7 Wichtige Standardobjekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15016.7.1 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15016.7.2 JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15116.7.3 Ereignisbehandlung (Events und Event-Handler) . . . . . . . . . . . . . . . . 15216.7.4 Date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153

16.8 Funktionen und Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15416.8.1 Rückruffunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15516.8.2 Closures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15516.8.3 IIFE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15716.8.4 Rekursionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15716.8.5 Funktionen höherer Ordnung . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

16.9 DOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15916.9.1 Grundlegende Objekte des DOM: document und element . . . . . . . . . . . . 15916.9.2 Das window-Objekt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162

16.10XMLHttpRequest und AJAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16416.10.1 Aktionen nach dem Request: onreadystatechange . . . . . . . . . . . . . . . . 16616.10.2 AJAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168

16.11Web Workers: Nebenläufigkeit in JavaScript . . . . . . . . . . . . . . . . . . . . . . . 16916.12DOM Storage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170

16.12.1 Lokale und sessionspezifische Speicherung . . . . . . . . . . . . . . . . . . . 171

JavaScript ist eine wichtige Programmiersprache, da es die Sprache der Browser ist. Nach C,mit dem alle wichtigen Betriebssystemkerne programmiert sind, ist JavaScript damit die wohlam weitesten verbreitete höhere Programmiersprache der Welt. JavaScript ist, ähnlich wie PHP,

140

Page 141: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 141

eine Skriptsprache, deren Anweisungen der Interpreter direkt in den Arbeitsspeicher liest undausführt. Üblicherweise versteht man unter dem Begriff JavaScript eine clientseitige Sprache,deren Interpreter ein Modul des Browsers ist.1 JavaScript ermöglicht es, durch Zugriff auf be-stimmte Funktionen des Browsers, also „lokal“ auf dem Rechner des Webclients, eine HTML-Seite dynamisch und interaktiv zu gestalten. Im wesentlichen lassen sich mit JavaScript For-mulareingaben lokal (also noch vor Abschicken der Daten an den Server) überprüfen, Bilderanimieren, Mausereignisse verarbeiten, Pop-Up-Fenster öffnen, oder (insbesondere im Rahmenvon AJAX) asynchrone HTML-Requests für einzelne HTML-Elemente durchführen.

JavaScript wurde 1995 von Brendan Eich bei Netscape Communications entwickelt. DerName suggeriert eine Verwandtschaft mit der Programmiersprache Java, was aber bis auf ge-wisse Syntaxähnlichkeiten überhaupt nicht der Fall ist. Als Reaktion auf den Erfolg von Java-Script entwickelte Microsoft kurz darauf eine sehr ähnliche Sprache unter dem Namen JScript.Die europäische Industrievereinigung ECMA (European Computer Manufacturers Association)mit Sitz in Genf erarbeitete 1997 den Standard ECMA-Script (ECMA-262, [JS]). ECMA-262ist seit 1998 internationaler Standard (ISO/IEC 16262). Aktuelles findet man unter [JS] insbe-sondere zu den verschiedenen Browserimplementierungen auf der Unterseite About_JavaScript.

Insgesamt ist JavaScript eine im Kern sehr schöne und mächtige Programmiersprache, dieallerdings auch einige üble Eigenschaften hat. Zudem existieren im Web unzählige unsäg-lich schlechte Programmbeispiele von Programmierlaien und – ja, auch Idioten. Glauben Sieniemals blind irgendeinem Beispiel aus dem Netz, prüfen Sie stets die Programme und Aus-schnitte auf Nachvollziehbarkeit! Douglas Crockford, einer der Kämpfer für die Nutzung derguten Möglichkeiten von JavaScript [2], hat die Webseite JSLint [JSL] eingerichtet, auf derJavaScript-Quelltext auf seine Qualität geprüft werden kann. In einer umfangreichen Options-liste kann man dabei die Toleranz des Prüfprogramms einstellen. Die Quelltexte dieses Skriptessind mit den Einstellungen in 16.1 geprüft (bis auf die Methode document.write).

Abbildung 16.1: Optionen der Toleranz von JSLint [JL]

1 Seit November 2009 existiert die vielbeachtete auf JavaScript basierende eigenständige LaufzeitumgebungNode.js, die Netzwerk- und Dateisystemfunktionen besitzt und serverseitig laufen kann [13].

Page 142: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

142 Andreas de Vries

16.1 Einleitende BeispieleNach alter Tradition soll unser erstes Programm eine kleine Begrüßungsformel ausgeben. AlsVorbemerkung halten wir zunächst fest, dass ein JavaScript-Programm stets in einem HTML-Dokument eingebettet ist. Anders als bei PHP ist also der Quelltext von JavaScript in einerTextdatei mit der Endung .html oder .htm.

Listing 16.1: Hello World mit document.write1 <!DOCTYPE html>

2 <html>

3 <head><meta charset="UTF-8"/></head>

4 <body>

5 <script>

6 document.write("<h2>Grüße Dich, Welt!</h2>");

7 </script>

8 </body>

9 </html>

Achtet man auf die korrekte Textcodierung des HTML-Dokuments, so kann man problemlosUmlaute oder Sonderzeichen ausgeben.

16.1.1 Das <script>-TagGehen wir das obige Programm kurz durch. Zunächst bemerken wir, dass das Programm einHTML-Dokument ist: Die ersten vier Zeilen sind Standard-HTML. In der fünften Zeile beginntmit dem Tag <script> die Deklaration des JavaScript-Programms. Das HTML-Tag

<script> ... </script>

sagt dem Browser, dass nun JavaScript-Code folgt. Man kann JavaScript-Quellext auch in eineeigene Datei auslagern, was mit Hilfe des Attributs src geschieht:

<script src="./quelltext.js"></script>

Das Auslagern von Quelltext ist für kleine Programme zwar etwas aufwendiger, dafür aber beigrößeren Projekten übersichtlicher. Zudem kann so einmal erstellter JavaScript-Code in anderenWebseiten verwendet werden.

Wo kann ein <script> erscheinen?

In unserem ersten Programm wurde der Quelltext im body-Tag des HTML deklariert. Muss dasimmer so sein? Prinzipiell kann JavaScript durch ein script-Tag an jeder Stelle des HTML-Dokuments – also im head-Element oder im body-Element – eingebunden werden, solange dieHTML-Syntax nicht verletzt wird. Insbesondere kann man beliebig viele script-Tags verwen-den. Der Browser interpretiert sie alle der Reihe nach durch.

Als Faustregel sollte man jedoch beachten, dass Deklarationen von Funktionen (s.u.) eherim head vorgenommen werden, das ist eine übliche und sinnvolle Konvention. JavaScript-Anweisungen, die vor oder während des Aufbaus der HTML-Seite geschehen sollen, müssensogar im head deklariert werden.

Aus Performanzgründen allerdings wird für große Programme oft geraten, die <script>-Elemente am Ende des <body>-Elements zu laden, da somit das Laden des JavaScript-Quell-textes und der HTML-Elemente sich nicht gegenseitig blockieren können.2 Sicher sollte man

2 https://docs.angularjs.org/guide/bootstrap

Page 143: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 143

diesen Hinweis bei Ladezeitproblemen großer Programme auch beachten, jedoch werden indiesem Skript die <script>-Elemente bevorzugt im <head> erscheinen.

16.1.2 Anweisungen

Jede Anweisung sollte mit einem ; abgeschlossen werden. (Solange jede Anweisung in einereigenen Zeile steht, ist dies zwar nicht notwendig, aber es kann zu Mehrdeutigkeiten und somitzu unvorhergesehenen Effekten führen.)

16.1.3 Ausgaben

Ausgabe mit document.write()

Der JavaScript-Befehl document.write übergibt direkt Text an den Browser, den dieser gemäßHTML interpretiert und im Fenster darstellt. Der Browser empfängt zum Beispiel im Programmdes Listings 16.1 einfach <h2>Hello World</h2> innerhalb des body-Tags. Eine Ausgabe mitdocument.write sollte also stets im body-Tag an der Stelle stehen, wo auch der Text erscheinensoll.

Ausgabe in HTML-Elementen mit ID

Eine weitere Möglichkeit zur Ausgabe in JavaScript zeigt das folgende Beispiel. Es ist ein we-nig komplizierter, verwendet aber bereits eine sehr bedeutsame Möglichkeit von JavaScript,auf einzelne Elemente eines HTML-Dokuments zuzugreifen, wenn sie jeweils dokumentweiteindeutige ID’s erhalten haben. Dazu wird das Attribut id verwendet, das bereits im Zusam-menhang mit CSS angesprochen wurde. Mit der Funktion getElementById kann dann aus Ja-vaScript mit dieser ID auf das Element referenziert werden. Das so erhaltene Element ist einObjekt in JavaScript, das als ein Attribut innerHTML besitzt, das wiederum auf den Textinhaltverweist. (Beachten Sie dabei die Groß- und Kleinschreibung!) Betrachten wir dazu das Bei-spielprogramm 16.2, in dem eine Ausgabe nach Anklicken eines Buttons geschieht.

Abbildung 16.2: Ausgabe per Element-ID

1 <!DOCTYPE html>

2 <html>

3 <head>

4 <meta charset="UTF-8"/>

5 <script>

6 var ausgeben = function() {

7 document.getElementById("ausgabe").innerHTML = "I say hello!";

8 }

9 </script>

10 </head>

11 <body>

12 <p id="ausgabe">You say good-bye.</p>

13 <input type="button" value="OK" onclick="ausgeben();"/>

14 </body>

15 </html>

Page 144: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

144 Andreas de Vries

Hier hat das <p>-Element die ID "ausgabe" und wird so mit der Anweisung in Zeile 7 mit einemText beschrieben. Zu beachten ist, dass die Funktion getElementById zum Zeitpunkt ihrer Aus-führung das Element kennen muss. Da sie in unserem Programm im <head>-Element deklariertist, das <p>-Element in Zeile 13 also noch nicht bekannt ist, wird hier ein in JavaScript übli-cher Mechanismus verwendet, der die Ausführung erst nach Anklicken des Buttons ausführt;zu diesem Zeitpunkt ist das <p>-Element also schon bekannt. (Diesen Mechanismus werden wirunter dem Stichwort Ereignisbehandlung bzw. Event Handling näher kennen lernen.): Mit demAttribut onclick wird festgelegt, was bei Anklicken der Schaltfläche passieren soll. Hier wirddie Funktion ausgeben ausgeführt, die den Inhalt innerHTML des <p>-Elements überschreibt. DieDeklaration der Funktion ab Zeile 6 mit dem Schlüsselwort function ist JavaScript typisch undwird weiter unten erklärt.

Debugging: Ausgabe auf der JavaScript-Konsole

Bei der Entwicklung von JavaScript-Programmen kann man zum Debuggen seiner Programmeauch Text auf der JavaScript-Konsole ausgeben, und zwar mit dem Befehl

console.log("Hallo Welt!");

Die Konsole ist bei den Browsern Firefox oder Chrome sehr einfach einzuschalten.

16.1.4 Eingabe von Daten in JavaScript

Eine Erweiterung des Programmbeispiels 16.2 ist das folgende Programm mit der Möglichkeit,Daten in ein JavaScript-Programm einzulesen. Bei dieser Erweiterung definiert man im <head>-Element eine Funktion einlesen, die beim Klicken des OK-Schaltknopfes aufgerufen wird undden eingegebenen Text verarbeitet. Hierzu müssen also zwei HTML-Elemente mit einer IDversehen werden, so dass sie aus JavaScript angesprochen werden können, ein <input>-Elementfür die Eingabe und ein <span>-Element für die Ausgabe:

1 <!DOCTYPE html>

2 <html>

3 <head>

4 <meta charset="UTF-8"/>

5 <script>

6 var einlesen = function() {

7 var text = document.getElementById("eingabe").value;

8 document.getElementById("ausgabe").innerHTML = text;

9 }

10 </script>

11 </head>

12 <body>

13 <input type="text" id="eingabe"/>

14 <input type="button" value="OK" onclick="einlesen();"/>

15 <p>Sie haben gerade <span id="ausgabe"></span> eingegeben.</p>

16 </body>

17 </html>

Um auf den eingegeben Wert des Eingabefeldes eingabe zuzugreifen, muss man sein value-Attribut ansprechen, das auf aktuell den eingegegeben Inhalt verweist.

Page 145: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 145

16.2 Grundsätzliche SyntaxregelnJavaScript ist schreibungssensitiv (case sensitive), d.h. es wird strikt unterschieden zwischenGroß- und Kleinschreibung. Das reservierte Wort null ist etwas völlig anderes als Null.

Wie in Java beginnen Kommentare entweder mit einem // und enden mit dem Zeilenende,oder sind eingeschlossen zwischen /* und */.

Eine Anweisung wird mit einem Semikolon beendet. Zwar besitzt JavaScript einen Me-chanismus, der fehlende Semikolons einfügt, d.h. man muss sie nicht notwendig selber setzen.Allerdings sollte man sich auf diesen Mechanismus nicht verlassen, er kann zu logischen Pro-grammfehlern führen [2, S. 109f, 127f].

Anweisungen werden durch Umschließen von geschweiften Klammern {...} zu Blöckenzusammengefasst. Empfohlen wird in JavaScript der 1TBS-Stil,3 bei dem die öffnende ge-schweifte Klammer immer am Ende einer Zeile steht, nie am Anfang [2, S. 103].

16.3 Dynamisch und implizite TypisierungEine Variable in JavaScript kann während ihrer Laufzeit verschiedene Datentypen annehmen.Programmiersprachen, die das ermöglichen, heißen dynamisch typisiert. Demgegenüber heißteine Programmiersprache statisch typisert, wenn jede Variable einen Datentyp hat, den sie le-benslänglich behält. Konsequenterweise ist in JavaScript eine Variable stets implizit definiert,d.h. der Datentyp wird bei jeder Zuweisung während der Laufzeit automatisch bestimmt. Javaist demgegenüber statisch und explizit typisiert. In JavaScript kann eine Variable die folgenden7 möglichen Datentypen annehmen oder eine Funktion oder ein Objekt sein.

• string: eine in Anführungszeichen "..." oder Apostrophs’...’ eingerahmte Zeichen-kette (mit Unicode-Zeichen), z.B. "¡Howdy!" oder ’Allô’; um Unicode zu ermöglichen,sollte das einbettende HTML-Dokument die Zeichenkodierung UTF-8 im <meta>-Tagvorsehen werden, wie in den obigen einleitenden Beispielen.

• number: eine Zahl gemäß IEEE754 (double in Java oder C), also 42 oder 3.14159. SpezielleWerte sind Infinity für den Wert Unendlich (∞) und NaN für „not a number“. Einenexpliziten Datentyp für ganze Zahlen (wie int in Java) kennt JavaScript nicht. Eine Zahlin JavaScript hat eine Objektmethode4 toString(radix) mit radix ∈ {2, 3, . . . , 36}, diesie bezüglich der Basis radix darstellt, also beispielsweise

1 document.write((71).toString(36)); // => 1z

2 document.write(Math.PI.toString(7)); // => 3.066365143203613411

Eine weitere nützliche Standardmethode einer Zahl in JavaScript ist die Methode toFixed,die als Parameter die Anzahl n der darzustellenden Dezimalstellen erwartet, wobei 0 5 n5 20.5

1 document.write((123.4567).toFixed(3)); // => 123.457

• boolean: einer der beiden logischen Werte true oder false. Wichtige Boole’sche Opera-toren sind === und !==, hierbei ergibt x === y den Wert true genau dann, wenn Datentypund Wert der beiden Operanden x und y gleich sind, und umgekehrt liefert x !== y den

3 http://de.wikipedia.org/wiki/Einrückungsstil [2016-07-17]4 https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number/toString [2016-07-17]5 http://www.hunlock.com/blogs/The_Complete_Javascript_Number_Reference#toFixed

Page 146: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

146 Andreas de Vries

Wert true genau dann, wenn Typ oder Wert verschieden sind.6 Um den Unterschied zwi-schen === und == zu illustrieren, sei auf die Webseite

http://haegar.fh-swf.de/Webtechnologie/equalities-js.html

verwiesen. Hier erkennt man, dass === die erwartete Gleichheit zeigt (nur die Diagonaleist besetzt). Auch die „falsy“ Werte, also Werte == false, sind einigermaßen übersichtlich(0, "0", NULL, leere Arrays oder Arrays mit Eintrag 0); Ähnliches gilt für „truthy“, also ==

true, nur mit 1 statt 0. (Vergleiche die Situation in PHP).

• function: Der Datentyp für eine Funktion.

• object: Der Datentyp für ein Objekt. Für den Operator typeof ist auch ein Array vomTyp object [2, S. 18, 66].

• null: ein spezieller Wert für das Null-Objekt;

• undefined: ein spezieller Wert für „undefiniert“.

Der Datentyp eines gegebenen Wertes kann mit dem Operator typeof ermittelt werden. Vorsichtist dabei nur geboten, wenn man auf das Nullobjekt prüfen möchte, denn typeof null ergibtobject.

In JavaScript wird mit dem Schlüsselwort var eine Variable deklariert.

1 var x = 1;

2 var a = 2, b, c = "Hallo?";

3 document.write("a=" + a + ", b=" + b+ ", c=" + c); // a=2, b=undefined, c=Hallo?

Dabei können in einer var-Anweisung auch mehrere durch Kommas getrennte Variablen dekla-riert werden. Auch wenn eine Variablendeklaration in JavaScript nicht notwendig und prinzipi-ell immer eine einfache Wertzuweisung wie x = 1 für eine neue Variable x möglich ist, wird sieaus Gründen der Softwarequalität dringend empfohlen [2, S. 125, 130], [JSL].

Zwar besitzt JavaScript eine „C-Syntax“ (wie Java), durch die insbesondere ein Programmdurch geschweifte Klammern in Blöcke {...} unterteilt wird. Anders als in Java oder C im-pliziert dies aber nicht automatisch, dass ein Block den Geltungsbereich (Scope) aller in ihmdeklarierten Variablen begrenzt. JavaScript nutzt nicht Blöcke als Geltungsbereich für Varia-blen, sondern Funktionen [2, S. 40, 109].

16.4 PrototypenIm Unterschied zu einer klassenbasierten objektorientierten Sprache wie Java oder C++ gibtes in JavaScript keine Klassen, sondern nur Prototypen. Klassenbasierte Objektorientierungunterscheidet zwischen Klassen, die die Struktur seiner Attribute und Methoden festlegen, undden Objekten oder Instanzen, die daraus gebildet werden. Ein Objekt kann niemals die Strukturseiner eigenen Klasse ändern.

In einer prototypenbasierten Programmiersprache wie JavaScript gibt es keine Klassen, son-dern nur Objekte. Sie sind prototypisch in dem Sinne, dass ihre Struktur von anderen Objek-ten übernommen und vererbt werden kann und sie ihre eigene Struktur dynamisch erweitern

6 Die auch in JavaScript vorhandenen Operatoren == und != sind nicht zu empfehlen, sie erzwingen bei Ty-penungleichheit unerwartete Ergebnisse; insbesondere ist == nicht transitiv [2, S. 117]: ""==0: true, 0=="0": true,""=="0": false.

Page 147: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 147

können. Ein Objekt in JavaScript ist eine Menge von Attribut-Wert-Paaren, ganz ähnlich wieHashMaps in Java oder assoziative Arrays in PHP. Die Attribute heißen in JavaScript auchProperties. JavaScript eröffnet grundsätzlich zwei Möglichkeiten, ein Objekt zu erzeugen, ei-ne Deklaration in einer pseudoklassische Notation [2, S. 52] einerseits, und als Objektliteralandererseits. Ist man an eine klassenbasierte Programmiersprache wie Java gewöhnt, ist diepseudoklassische Notation zwar einsichtig, allerdings sind Objektliterale eleganter und werdenallgemein empfohlen [2, §3]. Bei einem Objektliteral werden mit einem Doppelpunkt jeweilsein Attribut-Wert-Paar bestimmt und diese verschiedenen Paare durch Kommas getrennt:

1 var gemüse = {

2 "name": "Möhre",

3 "details": {

4 "color": "orange",

5 "size": 12

6 },

7 "toString": function() {return this.name + ", " + this.details.color;}

8 }

9 document.write(gemüse.name + ", " + gemüse.details.color); // => Möhre, orange

10 document.write("<br>" + gemüse["name"] + ", " + gemüse["details"]["color"]);

11 document.write("<br>" + gemüse); // => Möhre, orange

Diese Syntax liegt dem wichtigen Format JSON zugrunde, das mittlerweile zu einem De-Fac-to-Standard der Datenübertragung im Web geworden ist.7 In den write-Funktionen erkennt mandie verschiedenen Abrufmöglichkeiten der Objekteigenschaften, nämlich mit der Punktnotationobjekt.property (wie in Java oder C++), mit der Array-Notation mit eckigen Klammern, oderüber definierte Objektmethoden wie toString. Die toString-Methode braucht dabei (als einzigeMethode) nicht explizit genannt zu werden.

Die zweite Möglichkeit der Objekterzeugung ist wie in Java mit dem Schlüsselwort new;dazu muss ein Konstruktor als Funktion definiert werden, die mit der Selbstreferenz this dieEigenschaften (properties) des Objekts festlegt, also dessen Attribute und Funktionen (Metho-den):

1 var Angestellter = function(name, abteilung) {

2 this.name = name;

3 this.abteilung = abteilung;

4 this.toString = function() {return name + " in " + abteilung;}

5 }

6 emil = new Angestellter("Emil", "IT"); // Objekterzeugung

7 document.write(emil.name + ", " + emil.abteilung); // => Emil, IT

Der Konstruktor übernimmt somit in gewisser Hinsicht die Rolle der Klasse in einer klassenba-sierten Sprache wie Java.

Für Objekte gibt es den Operator in mit der Syntax "xyz" in obj , der true zurückgibt,wenn das Objekt obj die Eigenschaft xyz besitzt, ansonsten false:

1 "details" in emil; // => false

2 "details" in gemüse; // => true

Der in-Operator kann auch für Arrays (s.u.) verwendet werden, im Falle eines numerischenIndizes müssen dabei allerdings die Anführungszeichen weggelassen werden.

7 Für „lupenreines“ JSON kann es als Wert allerdings keine Funktionen geben.

Page 148: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

148 Andreas de Vries

Notiz. JavaScript ermöglicht auch das Konzept der „prototypischen Vererbung“, eine Möglich-keit zur dynamischen Veränderung und Erweiterung der Property prototype bestehender Ob-jekte. Allerdings ist das Konzept aus meiner Sicht unklar und nur begrenzt brauchbar (es ermög-licht z.B. kein Überschreiben bestehender Properties), daher wird es in diesem Skript, im Ge-gensatz zu früheren Versionen, nicht erläutert. Auch die ansonsten ja sehr guten Quellen https:

//developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype

oder http://www.w3schools.com/js/js_object_prototype.asp brachten mir nicht viel. (Gernenehme ich das Konzept wieder auf, wenn mich jemand vom Gegenteil überzeugt!)

16.5 Mathematische Funktionen und Konstanten

Das für mathematische Funktionen und Operationen zentrale Standardobjekt in JavaScript istMath [JS, §15.8]. Es besitzt als Attribute die Konstanten

Math.E // Euler’sche Zahl e =∞

∑k=0

1k!≈ 2,718281828 . . .

Math.LN2 // Natürlicher Logarithmus von 2: ln2≈ 0,6931471 . . .Math.LN10 // Natürlicher Logarithmus von 10: ln10≈ 2,302585092994 . . .Math.LOG2E // log2 e≈ 1,44269504 . . .Math.LOG10E // log10 e≈ 0,4342944819 . . .

Math.PI // Kreiszahl π =∞

∑k=0

116k

(4

8k+1− 2

8k+4− 1

8k+5− 1

8k+6

)≈ 3,14159 . . .

Math.SQRT2 //√

2≈ 1,41421356237 . . .Math.SQRT1_2// 1/

√2≈ 0,707106781 . . .

und als Methoden die mathematischen Funktionen

Math.abs(x) // |x|Math.acos(x) // arccosxMath.asin(x) // arcsinxMath.atan(x) // arctanxMath.atan2(x,y) // arctan(x/y)Math.ceil(x) // dxeMath.cos(x) // cosxMath.exp(x) // ex (e hoch x)Math.floor(x) // bxcMath.log(x) // lnx (natürlicher Logarithmus)

Math.max(x,y) // Maximum von x und y; kann auch mehrere Argumente bekommen

Math.min(x,y) // Minimum von x und y; kann auch mehrere Argumente bekommen

Math.pow(x,y) // xy (x hoch y)Math.random() // Pseudozufallszahl z mit 0≤ z < 1Math.round(x) // kaufmännische Rundung von x auf die nächste ganze Zahl

Math.sin(x) // sinxMath.sqrt(x) //

√x

Math.tan(x) // tanx

Page 149: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 149

16.6 Kontrollstrukturen

16.6.1 Die if-AnweisungJavaScript hat dieselbe bedingten Verzweigung wie Java:

if(ausdruck) { code } [else { code2 }]

Hierbei bezeichnet ausdruck einen Boole’schen Wert und code eine Anweisung oder einenBlock von Anweisungen, der else-Zweig ist optional (und daher in eckigen Klammern). co-de wird genau dann ausgeführt, wenn der Ausdruck nicht die Werte true annimmt, ansonstenwird code2 ausgeführt, oder eben nichts, wenn der else-Zweig nicht existiert.

Fallunterscheidungen mit switch-case

JavaScript verwendet zur Unterscheidung mehrerer alternativer Fälle den Befehl switch. DieSyntax und Funktionsweise ähnelt der switch-Anweisung in Java.

1 compute = function (operator, x, y) {

2 var z;

3 switch (operator) {

4 case "+": z = x + y; break;

5 case "-": z = x - y; break;

6 case "*": z = x * y; break;

7 case "/" | ":": x / y; break;

8 case "%": z = x % y; break;

9 default: z = NaN;

10 }

11 return z;

12 };

13 document.write(compute("+", 4, 3)); // => 7

14 document.write("<br/>" + compute("%", 4, Math.PI)); // => 0.8584073464102069

16.6.2 SchleifenSchleifen gehören als iterative Kontrollstrukturen in die Welt der imperativen Sprachen, reinfunktionale Sprachen ermöglichen die Wiederholungen ausschließlich über Rekursionsaufrufe.JavaScript ist jedoch nicht rein funktional, es hat die vier Schleifenkonstrukte while, do/while,for und for-in wie in Java. Die Syntax ist bei den ersten drei Schleifenkonstrukten identisch zuder in Java. Bei der for-Schleife ist zu beachten, dass die Zählvariable mit var deklariert wird,so wie im folgenden Beispiel, dass die Euler’sche Zahl iterativ berechnet:

1 var n = 5, y = 0;

2 for (var k = 0; k <= n; k++) {

3 y += 1/factorial(k);

4 document.write("<br/>" + k + ". Iteration für e: " + y);

5 }

Hier bezeichnet factorial die Fakultätsfunktion auf S. 157. Die Ausgaben lauten dabei sukzes-sive 2, 2.5, 2.66666. . . , 2.70833. . . , 2.71666. . . .

Mit der for-in-Schleife kann man auf die Einträge einer Liste zugreifen, ähnlich wie dieforeach-Schleife in PHP. Hierbei kann eine Liste ein Array sein oder ein JSON-Objekt. DieSyntax der Schleife lautet:

Page 150: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

150 Andreas de Vries

for(var key in liste) {

... liste[key] ...;

}

Hierbei sind for, var und in Schlüsselworte, während key die durch die Eigenschaften (proper-ties) der Liste liste laufende Variable bezeichnet. Für ein Array ist key einfach der Index derEinträge. Auf beide Werte von key und liste kann dann in der Schleife zugegriffen werden. DasBeispielprogramm

1 var gemüse = {

2 name: "Möhre",

3 for: "Max", // funktioniert nicht im IE 8! (aber in IE 9)

4 details: {

5 color: "orange",

6 size: 12

7 },

8 toString: function() {return this.name + ", " + this.details.color;}

9 }

10 for(var schlüssel in gemüse) {

11 document.write("<br/> gemüse[" + schlüssel + "] = " + gemüse[schlüssel]);

12 }

ergibt die Ausgabe

gemüse[name] = Möhre

gemüse[for] = Max

gemüse[details] = [object Object]

gemüse[toString] = function () {return this.name + ", " + this.details.color;}

Man sieht, dass Werte von Attributen mit einfachem Datentyp angezeigt werden, Objekte alsAttribut jedoch nicht. Bei einer Funktion wird der Queltext angezeigt, d.h. im Programmablaufkann man auf den definierenden Quelltext von Objektfunktionen lesend zugreifen.

16.7 Wichtige StandardobjekteEs gibt einige vorgegebene Objekte in JavaScript, so die drei Objekte String, Number, Booleanzu den entsprechenden Datentypen, die Objekt Math, Date und RegExp, das Function-Objekt undeinige Error-Objekte, sowie die Datenstrukturen Array und JSON [JS, §15].

16.7.1 Arrays

Die einzige Datenstruktur oder Kollektion in JavaScript ist das Array. Ein Array ist in JavaScriptein Objekt mit dem Konstruktor Array und kann daher mit dem new-Operator erzeugt werden.Empfohlen ist jedoch stattdessen die Erzeugung mit [] (dem Literalausdruck):

1 var a = [];

2 a[0] = 10;

3 a[1] = 20;

4 a[5] = "Unterschied"; // Array mit unterschiedlichen Datentypen

5 document.write("Länge von a: " + a.length + "<br/>"); // => 6

6 document.write("a = "+a+"<br/>"); // => 10,20,,,,Unterschied

Page 151: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 151

Arrays sind, wie in Skriptsprachen allgemein, dynamisch in ihrer Größe. Daher muss die Größenicht bei der Erzeugung angegeben werden wie beispielsweise in Java. Standardmäßig sindArrays in JavaScript numerisch. Der Array-Index wird von 0 an hochgezählt. Die Elementeeines Array müssen nicht vom gleichen Typ sein. Das Attribut length gibt die Länge des Arrayszurück, die sich bei numerischen Arrays aus dem größten belegten Indexwert plus Eins ergibt.Ferner muss man das Array nicht sukzessive auffüllen, sondern kann durchaus nach Index 1 denIndex 3 belegen; der Eintrag mit Index 2 bleibt dann entsprechend undefiniert.

Ein Array kann ohne new und den Konstruktor mit einer einzigen Anweisung erzeugt wer-den, indem die Einträge in eckigen Klammern eingeschlossen und durch Kommas getrennt demArraynamen zugewiesen werden:

1 var b = [5,7,12];

2 document.write("Länge von b: " + b.length + "<br/>"); // => 3

3 document.write("b = " + b + "<br/>"); // => 5,7,12

Damit ist das Array automatisch indiziert. (Eine Einzelbelegung der Arrayplätze ohne einenIndex mit leeren eckigen Klammern, wie in PHP, funktioniert in JavaScript jedoch nicht.)

Assoziative Arrays. In JavaScript sind auch assoziative Arrays möglich. Als Schlüssel (keys)können dabei Strings verwendet werden, aber auch beliebige Objekte wie ein Array.

1 var tel = new Array();

2 tel["Meier"] = "9330-723"; // Arrays können assoziativ sein

3 tel["Müller"] = "0815/4711";

4 tel[a] = 42; // a ist das Array von oben!

5 document.write("<br/>Länge: " + tel.length + "<br/>"); // lenght=0!

6 for(var key in tel) {

7 document.write("tel[" + key + "] = " + tel[key] + "<br/>");

8 } // tel[Meier] = 9330-723, tel[Müller] = 0815/4711, tel[10,20„„Unterschied] = 42

Allerdings kann man bei einem assoziativen Array nicht mehr das Attribut length verwenden,es hat stets den Wert 0. Im Grunde sind Objekte in JavaScript nichts anderes als assoziativeArrays, bis auf die Tatsache, dass für ein Objekt im allgemeinen das Attribut length undefiniertist, während es für ein assoziatives den Wert 0 hat.

Eine wichtige Funktion eines Arrays ist forEach,8 die als Argument eine Funktion callback

erhält, die sie auf jedes Array-Element anwendet. callback muss dabei drei Argumente (value,

index, array) vorsehen, wobei value der beim Durchlaufen aktuell bearbeitete Elementwertist, index der entsprechende Array-Index, und array das aktuelle Array.

1 var callback = function(value, index, array) {

2 document.write("a[" + index + "] = " + value + ", ");

3 }

4 [2, 3, 5].forEach(callback); // => a[0] = 2, a[1] = 3, a[2] = 5,

Falls der dritte Parameter array nicht benötigt wird (wie in diesem Beispiel), kann er aucheinfach weggelassen werden.

16.7.2 JSONDie Abkürzung JSON steht für JavaScript Object Notation und bezeichnet zunächst ein weit-verbreitetes Format zum Datenaustausch, also insbesondere eine allgemeine Syntax zur Seria-lisierung (Speicherung) und Übermittlung von Werten oder Objekten der sieben Datentypen

8 https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach

Page 152: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

152 Andreas de Vries

auf S. 145, bis auf die Funktionen und undefined. Dabei ist zu beachten, dass in JSON nurObjekte erlaubt sind, deren Attribute Strings sind; es muss also heißen "name"="Müller" stattname="Müller". In JavaScript ist JSON ein spezielles globales Objekt, das die beiden entgegen-gesetzt wirkenden („komplementären“) Methoden parse und stringify bereitstellt. Mit demBefehl JSON.parse("...") wird der JSON-String in ein Objekt oder einen Wert in JavaScriptumgewandelt. Ist der String nicht im JSON-Format, so wird das Programm mit einem Syn-taxfehler beendet. Mit JSON.stringify(...) wird ein Objekt oder ein Wert in einen String inJSON-Format umgewandelt.

1 var gemüse = {

2 name: "Möhre",

3 details: {

4 color: "orange",

5 size: 12

6 },

7 toString: function() {return this.name + ", " + this.details.color;}

8 }

9 document.write("<br>" + gemüse); // Möhre, orange

10 //var obj = JSON.parse(gemüse); // => Uncaught SyntaxError: Unexpected token M

11 var jsn = JSON.stringify(gemüse);

12 document.write("<br>" + jsn); // "name":"Möhre","details":"color":örange",ßize":12

13 var obj = JSON.parse(jsn);

14 document.write("<br>" + obj.name); // Möhre

15 var a = [2,3,5,7,11,13,17]; // Array von Primzahlen

16 jsn = JSON.stringify(a)

17 document.write("<br>" + jsn); // [2,3,5,7,11,13,17]

18 var b = JSON.parse("[2,3,5,7,11,13,17]");

19 document.write("<br>" + b); // 2,3,5,7,11,13,17

20 var c = JSON.parse("2357111317");

21 document.write("<br>" + c); // 2357111317

Man erkennt an dem Quelltextbeispiel, dass stringify alle Attribute in Strings verwandelt undFunktionen (wie hier die toString-Methode) einfach ignoriert. Weitere Details, insbesonderezur Syntax von JSON, findet man im MDN.9

16.7.3 Ereignisbehandlung (Events und Event-Handler)JavaScript ermöglicht die Ausführung von Anweisungen, die durch Eingabeereignisse, soge-nannte Events, ausgelöst werden und in speziellen Methoden, den zuständigen Event-Handlern,implementiert sind. Events und Event-Handler stellen auf diese Weise ein wesentliches Binde-glied zwischen dem HTML-Dokument und JavaScript-Funktionen dar. Grundsätzlich funkio-niert die Ereignisbehandlung dabei wie folgt. Jede Anwenderaktion, also eine Mausbewegung,ein Mausklick, ein Tastendruck, löst ein Ereignis oder Event aus. Ist für das Element, in demdas Ereignis erzeugt wird, also beispielsweise eine Schaltfläche oder ein Textfeld, ein Ereignis-behandler registriert, so ruft dieser diejenige, auf die er referenziert, und führt sie aus.

Das Grundkonzept der Ereignisbehandlung in JavaScript ist klar und einfach: Für ein HTML-Element kann ein Event-Handler als ein Attribut festgelegt werden, das auf die JavaScript-Funktion oder die Anweisungfolge verweist, die bei Auslösen des entsprechenden Ereignis-

9 https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/JSON; weitere Infos zuJSON: https://developer.mozilla.org/en-US/docs/JSON

Page 153: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 153

ses auszuführen ist. Die Attribute der Ereignisbehandler sind daran zu erkennen, dass sie miton... beginnen. Beispielsweise ist der Ereignisbehandler für einen Mausklick onclick oder fürdas Loslassen einer Taste onkeyup. Im allgemeinen kann nicht jeder Ereignisbehandler in je-dem HTML-Element registriert werden, eine Auflistung der Ereignisbehandler und der HTML-Elemente, für die sie definiert sind, findet man auf selfhtml.org10, eine umfangreiche Liste vonEreignissen in der Mozilla Event Reference11. Das folgende Beispielprogramm zeigt einigeEreignisbehandler für Maus- und Touchscreen-Ereignisse:

1 <!DOCTYPE html>

2 <html>

3 <head>

4 <meta charset="UTF-8"/>

5 <script>

6 var machma = function(event) {

7 alert(event + " ausgelöst!");

8 };

9 </script>

10 </head>

11 <body>

12 <p onclick="machma('Klick');">

13 Wer hier klickt, kann was erleben!

14 </p>

15 <p ondblclick="machma('Doppelklick');">

16 Wer hier doppelklickt, auch!

17 </p>

18 <p onwheel="machma('Mausrad');">

19 Hier müssen Sie das Mausrad drehen!

20 </p>

21 <p ontouchmove="machma('Touchmove');">

22 Hier müssen Sie wischen!

23 </p>

24 </body>

25 </html>

Das Programm ist für Ihr Endgerät abrufbar über http://haegar.fh-swf.de/JavaScript/event-handler.html.

16.7.4 DateDas Objekt Date regelt in JavaScript alle Berechnungen mit Datum und Zeit. Grundlage ist dieUnix-Zeit in Millisekunden mit dem Nullpunkt 1.1.1970, 0:00 Uhr UTC (Universal CoordinatedTime). Es gibt mehrere Konstruktoren für ein Date-Objekt

1 var today = new Date(); // liefert das aktuelle Datum und Uhrzeit

2 var birthday = new Date("December 17, 1985 03:24:00");

3 var geburtstag = new Date(1985,11,17);

4 var anniversaire = new Date(1985,11,17,3,24,0);

Daneben gibt es noch einen Konstruktor, der als Argument die Unixzeit in Millisekunden er-wartet. Zwar gibt es eine Reihe von Methoden für das Objekt, insbesondere zur Ausgabe von

10 http://de.selfhtml.org/javascript/sprache/eventhandler.htm11 https://developer.mozilla.org/en-US/docs/Mozilla_event_reference

Page 154: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

154 Andreas de Vries

Datum und Uhrzeit, jedoch sind die Ausgabeformate nur wenig spezifiziert und daher in ihrerDarstellung browserabhängig.12 Mit den folgenden Methoden kommt man in der Regel jedochhin:

1 var tag = ["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"];

2 var jetzt = new Date();

3 document.write("Heute ist " + tag[jetzt.getDay()] + ", der ");

4 document.write(jetzt.getDate() + "." + (jetzt.getMonth()+1) + "." + jetzt.getFullYear());

5 var minuten = Math.floor(jetzt.getMinutes() / 10) + "" + jetzt.getMinutes() % 10;

6 document.write(", " + jetzt.getHours() + "." + minuten + " Uhr");

7 document.write(", oder: " + jetzt.toISOString());

Eine Liste der möglichen Methoden für ein Date-Objekt findet man beispielsweise auf self-html.de.13

16.8 Funktionen und CallbacksJavaScript ermöglicht funktionale Programmierung. In einer funktionalen Programmiersprachekönnen Funktionen definiert werden und es gibt keinen Unterschied zwischen Daten und Funk-tionen, Funktionen können also auch in Variablen gespeichert und als Parameter übergebenwerden [12, S. 6]. Die funktionale Programmierung steht damit im Gegensatz zur imperativenProgrammierung, denn die Trennung von Daten und Programmlogik wird aufgehoben und jedeVariable kann nur einmal einen Wert bekommen (final in Java). Rein funktionale Sprachenhaben sogar gar keine Variablen oder Schleifen, denn ein Algorithmus wird hier durch eineAbfolge von Funktionsaufrufen ausgeführt; für Wiederholungen werden also keine Schleifenverwandt, sondern ausschließlich Rekursionen. So werden mathematisch unsinnige Ausdrückeder imperativen Programmierung wie x=x+1 vermieden. Andererseits widerspricht die funktio-nale Programmierung dem objektorientierten Paradigma, gemäß dem Objekte im Laufe ihresLebenszyklus verschiedene Zustände annehmen können, die Attribute also Veränderliche seinmüssen. JavaScript ist ein Kompromiss aus beiden Ansätzen, indem es beide Programmierpa-radigmen ermöglicht.

Funktionen gehören zu einem der elementaren Datentypen von JavaScript und bilden diemodularen Einheiten der Sprache [2, S. 29]. Eine Funktion wird definiert durch das Schlüssel-wort function, ihren Namen, eine von runden Klammern eingeschlossene Liste von durch Kom-mas getrennten Parametern, und den durch geschweifte Klammern umschlossenenen Funkti-onsrumpf, der die Anweisungen der Funktion enthält. Der Rückgabewert der Funktion wird mitdem Schlüsselwort return ausgegeben:

1 function f(x,y) {

2 return x*x - y*y;

3 }

4 document.write("f(5,3) = " + f(5,3)); // => 16

Als funktionale Programmiersprache ermöglicht JavaScript die Definition anonymer Funktio-nen, auch „Lambda-Ausdrücke“ genannt:

1 var g = function(x,y) {return x*x + y*y}

2 document.write("<br>g(5,3) = " + g(5,3)); // => 34

12 Eine der Methoden, getYear(), ist sogar deutlich schlecht programmiert, sie gibt die Differenz der Jahreszahlmit 1900 zurück!

13 http://de.selfhtml.org/javascript/objekte/date.htm [2016-07-17]

Page 155: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 155

Damit kann eine Funktion in einer Variablen gespeichert werden; oder genauer gesagt als Refe-renz auf eine anonyme Funktion. Solche Funktionsreferenzen werden Rückruffunktionen oderCallbacks genannt, wenn sie in andere Funktionen als Argument eingesetzt und von diesenaufgerufen werden.

16.8.1 RückruffunktionenRückruffunktionen sind ein wichtiges Programmierkonzept der funktionalen Programmierung.Die Programmierung mit Rückruffunktionen folgt dem Entwurfsmuster der Kontrollflussum-kehr (Inversion of Control, IoC), denn in ein bereits vorher definiertes Programmmodul (dieaufrufende Funktion) bzw. eine gegebene Infrastruktur (z.B. die API) kann „nachträglich“ aus-zuführender Quelltext definiert werden. Viele JavaScript-Bibliotheken und Frameworks basie-ren auf diesem Prinzip. Als ein einfaches Beispiel einer Rückruffunktion soll das folgende kurzeProgramm dienen:

var callback = function(x) {return x*x;};

var quadrate = [1, 2 , 3, 4, 5].map(callback);

document.write(quadrate); // => 1,4,9,16,25

Hier wird die Funktion callback(x) = x2 von der API-Funktion map eines Arrays aufgerufenund ausgeführt. Ihr „Rückruf“ ergibt am Ende ein Array, das in jedem Eintrag den Quadratwert

Hauptprogramm

API

[...]

map

callscallback

calls

Abbildung 16.3: Aufrufstruktur einer Rückruffunktion. (Modifiziert nach https://en.wikipedia.org/wiki/

File:Callback-notitle.svg)

des originalen Arrays enthält. Die Aufrufstruktur ist in Abbildung 16.3 skizziert.Es gibt zwei Arten von Rückruffunktionen. Eine Rückruffunktion heißt blockierend, oder

auch synchron, wenn sie mit ihrer Referenz aufgerufen wird und ihr Ausführungsergebnis ab-gewartet wird, um weiterverarbeitet zu werden. Das obige Programmierbeispiel ist eine solchesynchrone Rückruffunktion.

Bei einer verzögerten (deferred) oder asynchronen Rückruffunktion wird die Rückruffunkti-on in einem anderen Prozess oder Thread ausgeführt, das Hauptprogramm wartet aber nicht aufdas Ergebnis der Rückruffunktion. Stattdessen wird das Ergebnis der Rückruffunktion „mög-lichst schnell“ verarbeitet, wenn es eingetroffen ist. Typische Anwendungsfälle solcher ver-zögerten Rückruffunktionen sind Ereignisbehandler, die nach einem gefeuerten Ereignis dieRückruffunktion ausführen, oder Aufrufe serverseitiger Skripte im Web.

In der nebenläufigen Programmierung spricht man bei asynchronen Rückruffunktionen auchoft von Promises.14

16.8.2 ClosuresIm Gegensatz zu vielen Programmiersprachen wie Java können in JavaScript Funktionen auchinnerhalb von Funktionen definiert werden. Eine solche innere Funktion hat wie jede Funktion

14 https://docs.angularjs.org/api/ng/service/$q#the-promise-api

Page 156: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

156 Andreas de Vries

Zugriff auf ihre eigenen Variablen, aber auch auf die Variablen der Funktion, in der sie defi-niert ist. Eine innere Funktion heißt Closure.15 Mit Closures kann man Funktionenscharen oder„Funktionenfabriken“ programmieren, also Funktionen, die parameterabhängig Funktionen zu-rückgeben:

1 var fabrik = function(name) {

2 return function(instrument) {

3 return name + " spielt " + instrument;

4 }

5 };

6 var a = fabrik("Anna");

7 var b = fabrik("Bert");

8

9 document.write(a("Geige") + ", " + b("Bass")); // Anna spielt Geige, Bert spielt Bass

Die äußere Funktion definiert hier eine Variable name, auf die die innere anonyme Funktion auchZugriff hat. Bei jedem Aufruf der äußeren Funktion wird der jeweilige Wert der Variablen inder inneren Funktion „eingefroren“ und mit ihr zurückgegeben. Daher gibt die Funktion anna()

einen anderen Wert zurück als die Funktion bert().Wofür braucht man Closures? Ein wichtiger Anwendungsfall für Closures ist das Verbergen

von Hilfs- oder Arbeitsfunktionen, die nach außen vor dem Anwender gekapselt werden sollen.(In Java bis Version 7 war das nur mit private Objektmethoden möglich.) Als Beispiel seidie folgende effiziente Berechnung der Fibonacci-Zahlen f0 = 0, f1 = 1, f2 = 1, f3 = 2, . . . ,fn = fn−1 + fn−2 durch eine Rekursion innerhalb der aufzurufenden Funktion angegeben:

1 var f = function (n) {

2 var c = function (f1, f2, i) { // innere "Arbeitsfunktion" (Closure)

3 if (i == n) return f2;

4 return c(f2, f1+f2, i+1);

5 }

6 if (n.toFixed(0) != n) return NaN; // nur für ganze Zahlen definiert!

7 if (n <= 0) return 0;

8 return c(0,1,1);

9 }

Ruft man nun die Funktion f mit einer natürlichen Zahl n auf, so wird die innere Arbeitsfunktionc in Zeile 8 mit den Startwerten f0 = 0 unf f1 = 1 und dem Zähler i = 0 aufgerufen, die sichwiederum in Zeile 6 selbst aufruft, falls keine der Abbruchkriterien erfüllt ist. Bei jedem Aufrufenthält der zweite Parameter von c die Summe der letzten beiden Fibonacci-Zahlen, die

Zudem finden Closures Einsatz bei dem Funktionalkalkül, also der Algebra mit Funktionen.Man kann beispielsweise die Summe f +g zweier Funktionen f , g : R→ R definieren, indemman ( f + g)(x) = f (x)+ g(x) definiert. In JavaScript könnte der Additionsoperator für zweiFunktionen beispielsweise so aussehen:

1 var add = function(f, g) {

2 return function(x) {return f(x) + g(x);};

3 };

4

5 var f = function(x) {return x*x - 1;};

6 var g = function(x) {return x*x + 1;};

7 var x = 2;

15 http://jibbering.com/faq/notes/closures/#clClose [2016-07-17]

Page 157: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 157

8 document.write(add(f,g)(x) + ", " + max(f,g)(x)); // => 8, 5

16.8.3 IIFEEin von JavaScript-Entwicklern oft verwendetes Programmiermuster ist ein „sofort aufgerufe-ner Funktionsausdruck“ (immediately invoked function expression, IIFE) meist mit Closures.Hierbei wird eine anonyme Funktion deklariert und sofort aufgerufen [17]:

Listing 16.2: Ein einfaches IIFE(function() {

var tuwas = function() {

document.write("a="+ a);

}

var a = 1;

tuwas();

})(); // => “a=1”

Dieser Ausdruck tut zunächst nichts Besonderes, die Funktion tuwas wird ausgeführt und ver-arbeitet die Variable a. Funktionsdeklaration und Anweisungen sind in eine anonyme Funktion(Zeile 1) gekapselt, die sofort ausgeführt wird (letzte Zeile), also schematisch dargestellt:

(function() {...}) ();

Die Funktion tuwas ist hier also eine Closure, die auf die Variable a zugreifen kann, auch wenndie äußere anonyme Funktion bereits abgelaufen ist. Das Programm würde aber dasselbe aus-geben, wenn man die erste und letzte Zeile einfach wegließe. Nur wären dann tuwas und dieVariable a global definiert, und genau das ist das Problem: Globale Variablen sollten in Ja-vaScript in komplexen Systemen möglichst vermieden werden. Durch IIFEs lässt sich derenAnzahl deutlich reduzieren. Denn in Listing 16.2 beispielsweise sind die Variable a und dieFunktion tuwas außerhalb der anonymen Funktion unbekannt.

16.8.4 RekursionenIn rein funktionalen Sprachen können Wiederholungen nicht durch Schleifen, sondern nur durchRekursionen durchgeführt werden, also durch Selbstaufrufe von Funktionen. Als ein einfachesBeispiel sei die Berechnung der Fakultät angegeben:

1 var factorial = function (n) {

2 if (n < 0) return NaN;

3 if (n === 0) return 1;

4 return n * factorial(n-1);

5 }

6 document.write("<br>factorial(5) = " + factorial(5)); // => 120

Hierbei ist NaN in JavaScript ein globales Objekt und wird in der Regel als Ergebnis von imReellen nicht erlaubten mathematischen Operationen wie Division durch 0 oder

√−1 zurück-

gegeben.16

In JavaScript wird häufig eine Rekursion mit einer definierten Verzögerung aufgerufen. Da-zu muss die Funktion setTimeout verwendet werden,17 deren erstes Argument die aufzurufendeFunktion und deren zweites die Verzögerungszeit in Millisekunden ist:

16 https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/NaN [2016-07-17]17 http://developer.mozilla.org/en/DOM/window.setTimeout [2016-07-17]

Page 158: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

158 Andreas de Vries

1 var rekurs = function(n) {

2 if (n <= 0) return;

3 setTimeout("rekurs("+(n-1)+")",1000);

4 console.log("Aufruf rekurs("+n+")");

5 }

6 rekurs(5);

Um eine Funktion mit Argumenten aufzurufen, muss sie als String mit dem gewünschten Argu-mentwert aufbereitet werden.18 Man erkennt beim Ausführen des Skripts insbesondere in derKonsole des Firefox, in der die Uhrzeiten der Ausgaben protokolliert werden, dass setTimeout

zwar den Aufruf der angegebenen Funktion verzögert, den weiteren Ablauf der aufrufendenFunktion jedoch nicht aufhält: Die Ausgabe erscheint stets direkt nach Aufruf der Funktion,aber eine Sekunde vor dem Rekursionsaufruf der nächsten Funktion.

16.8.5 Funktionen höherer OrdnungEine Funktion höherer Ordnung ist eine Funktion, die als Argument eine Funktion erwartetoder deren Ergebnis eine Funktion ist. Beispielsweise kann die Kepler’sche Fassregel (oderauch Simpson-Regel)

I f (a,b)≈b−a

6(

f (a)+4 f(a+b

2

)+ f (b)

)(16.1)

als Näherungsformel für das Integral I f (a,b) =∫ b

a f (x)dx einer integrierbaren Funktion f :[a,b]→ R mit a, b ∈ R in JavaScript wie folgt implementiert werden:

1 var I = function (f, a, b) {

2 return (b-a)/6 * (f(a) + 4*f((a+b)/2) + f(b));

3 }

4

5 var f = function(x) {return 3*x*x;}

6 var g = function(x) {return 1/x;}

7 var h = function(x) {return Math.sqrt(1 - x*x);}

8

9 document.write("I(f,0,1) = " + I(f, 0, 1)); // => 1

10 document.write("<br/>I(g,1,e) = " + I(g, 1, Math.E)); // => 1.0078899408946134

11 document.write("<br/>I(h,0,1) = " + I(h, 0, 1)); // => 0.7440169358562924

Die tatsächlichen Werte sind∫ 1

03x2 dx = x3

∣∣∣10= 1,

∫ e

1

dxx

= lnx∣∣∣e1= 1 (16.2)

und [19, S. 163]

∫ 1

0

√1− x2 dx =

arcsinx+ x√

1− x2

2

∣∣∣∣∣1

0

4≈ 0,78539816339745. (16.3)

(Für die Herleitung dieser Gleichung mit Integration durch Substitution siehe z.B. [4, §19.15];der Graph der Funktion

√1− x2 beschreibt in dem Intervall [0,1] einen Viertelkreis mit Radius

1.)18 http://javascript.about.com/library/blrecursive.htm [2016-07-17]

Page 159: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 159

16.9 DOMDas DOM (Document Object Model), ist eine Schnittstellenbeschreibung für API’s, die Par-ser oder Browser zur Darstellung von HTML- oder XML-Dokumenten verwenden können.Für JavaScript (aber auch für jede andere Programmiersprache) ist im DOM festgelegt, welcheHTML-Elemente als Objekte in zur Verfügung stehen und wie man dynamisch neue Elementehinzufügen oder löschen kann, aber auch, welche Event-Handler für eine clientseitige Interakti-on implementiert werden können. Obwohl das Grundkonzept des DOM als eine Baumstrukturvon Knoten einfach ist, sind die Bezeichnungen und Dokumentationen zunächst etwas verwir-rend. Neben der Standardreferenz sei daher die DOM-API von Gecko, dem HTML-Interpreter(„Rendering Machine“) der Mozilla-Programme,

https://developer.mozilla.org/en-US/docs/Gecko_DOM_Reference

empfohlen. Bevor wir das DOM in seinen für uns wesentlichen Details untersuchen sei nochseine Historie erwähnt. Das DOM erschien sukzessive in mehreren Versionen, bis zur Version 3Level genannt. Level 1 wurde im Oktober 1998 veröffentlicht, Level 2 im November 2000 undLevel 3 im April 2004 .

Das DOM trägt seinen Namen „Objektmodell“ vor allem, da es HTML- oder XML-Elementeals Objekte darstellt und in gegenseitige Beziehungen setzt, nämlich in eine Baumhierarchie wiein Abbildung 16.4 skizziert. In jedem Browser ist eine Objekthierarchie mit dem Wurzelobjekt

window

documentnavigator history

Abbildung 16.4: Objekt-Hierarchie des Browsers mit wichtigen Objekten, insbesondere das document-Objekt.

window vorhanden (Abbildung 16.4). Eines seiner Kindelemente ist document und bestimmt denim Browserfenster sichtbaren Inhalt. Das Objekt navigator liefert Informationen über den ak-tuellen verwendeten Browser, und history über die im aktuellen Tab oder Frame bisher aufge-rufenen Webseiten.19

16.9.1 Grundlegende Objekte des DOM: document und element

Das zentrale Interface des DOM ist Node,20 das einen allgemeinen Knoten des DOM-Baumesbeschreibt. Ein Node im DOM hat u.a. stets einen parentNode und eine Liste von childNodes

als Attribute und Methoden zum Hinzufügen oder Löschen von Kindknoten (appendChild,removeChild). Die wichtigsten Implementierungen von Node sind document und element. Einelement21 ist ein allgemeines Element eines HTML- oder XML-Dokuments.

Das document-Objekt22 repräsentiert den Inhalt des darzustellenden Dokuments, also denInhalt des Browser-Fensters. Mit der Methode write() des document-Objekts können wir mitJavaScript in das Browser-Fenster schreiben. Eine weitere wichtige Methode des document-Objektes ist getElementById("ID"), die ein Element des Dokuments als Ergebnis liefert, dessenAttribut "id" als Wert den übergebenen String hat. Beide Methoden haben wir bereits als ein-führende Beispiele für JavaScript-Ausgaben im Abschnitt 16.1 kennen gelernt.

19 https://developer.mozilla.org/en-US/docs/Web/API/Window20 https://developer.mozilla.org/en-US/docs/DOM/Node, http://de.selfhtml.org/javascript/objekte/

node.htm [2016-01-18]21 https://developer.mozilla.org/en-US/docs/DOM/Element [2016-01-18]22 https://developer.mozilla.org/en-US/docs/DOM/Document [2016-01-18]

Page 160: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

160 Andreas de Vries

CSS-Anweisungen mit der Eigenschaft style

Ein element-Objekt hat unter anderem die Eigenschaft style, mit der CSS-Deklarationen überJavaScript angewiesen werden können.21 Hierbei kann zu jedem HTML-Element dessen style-Attribut per JavaScript verändert werden, indem das zu jeweilige CSS-Attribut mit einem neu-en Wert belegt wird. Dabei ist zu beachten, dass ein CSS-Attribut mit einem Bindestrich inJavaScript mit der Binnenmajuskel-Notation (CamelCase) übernommen wird, da dort der Bin-destrich als Minuszeichen eine arithmetische Rechenoperation darstellen würde. In dem fol-genden Beispielprogramm wird die Hintergrundfarbe des Textes in einem span-Element perSchaltfläche verändert, indem die Funktion aendereFarbe mit der gewünschten Hintergrundfar-be aufgerufen wird.

1 <!DOCTYPE html>

2 <html>

3 <head>

4 <meta charset="UTF-8"/>

5 <title>CSS-Anweisungen über JavaScript und DOM</title>

6 <script>

7 var aendereFarbe = function(farbe) {

8 document.getElementById("text").style.backgroundColor = farbe;

9 }

10 </script>

11 </head>

12 <body>

13 Hintergrundfarbe ändern:

14 <button onclick="aendereFarbe('green');">Grün</button>

15 <button onclick="aendereFarbe('red');">Rot </button>

16 <span id="text">Die Zeichen an der Wand.</span>

17 </body>

18 </html>

Die entscheidende Anweisung dazu ist in Zeile 8, wo das CSS-Attribut background-color inBinnenmajuskelnotation in JavaScript als Attribut backgroundColor des Elementattributs style

festlegt.

Das folgende auf Crockford [2, S. 42] zurückgehende Programm beispielsweise verändertmit einer Closure langsam die Hintergrundfarbe des Browserfensters (das Element document.body)von gelb (#ffff00) auf weiß (#ffffff):

1 var fade = function(element, delay) {

2 var level = 0;

3 var step = function() {

4 var hex = level.toString(16); // level in hexadezimal

5 element.style.backgroundColor = "#ffff" + hex + hex;

6 if (level < 15) {

7 level += 1; // Variable der äußeren Funktion!

8 setTimeout(step, delay); // Rekursion nach delay [ms]

9 }

10 };

11 step(); // erster Aufruf von step

12 };

13

Page 161: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 161

14 fade(document.body, 100);

Hier rufen wir in Zeile 14 die Funktion fade auf und übergeben ihr das DOM-Objekt document.body,also den Knoten des HTML-Dokuments, der durch das Tag <body> erzeugt wurde, und die Ver-zögerungszeit delay in Millisekunden. Die Methode fade setzt zunächst die Variable level auf0 und definiert als Closure eine rekursive Funktion step, in der level bei jedem hochgezähltwird und der Rekursionsaufruf mit Hilfe von setTimeout um delay verzögert wird. In Zeile 11wird dann step erstmals aufgerufen und die Rekursion gestartet. Bei jedem weiteren Aufrufvon step wird der Wert der Variablen level erhöht und als neuer Wert in step verwendet. DieVariablen element, delay und level sind hier aus Sicht der Closure also eine „globale“ Variable.Eleganter wäre sicherlich eine Rekursion, die ohne solche grlobalen Variablen auskommt, z.B.indem sie sie als Parameter übergibt:

var step = function(element, delay, level) {

...

if (level < 15) {

step(element, delay, level + 1);

}

};

Leider ermöglicht setTimeout jedoch nur den verzögerten Aufruf von Funktionen ohne Para-metern.

Hinzufügen und Löschen von Elementen

In dem folgenden Beispielprogramm wird mit Hilfe der Standardmethoden des DOM createElement

in Zeile 9 und appendChild in Zeile 10 durch JavaScript dynamisch ein <li>-Element an das<ol>-Element mit der id angehängt.

Listing 16.3: DOM-Manipulation1 <!DOCTYPE html>

2 <html>

3 <head>

4 <meta charset="UTF-8"/>

5 <title>DOM-Elemente</title>

6 <script>

7 var hinzufuegen = function() {

8 var wurzel = document.getElementById('liste');

9 var neu = document.createElement('li');

10 var neuerText = document.createTextNode("Die Zeichen an der Wand.");

11 neu.appendChild(neuerText);

12 wurzel.appendChild(neu);

13 }

14 var loeschen = function() {

15 var element = document.getElementById('liste');

16 if (element.hasChildNodes()) {

17 element.removeChild(element.lastChild);

18 }

19 }

20 </script>

21 </head>

22 <body>

Page 162: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

162 Andreas de Vries

23 <button onclick="hinzufuegen();">Neuer Text</button>

24 <button onclick="loeschen();">Löschen</button>

25 <ol id="liste"></ol>

26 </body>

27

28 </html>

Entsprechend wird in Zeile 18 das letzte Kindelement des <ol>-Elements mit der id mit derMethode removeChild gelöscht. Damit es nicht zu einem Laufzeitfehler kommt, wenn keinKindelement des <ol>-Elements mehr vorhanden ist, wird das Löschen nur durchgeführt, wenndie Prüfung auf Existenz von Kindknoten mit der Methode hasChildNodes in Zeile 17 positivausgeht. Der DOM-Baum des Dokuments ist in Abbildung 16.5 skizziert. Die gestrichelt ge-

document

<head>

<meta> charset="UTF-8"

<title> DOM-Elemente

<script> var hinzufuegen = function() { ...

<body>

<input>

type="button"

value="Neuer Text"

onclick="Hinzufügen"

<input> ...

<ol> <li> <ol>

Abbildung 16.5: Der DOM-Baum des HTML-Dokuments aus Listing 16.3.

zeichneten Knoten werden durch das JavaScript-Programm je nach Eingabe hinzugefügt odergelöscht.

16.9.2 Das window-Objekt

Das Browser-Fenster, in dem die HTML-Seite, die den JavaScript-Code enthält, dargestelltwird, wird durch ein window-Objekt repräsentiert.

Das window-Objekt verfügt über Methoden wie prompt() alert() oder confirm(), mit deneneigene Fenster zur Ein- und Ausgabe geöffnet werden können.

Darüberhinaus hat das window-Objekt Attribute, die sich von JavaScript aus steuern lassen.Dazu gehört die Statuszeile (Attribut status), der URL, der gerade dargestellt wird (location)oder die URL’s der Seiten, die bis jetzt dargestellt wurden (history).

Tatsächlich sind sind sogar alle anderen JavaScript-HTML-Objekte entweder selbst Attribu-te des window-Objekts oder Attribute von Attributen des window-Objekts; so auch das document-Objekt, welches wir bereits öfter zum Schreiben in das Browser-Fenster benutzt haben. Daswindow-Objekt ist also die Wurzel der Objekthierarchie in JavaScript.

Das window-Objekt verfügt über drei Methoden, mit denen Benutzerinteraktion möglich ist.Die erste (prompt()) haben wir bereits kennengelernt. prompt() öffnet ein eigenes Fenster ober-halb des Browser-Fensters. Das Fenster enthält zwei Bereiche: im ersten wird eine Meldung

Page 163: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 163

dargestellt (erster Parameter von prompt()), im zweiten kann der Benutzer Eingaben tätigen(der zweite Parameter von prompt() ist eine Vorgabe im Eingabefeld).

confirm() erwartet vom Benutzer eine Bestätigung. Der einzige Parameter von confirm()

ist eine Meldung, die im von confirm() aufgespannten Fenster dargestellt wird. Der Benutzerkann mit einem OK-Button bestätigen (confirm() liefert dann true zurück) oder mit einemAbbruch-Button abbrechen (confirm() liefert false zurück). Betrachten wir dazu folgendesProgramm:

1 <!DOCTYPE html>

2 <html>

3 <head>

4 <meta charset="UTF-8"/>

5 <script>

6 var factorial = function (n) {

7 if (n < 0) return NaN;

8 if (n === 0) return 1;

9 return n * factorial(n-1);

10 }

11

12 var einlesen = function () {

13 var n = document.getElementById("eingabe").value;

14 var wirklich = true;

15 if (n > 150) {

16 wirklich = confirm("Wirklich "+n+"! berechnen? Das kann lange dauern . . .");

17 }

18 if (wirklich) {

19 document.getElementById("label").innerHTML = n + "! = " + factorial(n);

20 } else {

21 document.getElementById("label").innerHTML = "Berechnung von "+n+"! abgebrochen.";

22 }

23 }

24 </script>

25 </head>

26 <body>

27 <input type="text" id="eingabe"/>

28 <input type="button" value="Rechnen" onclick="einlesen();"/>

29 <p>Ergebnis: <span id="label"></span>.</p>

30 </body>

31 </html>

Hier muss der Anwender die Frage bestätigen, ob die Zahl, deren Fakultät berechnet werdensoll, größer als 150 sein darf. In diesem Fall wird ein confirm-Fenster aufgebaut. Wählt der Be-nutzer „OK“, gibt confirm einfach true zurück. Der Boole’schen Variablen wirklich wird damitder Wert true zugewiesen und die Fakultäten werden berechnet. Klickt der Benutzer hingegenAbbrechen, wird von confirm false zurückgegeben, wirklich wird damit false zugewiesen,und die Berechnung findet nicht statt.

Page 164: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

164 Andreas de Vries

16.10 XMLHttpRequest und AJAXEin weiteres wichtiges Objekt in JavaScript ist XMLHttpRequest. Es ermöglicht, über einen ausJavaScript ausgelösten Request, also eine Netzanfrage, Daten von einem beliebigen URL zuladen. Es spielt eine Schlüsselrolle bei AJAX-Anwendungen. Anders als der Name suggeriert,kann XMLHttpRequest nicht nur XML-Daten laden, sondern beliebige Formate, also auch Binär-dateien wie Bilder und Streams. Ebenso kann es nicht ausschließlich HTTP-Requests auslösen,sondern auch andere Anfragen über andere Protokolle wie FTP oder FILE.

Als Objekt besitzt es als wichtigste Attribute readystate, response und status, als wich-tigste Methoden open und send sowie den Event-Handler onreadystatechange:23

XMLHttpRequestreadystate : intresponse : Stringstatus : intonreadystatechange()

open(method, url [, ...])

send([data])

Um einen HTTP-Request auszulösen, muss zunächst ein XMLHttpRequest-Objekt mit new in-stanziiert werden:

var request = new XMLHttpRequest();

Mit der Methode open wird ein Request initialisiert. Sie benötigt dafür mindestens zwei Para-meter vom Typ String, sowie drei optionale Parameter:

void open(String method, String url, [boolean async, String user, String password])

Hierbei bezeichnet method die HTTP(S)-Methode, die einen der Werte "GET", "POST", "PUT"oder "DELETE" annehmen kann und url der angefragte URL, also der Pfad zur angefragten Da-tei. Der optionale Boole’sche Parameter async bestimmt, ob die Anfrage asynchron ablaufenoder das Programm die Antwort abwarten soll; er ist im Default auf true gesetzt. Die beidenoptionalen Parameter user und password schließlich ermöglichen eine etwaig notwendige Au-thentifizierung für Zugang zu dem URL. Mit der Methode send wird die Anfrage abgeschickt.Dazu muss sie vorher mit open initialisiert sein. Ist sie asynchron initialisiert, so läuft das Pro-gramm weiter, andernfalls wird das Ende der Methode abgewartet. Die Methode kann optionalmit zu übertragenden Daten als Parameter aufgerufen werden, z.B. Formulardaten. Die Funk-tion onreadystatechange ist ein Event Handler, der auf Änderungen des Attributs readyState

reagiert, das wiederum einen der 5 möglichen Werte 0, 1, 2, 3, 4 annehmen kann:

readyState Zustand Bedeutung0 UNSENT open ist noch nicht aufgerufen1 OPENED send ist noch nicht aufgerufen2 HEADERS_RECEIVED send ist aufgerufen und Headers und Status des

Requests sind verfügbar3 LOADING Daten werden empfangen4 DONE Die Anfrage ist erledigt

Die beiden ersten Zustände dienen der Vorbereitung der Kommunikation, der Request wird erstdurch die send()-Methode ausgelöst. Diese Kommunikation läuft übrigens asnchron ab, d.h.die send()-Methode blockiert oder beeinflusst nicht andere JavaScriptprogramme der Seite.

23 https://developer.mozilla.org/en/DOM/XMLHttpRequest

Page 165: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 165

Diese Möglichkeit, asynchrone Anfragen an den Server zu stellen, ohne dass die dargestellteWebseite blockiert wird oder gar neu geladen werden muss, bildet die technische Grundlage fürAJAX-Anwendungen, die wir in Abschnitt 16.10.2 behandeln werden.

Der Event Handler ist zunächst nur eine „leere“ Funktion und muss implementiert werden,so wie wir es ja auch von den Event-Handlern des DOM bereits kennen. Üblicherweise wird hierdie Antwort der Anfrage verarbeitet, die wiederum in dem Attribut response gespeichert ist. Im

UNDEFINED

readyState 0

OPENED

readyState 1

HEADERS_RECEIVED

readyState 2

LOADING

readyState 3

DONE

readyState 4

Objekter-zeugung open()

send()

open

()

send

()

Objekt-löschung

Abbildung 16.6: Zustandsdiagramm eines XMLHttpRequest-Objekts. Vgl. [5, S. 26].

Überblick ergibt sich damit das Zustandsdiagramm eines XMLHttpRequest-Objekts nach Ab-bildung 16.6. Die Details sind im technischen Report unter http://w3.org/TR/XMLHttpRequestdes W3-Konsortiums festgelegt.

Beginnen wir mit einem einfachen Beispiel, das die vier Schritte Erzeugung eines Requests,Implementierung des Event Handlers, Öffnen und Senden eines Requests zeigt:

1 var request = new XMLHttpRequest();

2 request.onreadystatechange = function() { // Event Handler

3 if (request.readyState === 4) { // Request ist erledigt

4 document.write(request.response);

5 }

6 }

7 request.open("GET", "http://localhost/");

8 request.send();

Die Reihenfolge der Anweisungen bei der Ausführung des Programms entspricht dabei nichtganz der Reihenfolge ihrer Implementierung: Der Event-Handler onreadystatechange wird fürdas Request-Objekt zwar zu Beginn des Objektes implementiert, aber erst nach Beenden derAnfrage verarbeitet, also nach dem send. Er sollte aber natürlich bereits implementiert sein,wenn der Request gesendet wird.

Zu beachten ist, dass bei den Standardeinstellungen des Webservers eine Anfrage in Ja-vaScript nur für denselben Server möglich ist, auf dem sich auch das JavaScript-Programmbefindet. Möchte man über XMLHttpRequest einen anderen Server aufrufen, so müssen die Ein-stellungen dieses Servers entsprechend angepasst sein. Man spricht in diesem Falle von CrossOrigin Resource Sharing (CORS).24 Damit JavaScript einen XMLHttpRequest weiter verarbei-tet, muss der Server nämlich die Antwort mit dem HTTP-Header

Access-Control-Allow-Origin: *

24 http://www.w3.org/wiki/CORS_Enabled

Page 166: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

166 Andreas de Vries

senden. Möglich ist auch die Variante Access-Control-Allow-Origin: http://foo.bar, wobeifoo.bar die Domain ist, von der die Anfrage, also das JavaScript-Programm, kommt. Ein PHP-Skript kann diesen Header individuell senden, wenn es mit der Zeile

1 header("Access-Control-Allow-Origin: *");

beginnt.Mit dem Standardobjekt FormData kann man dynamisch erstellte Formulardaten versen-

den.25 Ein einfaches Beispiel übermittelt die Formulardaten x=2 an ein PHP-Skript:

1 var request = new XMLHttpRequest();

2 request.onreadystatechange = function() { // Event Handler

3 if (request.readyState === 4) {

4 document.write(request.response);

5 }

6 };

7 request.open("POST", "http://haegar.fh-swf.de/AJAX/spiegel.php");

8 var data = new FormData();

9 data.append("x",2);

10 request.send(data);

Mit der folgenden Änderung der Zeile 9 erhält man sogar die Übertragung eines dynamisch inJavaScript erzeugten Arrays prim:

1 data.append("prim[]",2); data.append("prim[]",3); data.append("prim[]",5);

16.10.1 Aktionen nach dem Request: onreadystatechange

Bislang haben wir nur Beispiele von XMLHttpRequest-Objekten kennengelernt, deren Event-Handler onreadystatechange einfach nur die empfangene Antwort des Servers, d.h. den Stringrequest.response, ausgibt. Häufig werden allerdings komplexere Daten übermittelt, die in demEvent-Handler weiter verarbeitet werden sollten. Grundsätzlich können diese Daten als beliebi-ger Text vorliegen, üblich sind aber Strings in den drei folgenden Formaten HTML, JSON undXML. Die Verarbeitung

• HTML-Strings werden dabei in der Regel nicht weiterverarbeitet und unverändert darge-stellt, also so wie in den obigen XMLHttpRequest-Beispielen mit request.response.

• Ein JSON-String kann mit der Standardmethode JSON.parse() direkt in ein JSON-Objektumgewandelt werden, also beispielsweise

var objekt = JSON.parse(request.respnse);

Dieses Objekt kann nun in JavaScript beliebig weiterverarbeitet werden.

• Ein XML-String kann manuell geparst werden. Ist die Serverantwort beispielsweise einSVG-String, so kann die Grafik direkt im Browser dargestelllt werden.

Betrachten wir als Beispiel das folgende Programm, das die Daten des aktuellen Sondernange-bots im JSON-Format erhält und im Event-Handler verarbeitet:

25 https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/FormData/ [2016-07-17]; siehe auch:https://developer.mozilla.org/en/DOM/XMLHttpRequest/FormData/Using_FormData_Objects

Page 167: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 167

1 <!DOCTYPE html>

2 <html>

3 <head>

4 <meta charset="UTF-8"/>

5 <script>

6 var ladenJSON = function() {

7 var request = new XMLHttpRequest();

8 request.onreadystatechange = function() {

9 if (request.readyState === 4 && request.status === 200) {

10 var artikel = JSON.parse(request.response);

11 var element = document.getElementById("angebot");

12 var ausgabe = "Kaufen Sie unseren " +

13 artikel.name + " mit der Nummer " +

14 artikel.id + " für " + artikel.preis + " &euro;!";

15 element.innerHTML = ausgabe;

16 }

17 };

18 request.open("GET", "http://haegar.fh-swf.de/json-artikel.php");

19 request.send();

20 }

21 </script>

22 </head>

23 <body>

24 <h1>Unser Preisknaller!</h1>

25 <p id="angebot">Klicken Sie, um unser heutiges Sonderangebot zu sehen:</p>

26 <input type="button" value="JSON Eingabe" onclick="ladenJSON();";>

27 </body>

28 </html>

Bei Aufruf der HTML-Datei erscheint unter der Überschrift zunächst der Text „Klicken Sie, umunser heutiges Sonderangebot zu sehen:“. Klickt man den Button, so wird sein Event-Handleronclick aufgerufen, der wiederum die Funktion ladenJSON aufruft. In ihr wird ein XMLHttpRe-quest request erzeugt, das ein PHP-Skript auf dem Hägar-Server aufruft und einen JSON-Stringempfängt, der in dem Event-Handler onreadystatechange zu einem vollständigen Text „Kau-fen Sie unseren Prozessor mit der Nummer 123 für 99.99 C!“ ausformuliert wird und damitden vorherigen Text im <p>-Element überschreibt, allerdings nur unter der Bedingung, dass dieHTTP-Antwort eingetroffen und der Status-Code OK lautet. (Der Status-Code 200 besagt, dassdie HTTP-Anfrage erfolgreich verlief.) Das PHP-Skript auf Hägar ist übrigens nur ganz kurzund gibt einen immer gleichen String aus:

1 <?php

2 header("Access-Control-Allow-Origin: *");

3 echo '{

4 "id" : "123",

5 "name" : "Prozessor",

6 "preis": 99.99

7 }';

8 ?>

Wir können uns jedoch leicht vorstellen, dass das PHP-Programm stattdessen einen Datenbank-zugriff ausführen könnte und so das Tagesangebot aktuell aus der Datenbank selektiert.

Page 168: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

168 Andreas de Vries

16.10.2 AJAXViele moderne Webanwendungen basieren auf AJAX (Asynchronous JavaScript and XML), daswiederum auf dem XMLHttpRequest-Objekt beruht. Ziel vieler AJAX-Anwendungen ist es,das starre Architekturmuster des Request-Response von HTTP zu überwinden, bei dem Anfra-gen nur vom Client ausgehen und der Server nur reagieren kann. Haben sich jedoch zentraleDaten auf dem Server aktualisiert, so kann der Server die Clients nicht darüber informieren.Bei einer Internetauktion beispielsweise würde ein Bieter nicht erfahren, wenn ein neues Ge-bot eines anderen vorläge, wenn er nicht selber immer wieder nachfragt. Ebenso würde beieinem Chatserver beispielsweise ein angemeldeter User nicht erfahren, wenn eine neue Nach-richt eines Anderen eingetroffen wäre. Zwei Verfahren, den Client mit Hilfe eines asynchronenXMLHttpRequest-Objekts automatisiert von einer Datenaktualisierung in Kenntnis zu setzen,sind das Polling und das Long Polling, siehe Abbildung 16.7. Beim Polling wird in einem regel-

AJAX-Client Serverrequest

response

request

response

request

response

Daten-aktualisierung

∆t

∆t

...

(a) Polling

AJAX-Client Serverrequest

response

request

response

Daten-aktualisierung

Daten-aktualisierung

∆t

∆t

...

(b) Long Polling

Abbildung 16.7: Polling und Long Polling als Methoden zur Synchronisation eines zentralen Datenbestandes.Vgl. [5, S. 27f].

mäßigen Zeitabstand ∆t eine Anfrage an den Server gestellt, auf die er unverzüglich antwortet.Beim Long Polling dagegen stellt der Client eine asynchrone Anfrage, auf die der Server jedocherst nach einer Aktualisierung seiner Daten antwortet. Empfängt der Client eine Antwort, stellter sofort eine neue Anfrage, auf die er wiederum eine Antwort erst nach erfolgter Datenaktuli-sierung auf dem Server erhält.

Das Polling ist ein in JavaScript clientseitig relativ einfach zu implementierendes Verfahren,siehe Listing 16.4. Allerdings hat es den großen Nachteil, dass eine große Anzahl unnützerAnfragen gestellt werden, wenn die Anfragefrequenz höher als die typische Änderungsfrequenzder Daten ist. Vor allem Server mit sehr vielen Usern können dadurch unnötig belastet werden.Das Long-Polling dagegen lastet den Server optimal aus, da er nur noch zu den notwendigenZeitpunkten an die betroffenen Clients Nachrichten sendet.

Listing 16.4: Polling durch Rekursion1 <!DOCTYPE html>

2 <html>

3 <head>

4 <meta charset="UTF-8"/>

5 <script>

Page 169: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 169

6 var periode = 2000; // Polling-Periode in ms

7 var data;

8 var request = new XMLHttpRequest();

9

10 request.onreadystatechange = function() { // Event Handler

11 if (request.readyState === 4) {

12 document.getElementById("ausgabe").innerHTML = request.response;

13 }

14 }

15

16 var poll = function(x) {

17 if (x > 5) return; // Basisfall: beende Rekursion

18 request.open("POST", "http://haegar.fh-swf.de/AJAX/spiegel.php");

19 data = new FormData();

20 data.append("x", x); // x-Werte

21 data.append("y", x*x); // y-Werte

22 request.send(data);

23 setTimeout("poll("+(x+1)+")", periode); // Rekursionsaufruf

24 }

25

26 poll(0); // Start der Rekursion

27 </script>

28 </head>

29

30 <body>

31 <div id="ausgabe"></div>

32 <p>(<i>y</i> = <i>x</i><sup>2</sup>)</p>

33 </body>

34 </html>

16.11 Web Workers: Nebenläufigkeit in JavaScriptIm Gegensatz zu Java oder C++ bietet JavaScript keine Möglichkeit, einzelne Threads zu pro-grammieren, ein JavaScript-Programm wird grundsätzlich in nur einem einzigen Thread ausge-führt [8]. Bei rechenintensiven Algorithmen bewirkt diese Eigenart, dass das Programm solangeblockiert und keine weiteren Anweisungen ausführt oder auf Benutzereingaben reagiert, bis dieBerechnungen beendet sind.

Allerdings bietet JavaScript zur nebenläufigen Programmierung das Konzept der Workersoder Web Workers an.26 Ein Worker in JavaScript ist ein Standardobjekt, das als Teilprozess imHintergrund läuft, also nachrangig zum Hauptprozess des eigentlichen JavaScript-Programms,und isoliert für sich ausgeführt wird, insbesondere unabhängig von weiteren Benutzereingaben.Interaktionen sind ausschließlich mit dem Hauptprozess über die Methoden postMessage undterminate sowie den Event-Handler onmessage möglich. Um ein Worker-Objekt zu erzeugen,muss Quelltext des Workerprogramms in einer externen JavaScript-Datei ausgelagert vorliegen.Dies sei beispielsweise worker.js; dann wird im Hauptdokument das Worker-Objekt wie folgterzeugt:

26 http://dev.w3.org/html5/workers/http://dev.w3.org/html5/workers/, https://developer.mozilla.org/

en-US/docs/DOM/Worker [2016-07-17]

Page 170: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

170 Andreas de Vries

var worker = new Worker("worker.js");

Die Kommunikation zwischen dem Hauptprozess und dem Workerprozess verläuft nun überden Austausch von Nachrichten. Wie in Abbildung 16.8 dargestellt reagiert der Event-Handler

Hauptprozess Worker

worker.postMessagedata−→ self.onmessage

worker.onmessagedata←− self.postMessage

Abbildung 16.8: Kommunikation zwischen Hauptprozess und Worker.

des einen Prozesses stets auf die von postMessage gesendeten Nachricht des jeweils anderenProzesses. Ein einfaches Beispiel ist das folgende HTML-Dokument, das einen bidirektionalenNachrichtenaustausch bewirkt:

1 <!DOCTYPE HTML>

2 <html>

3 <head><meta charset="UTF-8"/><title>Worker example: Send Messages</title></head>

4 <body>

5 <p>

6 <script>

7 var worker = new Worker("worker.js");

8 worker.onmessage = function (event) {

9 document.getElementById("result").innerHTML = event.data;

10 };

11 </script>

12 <input type="text" id="message" value="Hallo Welt!"/>

13 <input type="button" value="Send"

14 onclick="worker.postMessage(document.getElementById('message').value);"/>

15 </p>

16 <p>Message: <output id="result"></output></p>

17 </body>

18 </html>

Die zugehörige Worker-Datei lautet:

1 var count = 0;

2 self.onmessage = function (event) {

3 count++;

4 self.postMessage(event.data + " (No " + count + ")");

5 };

16.12 DOM StorageDOM Storage, oder Web Storage nach W3C,27 ist eine Web-Technik, mit der über einen Brow-ser Daten von mehreren MB Größe auf einem Rechner gespeichert werden können. DOM Sto-rage ermöglicht damit eine persistente Datenspeicherung ähnlich wie ein Cookie, allerdings mit

27 Die Namensgebung ist einigermaßen kompliziert, nach W3C heißt es Web Storage, aber auch DOM Storageist möglich, allerdings setzt es nicht die Existenz eines tatsächlichen Dokument-Objekts voraus http://dev.w3.

org/html5/webstorage/#terminology.

Page 171: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 171

der entscheidenden Einschränkung, dass Datenzugriffe nicht über das HTTP-Protokoll gesche-hen, sondern vollständig vom Browser gesteuert und durch clientseitige Skripte (in der RegelJavaScript) durchgeführt werden.

DOM Storage speichert Daten in einem assoziativen Array, in dem die Schlüssel und WerteStrings sind. Sie können also in JavaScript einfach mit JSON.parse als Objekt erzeugt und mitJSON.stringify in DOM Storage gespeichert werden.

16.12.1 Lokale und sessionspezifische SpeicherungDaten, die lokal gespeichert werden, die sogenannten Local Shared Objects (LSO), sind miteiner Domain verknüpft und bleiben auch nach Beenden des Browsers bestehen. Alle Skripteeiner Domain, von der aus die Daten gespeichert wurden, können auf die Daten zugreifen. BeiMozilla Firefox werden die Daten in der Datenbankdatei webappsstore.sqlite gespeichert.

Session-spezifisch gespeicherte Daten sind mit dem erzeugenden Browser-Fenster verknüpftund auf dieses beschränkt. Gespeicherte Daten werden beim Schließen des Browser-Fenstersgelöscht. Diese Technik bietet die Möglichkeit, mehrere Instanzen derselben Anwendung inverschiedenen Fenstern laufen zu lassen, ohne dass es zu einer gegenseitigen Beeinflussungkommt, was von Cookies nicht unterstützt wird.

In JavaScript werden beide Speicherarten durch die Standardobjekte localStorage und ses-

sionStorage realisiert und bieten die Methoden setItem und getItem zum Speichern und Lesender Daten:

// Speichert ein Key-Value-Paar im localStorage

localStorage.setItem('schluessel', 'wert');

// Liest den eben gespeicherten Wert aus und zeigt ihn an

alert(localStorage.getItem('schluessel')); // => wert

// Speichert ein Key-Value-Paar im sessionStorage

sessionStorage.setItem('key', 'value');

// Liest den eben gespeicherten Wert aus und zeigt ihn an

alert(sessionStorage.getItem('key')); // => value

Für weitere Informationen zu DOM Storage mit JavaScript siehe http://www.jstorage.info/

Page 172: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Literaturverzeichnis

[1] AMMELBURGER, D. : Go To PHP 4. München : Addison Wesley, 2002

[2] CROCKFORD, D. : Das Beste an JavaScript. Köln : O’Reilly, 2008

[3] FIELDING, R. T.: Architectural Styles and the Design of Network-based Software Architectures. Irvine,University of California, Diss., 2000. – http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

[4] FORSTER, O. : Analysis 1. 9. Aufl. Wiesbaden : Vieweg, 2008

[5] GORSKI, P. L. ; IACONO, L. L. ; NGUYEN, H. V.: WebSockets. Moderne HTML5-Echtzeitanwendungenentwickeln. Müchen : Hanser, 2015

[6] HAUSER, T. : XML-Standards. schnell + kompakt. Frankfurt : entwickler.press, 2006

[7] KRAUSE, J. : PHP 5. Grundlagen und Profiwissen. München : Hanser Fachbuch, 2004

[8] LAU, O. : ‘Verteiltes Rechnen mit JavaScript’. In: c’t kompakt Programmieren 3 (2012). – http://www.ct.

de/cs1207014

[9] MAURICE, F. : PHP 5.5 und MySQL 5.6. 3. Aufl. Heidelberg : dpunkt.verlag, 2014

[10] MCLUHAN, M. : The Gutenberg Galaxy. Toronto : University of Toronto Press, 1962. – https://books.

google.com/books?id=7K7rKIWaXXIC

[11] MCLUHAN, M. : Understanding Media. The Extensions of Man. Oxon : Routledge, 1964 (reissued 2001). –https://books.google.com/books?id=K4AWBwAAQBAJ

[12] PIEPMEYER, L. : Grundkurs Funktionale Programmierung mit Scala. München Wien : Carl Hanser Verlag,2010

[13] SCHUHFUSS, M. : ‘Node-Ausrüstung’. In: JavaScript Spezial (2012), S. 34–38. – http://www.

javascript-spezial.de

[14] SOSINSKY, B. : Networking Bible. Indianapolis : Wiley, 2009. – https://books.google.com/books?id=

3DOREqRZejcC

[15] ST. LAURENT, S. ; FITZGERALD, M. : XML kurz & gut. 3. Aufl. Köln : O’Reilly Verlag, 2006

[16] TURING, A. M.: ‘On computable numbers, with an application to the Entscheidungsproblem’. In: Proc.London Math. Soc. 42 (1936–1937), Nr. 2, S. 230–265. – http://www.turingarchive.org/browse.php/B/12

[17] WENZ, C. : ‘Die 10 Gebote. Zehn Dinge, die man über JavaScript wissen muss’. In: Entwickler MagazinSpezial 5 (2015), S. 10–16. – https://entwickler.de/entwickler-magazin/

[18] WOJCIESZAK, M. : ‘Binäre Austauschformate’. In: Java Magazin 6 (2015)

[19] ZEIDLER, E. (Hrsg.): Teubner Taschenbuch der Mathematik. Teil 1. Leipzig : B. G. Teubner, 1996

Web-Links[DOM] https://w3.org/DOM – Spezifikation des W3C des DOM.

[GMP] http://www.masterplanthemovie.com/ – Ozan Halizi und Jürgen Mayer: „The Google Master Plan“, Filmnach ihrer Bachelor-Thesis an der FH Ulm 2007. Kritische Betrachtung zu Google und dessen Wachstum.Der Film ist auch unter http://www.youtube.com/watch?v=9zKXCQpUnMg zu finden.

[JS] https://developer.mozilla.org/en-US/docs/Web/JavaScript – JavaScript-Dokumentation des Mozilla De-veloper Network.

[JSL] http://www.jslint.com/ – JSLint, Programm zur Überprüfung der Qualität von JavaScript Quelltext.

172

Page 173: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 173

[OWASP] https://owasp.org/ – Open Web Application Security Project (OWASP), gemeinnützige („501(c)(3)“) Or-ganisation mit dem Ziel, die Sicherheit von Software im WWW zu verbessern und durch Transparenz Ent-scheidungskompetenz bei Endanwendern und Organisationen in Fragen von Sicherheitsrisiken zu schaffen.Empfehlenswert ist die Wikiseite zu Sicherheitslücken (vulnerability): https://www.owasp.org/index.php/Category:Vulnerability

[PHP] http://php.net/manual/de/ – PHP-Handbuch

[PS] http://sandbox.onlinephpfunctions.com – PHP Sandbox, Möglichkeit zum Testen von PHP-Quelltext-fragmenten (Snippets). Die Sandbox wird bereitgestellt von Jereon (John) Post, die Website liefert Infor-mationen und Tutorials über PHP.

[SuMa] http://suma-ev.de/ – SuMa eV, gemeinnütziger Verein zur Förderung der Suchmaschinentechnologie unddes freien Wissenszugangs. Hauptziel: Aufbau einer dezentralen und kooperativen Suchmaschinen-Strukturin Deutschland, die schwer monopolisierbar ist.

[TF] https://www.tensorflow.org/ – TensorFlow, quelloffene Softwarebibliothek, die die Programmierung neu-ronaler Netze auf verteilten Systemen ermöglicht.

[W3C] http://www.w3c.org/ – World Wide Web Consortium, Gremium zur Standardisierung der Web-Techniken;eine deutsche Übersetzung wichtiger Teile dieses Webauftritts findet man unter http://www.edition-w3c.de/, auf die auch das Deutsch-Österreichische Büro W3C.DE/AT http://www.w3c.de/ bzw. http://www.w3c.at/ verlinkt.

[XSD] http://www.w3c.org/TR/xmlschema-0/ – Einführung in XML Schema, auf deutsch unter http://www.edition-w3c.de/TR/2001/REC-xmlschema-0-20010502/

Page 174: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Index

.=, 55? :, 67$mysqli->connect_error, 108->, 102.=, 55., 55, 60/*...*/, 56//, 56<=, 61<colgroup>, 25<span>, 141<, 61===, 61==, 61=>, 79, 146=, 59>=, 61>, 61Date, 150FormData, 163Infinity, 142JSON, 148Math, 145NaN, 142PHP_SELF, 91Worker, 166XMLHttpRequest, 161XOR, 63#, 56$_COOKIE, 71, 87, 96$_ENV, 71$_FILES, 71, 87$_GET, 71, 87$_POST, 71, 87, 88$_SERVER, 71, 91$_SESSION, 71, 99$mysqli->affected_rows, 114$mysqli->connect_error, 108$mysqli->query, 109$result->fetch_field(), 113$, 54, 59$_FILES, 133&&, 62ˆ, 63||, 62!==, 61!=, 61!, 63\$, 55\n, 84

abs, 68array, 75arsort, 84asort, 84as, 77case, 67, 146copy, 133count, 83date(), 73do/while, 69document.body, 158do, 146echo, 53empty, 58, 83escape_string, 114escape_string(), 125exit, 109explode, 83fclose, 130fopen, 130forEach, 148foreach-Schleife, 77form, 26for, 146for-Schleife, 69fread, 131function, 70, 151fwrite, 130getElementById, 156implode, 83, 122include_once, 71include, 72ini_set, 100in, 144is_bool(), 58is_double(), 58is_float(), 58is_int(), 58is_integer(), 58is_long(), 58is_numeric, 58, 92is_real(), 58krsort, 84ksort, 84length, 148mktime(), 73natcasesort, 84null, 58number_format, 92onclick, 150

174

Page 175: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 175

onkeyup, 150onmessage, 166onreadystatechange, 161postMessage, 166print_r, 83readfile, 131readyState, 161real_escape_string, 114require_once, 71, 109require, 72result::num_rows, 114return, 70rsort, 84session_regenerate_id, 100session_start(), 98setTimeout, 154sizeof, 76, 83sort, 84sqrt, 70str_replace, 92strtr, 133submit, 30switch, 67, 146terminate, 166time(), 73toString, 144typeof, 143uasort, 84uksort, 84urldecode, 133urlencode, 133usort, 84var_dump, 83var, 143while, 67, 146\n, 1321TBS-Stil, 142

abs, 68absoluter Pfad, 21ACK-Flag, 12Adressraum, privater, 11affected_rows, 114AJAX, 161, 165Akronym, 51Angriffsvektor, 124anonyme Funktion, 151Anweisung, 53Anwendungsprotokolle, 13Array, 29, 58, 74, 143

Sortierfunktionen, 84Arrays in JavaScript, 147, 148Assoziationsoperator =>, 79assoziatives Array, 77assoziatives Array (JavaScript), 148asynchrone Kommunikation, 161asynchrone Rückruffunktion, 152Attribut, 17, 40, 101

Barrierefreiheit, 23

Bedingungsoperator, 67Big Data, 48blinde Tabelle, 23Block, 142blockierende Rückruffunktion, 152body, 19Boole’sche Werte, 61Boole’scher Ausdruck, 65Browser, 16

C-Syntax, 143Callback-Funktion, 152Cascading Stylesheets, 31CBOR, 48CDATA, 41Closure, 153, 157codefunction, 143codenull, 143codeundefined, 143colgroup, 25console.log, 141Cookie, 14, 94CORS, 162Cross-Site-Scripting, 128CSRF, 127CSS, 20, 140CSS-Regel, 32CST, 128csv-Datei, 83cyberphysikalische Systeme, 47

Dangling else, 66Date, 150date(), 73Datei-Handle, 130Dateien hochladen, 132Dateimodus, 130Datenbank, 106Datenstruktur, 147Debugging, 119deferred callback, 152Deklaration, 143deprecated, 20do/while, 146do/while-Schleife, 69document.body, 158Dokument, 39DOM, 156DOM Storage, 167Doppel-Doppelpunktoperator, 102DTD, 42dynamisch typisiert, 142

ECMA, 138Element, 40Element in HTML, 17elseif, 67Empfänger, 9Endlosschleife, 68Ereignisbehandler, 149, 152

Page 176: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

176 Andreas de Vries

Ergebnismenge einer SQL-Abfrage, 110Ergebnismenge einer SQL-Anweisung, 112escape_string, 114escape_string(), 125escaping, 125Euler’sche Zahl, 146Event Handler, 149, 152exit, 109Exploit, 124

Facebook, 6, 95Fakultät, 154false, 62falsy, 62, 143Fibonacci-Zahl, 153FIN-Flag, 12for, 146for-Schleife, 69forEach, 148foreach-Schleife, 77FormData, 163Formular, 26FPDF, 101Framework, 101Full-Duplex, 13function, 143, 151Funktion, 69, 151Funktion, innere –, 152funktionale Programmiersprache, 151Funktionalkalkül, 153Funktionenschar, 153

gültiges XML-Dokument, 42Gecko, 156Geltungsbereich, 143getElementById, 140, 156Gleichheitsoperator, 62globale Variable, 71, 154Google, 6, 95

höhere Ordnung, Funktion, 155half close, 12head, 19Heron, 68hochladen, 132htdocs, 22HTML, 16, 163HTTP, 13, 98, 165HTTP-Cookie, 94HTTP-Methode, 128HTTP-Statuscode, 15HttpOnly, 95HTTPS, 15, 88Hyperlink, 20

ID-Selektor, 32idempotente HTTP-Methode, 14Identitätsoperator, 62IETF, 95IIFE, 154

imperative Programmierung, 151implizit typisiert, 142in-Operator, 144index.html, 22indiziertes Array, 74Infinity, 142Informationssicherheit, 124innere Funktion, 152innerHTML, 140Internet der Dinge, 48Internet-Dienste, 9, 13Internetrecht, 30Inversion of Control, 152IoC, 152IoT, 48IP, 8, 10, 11IP-Adresse, 10IPv6, 10is_numeric, 92ISN, 12isset, 58

Java, 138JavaScript, 137, 168JScript, 138JSLint, 138JSON, 46, 144, 148, 163JSON.parse, 163

Key, 77Klasse, 101klassenbasierte Objektorientierung, 143Klassendiagramm, 101Klassenselektor, 32Kommntar (JavaScript), 142Konkatenation, 55konkatenieren, 55Konstante, 58Konstanten, mathematische, 145Konstruktor, 144Kontrollflussumkehr, 152

Lambda-Ausdruck, 151Laufzeit eines PHP-Skripts, 68Leeraumzeichen, 18leeres Element, 17, 40length, 148Local Storage Objects, 168Login, 98logische Operatoren, 62lokale Variable, 71Long Polling, 165LSO, 168

Magic Cookie, 94Maskierung, 125Math, 145mathematische Konstanten, 145mathematische Standardfunktionen, 68mehrdimensionale Arrays, 79

Page 177: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

Webtechnologie 177

Mehrfachvererbung, 104Metadaten, 113Methode, 101Mixins, 104mktime(), 73Modus, 130mysql_result::fetch_field(), 113mysqli-Objekt, 107

Nachrichten, 14Namensraum, 43NaN, 142, 154natsort, 84Nebeneffekt, 14new, 144Newton’sches Iterationsverfahren, 68Node.js, 138null, 58, 143num_rows, 114number, 142number_format, 92numerisches Array, 74numerisches Array in JavaScript, 148

Objekt, 101, 113Objektliteral, 144Objektmethode, 101Objektorientierung, 143onclick, 150onkeyup, 150onmessage, 166onreadystatechange, 161Open-Source, 51Operator

Assoziations- =>, 79Bedingungs-, 67logischer, 62

optionale Parameter, 70

Parameter, optionale –, 70Pfad, 21PHP, 51PHP-Engine, 52Polling, 165Port, 9postMessage, 166print_r, 83private Addressräume, 11Promise, 152property, 144Protokoll

verbindungsloses, 10, 11, 14verbindungsorientiertes, 12zustandsloses, 14

Prototyp, 143prototypenbasierte Objektorientierung, 143prototypische Vererbung, 145Prozess, 11Prozessinstruktion, 40

qualifizierter Namensraum, 43

Rückruffunktion, 152readyState, 161real_escape_string, 114Recht im Internet, 30rechtsbündige Spaltenformatierung, 25Rekursion, 154relationale Datenbank, 106relativer Pfad, 21Request-Response, 14, 16require_once, 109Ressource, 14REST, 98result set, 110RPC, 46

Schar, Funktionen-, 153Schicht, 9Schlüssel, 77Schleifen, 67schreibungssensitiv, 142schwach typisierte Programmiersprache, 57scope, 143script-Tag, 139Segment (TCP), 12Selektor, 31Semikolon, 142Sender, 9Sequenznummer, 12Session, 10, 98Session Fixation, 100, 126Session-ID, 98session_regenerate_id, 100setTimeout, 154short syntax array, 76sichere HTTP-Methode, 15Sitzung, 98Smarty, 101Socket, 9Sortierfunktionen, 84span, 141SQL, 61, 106, 107SQL-Injektion, 124Standardnamensraum, 43statisch typisiert, 142Statuscode, 15str_replace, 92Stringaddition, 55style, 20submit-Button, 30superglobal, 71superglobale Variable, 87SVG, 163SYN-Flag, 12synchrone Rückruffunktion, 152

Tabelle, 23Tags, 17, 40TCP, 11

Page 178: Webtechnologie - FH Südwestfalen · Vorwort Der Titel dieses Skripts erscheint auf den ersten Blick anachronistisch, also irgendwie „aus der Zeit gefallen“. Er verwendet das

178 Andreas de Vries

TCP-Window, 13TCP/IP, 8Template-Engine, 101Tensor, 80terminate, 166ternärer Operator, 67Textkodierung, 108Thread, 166three way handshake, 12time(), 73timestamp, 73toFixed, 142toString, 144TRACE, 128Trait, 104Transaktion, 14true, 62truthy, 62, 143Tunneling, 11typeof, 143typisiert, 142Typselektor, 32

UDP, 11Ueberladen, 70undefined, 143Unity, 6untypisierte Programmiersprache, 57upload, 132URI, 10, 14, 21, 43, 99URL, 10, 43, 135, 161use, 104UTF8, 108

valides XML-Dokument, 42var, 143var_dump, 83Variable, 54, 142, 143

superglobale, 87Verarbeitungsanweisung, 40Verbindung, 12, 98verbindungsloses Protokoll, 10, 11, 14verbindungsorientiertes Protokoll, 12Vererbung, 103verzögerte Rückruffunktion, 152VPN, 11

W3C, 19Wahrheitstabellen, 63Web Storage, 167Web Worker, 166while, 146while-Schleife, 67Whitespace, 18window-Objekt (JavaScript), 159wohlgeformtes XML-Dokument, 41Worker, 166

XML, 18, 38, 163XML Schema, 44

XMLHttpRequest, 161XOR, 63XSD, 44XSRF, 127XSS, 95, 128XST, 128

Zeitstempel, 73ZEND-Engine, 51Zugriffsmodus, 130zustandslos, 98zustandsloses Protokoll, 14Zuweisungsoperator, 59