Informationssysteme-PHP

Aus Debacher-Wiki
Wechseln zu:Navigation, Suche

Der vorliegende Text gliedert sich in folgende Teile:

I. Datenschutz

II. Projektmanagement

III. Modellbildung

IV. PHP

V. MySQL

VI. Einbindung von MySQL in PHP

VII. Erweiterte Möglichkeiten in MySQL

VIII. Beispielaufgaben

IX. Anhang


IV. PHP-MySQL

Viele Anbieter im Web speichern ihre Inhalts-Seiten heute nicht mehr als HTML-Dateien, sondern er­zeugen Sie bei Bedarf dynamisch mit der Programmiersprache PHP (PHP Hypertext Preprocessor, ursprünglich Personal Home Page) und mit einer Datenbank wie MySQL.

Informationssysteme-php-dyn.png

Dynamische Seiten kann man leichter pflegen und konsistent halten, als statische Seiten. Außerdem kann man damit Gestaltung und Inhalt voneinander trennen: der Inhalt steckt in einer Datenbank, die Gestaltung bestimmt das Programm, das aus den Datenbankinhalten Webseiten erzeugt. Durch diese Trennung lassen sich die gleichen Inhalte für sehr unterschiedliche Ausgabegeräte, wie z.B. Desk­top-Rechner und Palm-Tops aufbereiten.

Auch für die meisten interaktiven Dienste wie Chat-Bereiche, Diskussionsforen oder einfach Gäste­bücher reichen normale HTML-Seiten nicht aus. Im folgenden Text soll es darum gehen, wie man mit der Programmierumgebung PHP/FI und dem Datenbanksystem MySQL Datenbankanwendungen innerhalb eines Intranetsystems erstellen kann.

Es muss dazu folgende Software vorhanden sein:

  1. Der Webserver Apache (http://www.apache.de)
  2. In den Apache wurden die PHP/FI Module eingebunden (http://www.php.net)
  3. Das Datenbanksystem MySQL (http://www.mysql.de)

Da diese Softwarekombination meist auf Servern mit dem Betriebssystem Linux läuft, spricht man oft auch von einem LAMP-System (Linux, Apache, MySQL, PHP). Auf Linux-Rechnern sind diese Programme normalerweise installiert, oder zumindest Teil der Distri­bution und damit leicht zu installieren.

Etwas aufwändiger ist die Installation der Software auf Rechnern mit einem Windows-Betriebssys­tem (man spricht dann von einem WAMP-System), hier müsste man die Programme normalerweise ein­zeln installieren und konfigurieren.

Um dieses Arbeit zu erleichtern haben sich mehrere Gruppen etabliert, die die Programme zu einem vorkonfigurierten Gesamtpaket schnüren. Sehr gut gepflegt ist das Paket XAMPP (das zweite P steht hier für die Programmiersprache Perl, das X allgemein für L und W) von der Website http://www.apachefriends.org.

Ein grundsätzliches Problem besteht darin, dass hier mit drei verschiedenen Programmen gearbeitet wird, die jeweils ihre eigene Programmiersprache besitzen. Die Befehle müssen aber alle in den glei­chen Programmtext eingebunden sein (ein vernetztes System). Grundlage ist immer eine HTML-Seite. Es ist deshalb wichtig zu beachten, an wen sich der Program­mierbefehl jeweils richtet.


1. PHP/FI Grundlagen

Bei PHP handelt es sich im Prinzip um eine Erweiterung von HTML. Alle PHP-Dokumente werden vom Apache-Webserver nach speziellen Programmier-Befehlen durchsucht. Gefundene Befehle wer­den ausgeführt. Der Benutzer bekommt immer eine normale HTML-Seite geliefert, da alle Be­fehle schon vom Webserver ausgeführt wurden. Es ist also wichtig, dass jedes PHP-Programm immer eine korrekte HTML-Seite zurück liefert. Eine PHP-Seite erkennt der Apache an der speziellen Endung z.B. .php, man kann ihn aber auch so konfigurieren, dass er jede .html Seite nach entsprechenden Befehlen durchsucht. Die notwendige En­dung hängt also von der Konfiguration des jeweiligen Webservers ab.

PHP-Befehle werden durch Fragezeichen kenntlich gemacht:

<?php $a=5; ?>

Innerhalb der spitzen Klammern können mehrere (beliebig viele) Befehle stehen, die dann aber im­mer mit einem Semikolon beendet sein müssen:

<?php $a=”Hallo Welt”;
 echo $a; ?>

Der Echo-Befehl bewirkt eine Ausgabe an den Browser.

Das folgende kurze Beispiel würde den Text „Hallo Welt” auf dem Bildschirm ausgeben. Dabei wird vorausgesetzt, dass um die beiden Zeilen herum der normale HTML-Rahmen vorhanden ist. Die komplette PHP-Seite hat also folgenden Inhalt:

<html><head><title>PHP-Testprogramm</title></head>
 <body>
 <CENTER><H1>Testprogramm</H1></CENTER>
 <?php 
     $a=”Hallo Welt”;
     echo $a;
 ?>
 </body></html>

Aufgabe 1:
Erstelle eine Seite test.php nach obiger Vorgabe und speichere sie so, dass sie für den Webserver erreichbar ist (unter Linux: /srv/www/htdocs, unter Windows c:\mini­xampp\htdocs) und rufe sie mit einem Webbrowser auf (http://localhost/hallo.php).

Hinweis: Eine PHP-Seite darf im im Browser nicht mittels Datei -> öffnen aufrufen, da sie dann nicht über den Webserver geladen wird. Der Aufruf einer PHP-Seite muss im­mer mit http:// beginnen.

Viele Funktionen von PHP sind auf den ersten Blick ganz einfach, bergen aber eine enorme Fülle von Möglichkeiten.

<html><head><title>Beispiel: Datum</title></head><body>
 <H3>Aktuelles Datum</H3>
 <?php
   echo date("d.m.Y");
 ?>
 </body></html>

Hier wird das aktuelle Datum ausgegeben und zwar in der Form:

17.04.2006 

Der Platzhalter d steht also für den Tag (day), das m für den Monat (month) und das Y für das Jahr (Year). Erst der folgende Ausschnitt aus der Platzhalterliste lässt die umfangreichen Möglichkeiten erahnen.

   d - Tag des Monats, 2-stellig mit führender Null: "01" bis "31" 
   D - Tag der Woche als 3 Buchstaben, z.B. "Fri" 
   F - Monat als ganzes Wort, z.B "January" 
   g - Stunde im 12-Stunden-Format ohne führende Null: "1" bis "12" 
   G - Stunde im 24-Stunden-Format ohne führende Null: "0" bis "23" 
   h - Stunde im 12-Stunden-Format: "01" bis "12" 
   H - Stunde im 24-Stunden-Format: "00" bis "23" 
   i - Minuten: "00" bis "59" 
   j - Tag des Monats ohne führende Null: "1" bis "31" 
   l - (kleines 'L') ausgeschriebener Tag der Woche, z.B. "Friday" 
   m - Monat: "01" to "12" 
   n - Monat ohne führende Null: "1" bis "12" 
   M - Monat als 3 Buchstaben, z.B. "Jan" 
   s - Sekunden: "00" bis "59" 
   w - Wochentag beginnend mit "0" (Sonntag) bis "6" (Samstag) 
   Y - Jahr als vierstellige Zahl, z.B. "2001" 
   y - Jahr als zweistellige Zahl, z.B. "01" 

Aufgabe 2:
Versuche Datum und Uhrzeit auf einer Webseite übersichtlich darzustellen. Was ist der Vorteil gegenüber der entsprechenden Anzeige mittels Javascript?

Aufgabe 3:
Probiere aus, was phpinfo() alles verrät:

<html><head><title>Beispiel: phpinfo()</title></head><body>
 <H3>phpinfo</H3>
 <?php
   phpinfo();
 ?>
 </body></html>


Variablen in PHP

Variablen werden durch ein vorangestelltes $ Zeichen gekennzeichnet, der eigentliche Name muss mit einem Buchstaben beginnen. Es gibt drei Variablentypen:

String		$a=”5"
Real		$a=5.0
Integer		$a=5

Die Typzuordnung erfolgt automatisch. Die Typzuordnung spielt aber keine sehr große Rolle. Folgende Verknüpfungen stehen für Zahlenvariablen zur Verfügung ($a=23; $b=17;):

"+" 	Addition	$a+$b ergibt 40
"-"  	Subtraktion	$a-$b ergibt 6
"*" 	Multiplikation 	$a*$b ergibt 391
"/"  	Division 	$a/$b ergibt 1.3529411764706 
"%"	Reste-Bildung 	$a%$b ergibt 6, da 23 durch 17 gleich 1 Rest 6 

Für die Verknüpfung von Strings dient der Dezimalpunkt ($a=“Hallo “; $b=“Welt“;).

"." 	Stringverknüpfung	$a . $b ergibt "Hallo Welt"

Würde man die Strings mit „+“ verknüpfen, so käme 0 heraus, da Sie dazu in Zahlen umgewandelt werden. Interessant wird es, wenn man Strings mit „+“ verknüpft, deren Inhalte mit Ziffern begin­nen.

$a="19";
$b="20";

In diesem Fall ergibt:

$a+$b	39
$a.$b	1920

In einem PHP-Programm ist eine Vielzahl von Variablen immer vorhanden. Dazu gehören die Umge­bungsvariablen, die ein Webserver automatisch im Array $_SERVER[] zur Verfügung stellt. Das sind u.a. folgende Informationen:

GATEWAY_INTERFACE	Die Revision der CGI-Spezifikation, die der Web-Server benutzt, z.B. 'CGI/1.1'. 
SERVER_NAME		Der Host-Name des Web-Servers, der das Skript aus führt. Das kann auch der Name eines virtuellen Servers sein. 
SERVER_SOFTWARE		Der Identifikations-String des Web-Servers (aus den Headern), sobald er An­forderungen beantwortet. 
SERVER_PROTOCOL		Name und Revision des Informations-Protokolls, über das die Seite an­gefordert wurde, z.B. 'HTTP/1.0'. 
HTTP_USER_AGENT		Inhalt der User_Agent:-Header-Angabe der aktuellen Anfrage (wenn eine An­gabe existiert).
REMOTE_ADDR		Die IP-Adresse, von der aus gerade auf die Web-Seite zugegriffen wird. 
SCRIPT_FILENAME		Der absolute Pfadname des gerade ausgeführten Skripts. 
SERVER_ADMIN		Der Inhalt der in der Konfigurations-Datei des Web-Servers (Apache) stehen­den Angabe zum SERVER_ADMIN. Bei virtuellen Hosts der da­für eingetragene Wert. 

Abgefragt werden die Daten z.B. mittels:

echo $_SERVER['SERVER_NAME']

Aufgabe 4:
Erstelle eine PHP-Seite, die mindestens den Server-Namen, die Server-IP und die User-Agent-Informationen liefert.

Es gibt aber eine ganze Menge Besonderheiten im Zusammenhang mit Variablen.

$a=”Hallo”;
$$a=”Welt”;

Das doppelte $ hat die Bedeutung, dass der Wert von $a als Variablen-Bezeichner benutzt wird. Die zweite Zeile hat also den gleichen Effekt wie:

$Hallo=”Welt”;

Noch ungewöhnlicher ist der Umgang mit Arrays. Diese werden dynamisch und sehr flexibel ange­legt.

$a[0]=”Hallo”;
$a[1]=”Welt”;

legt ein Feld mit zwei Komponenten an, das aber jederzeit erweitert werden kann. Die Definition hät­te man auch abkürzen können mittels:

$a[]=”Hallo”;
$a[]=”Welt”;

Den Rest denkt sich das System hinzu, wobei der Index jeweils hochgezählt wird. Natürlich dürfen auch Strings als Index auftauchen:

$a[”Hallo”]=”Welt;

Zur Arbeit mit Arrays kennt php die Funktionen: Next(), Prev(), Reset(), End() und Key().

Bedingte Anweisungen

Für bedingte Anweisungen besitzt das PHP-System ein übersichtliches Konstrukt:

if (Bedingung):
  Befehle;
endif;

Folgende Variation hat den gleichen Effekt, ist aber weniger lesbar

if (Bedingung) {
 Befehle;
}

Auch eine zweiseitige Auswahl ist möglich:

if (Bedingung):
  Befehle;
else:
  Befehle
endif;

Will man noch mehr Fälle unterscheiden, so ist auch folgende Erweiterung vorhanden:

elseif (Bedingung):
 Befehle;

Wichtig ist, dass die Bedingung immer in Klammern gesetzt werden muss. In der Bedingung können folgende Vergleichsoperatoren auftauche:

==	Gleich
!=	Ungleich
<	Kleiner
<=	Kleiner oder gleich
>	Größer
>=	Größer oder gleich


Innerhalb der Bedingung können mehrere Teilbedingungen verknüpft werden. Dafür gibt es u.a. die folgenden logischen Operatoren:

&&	AND	logisches Und
||	OR	logisches Oder
XOR		exklusives Oder
!		Verneinung


Ein kleines Beispiel (in HTML-Rahmen einbinden):

<?	
 $a=5;
 $b=-3;
 if ($a>0 && $b>0):
   echo ”Beide Zahlen sind positiv”;
 elseif ($a<0 && $b<0):
   echo ”Beide Zahlen sind negativ”;
 else:
   echo ”Ein dritter Fall”;
 endif;
?>


Switch Für mehrseitige Auswahlen gibt es in Pascal das CASE. In PHP erreicht man den gleichen Effekt mit SWITCH.

switch(Ausdruck):
 case wert1:
           Befehle1;
           break;
 case wert2:
           Befehle2;
           break;
 default:
           Befehle3;
           break;
endswitch;


Wiederholungen

PHP kennt sehr unterschiedliche Schleifenkonstrukte. Am einfachsten sind Wiederholungen mit while:

while (Bedingung):
 Befehle;
endwhile;

Für jede Wiederholstruktur ist es wichtig, dass die ausgeführten Befehle die Bedingung verändert, sonst läuft die Schleife endlos. Ein einfaches Beispiel:

$i=0;
 while ($i<10):
  echo ”$i<p>”;
  $i++;
 endwhile;

Hiermit werden die Ziffern von 0 bis 9 ausgegeben. Gerade für das vorangegangene Beispiel wäre aber ein Konstrukt der folgenden Art sinnvoller.

for (expr1; expr2; expr3):
           Befehl;
endfor;

Gleich als konkretes Beispiel:

for ($i=0;$i<10;$i=$i+1):
  echo "$i<br>";
 endfor;

Beim Start der Schleife wird expr1 ausgewertet, hier also die Variable $i auf den Wert 0 gesetzt. Zu Beginn eines jeden Schleifen-Durchlaufs wird expr2 überprüft. Nur wenn die Bedingung wahr ist folgt ein weiterer Durchlauf. Am Ende jedes Durchlaufs wird expr3 ausgeführt.

Wenn expr2 fehlt, dann wird die Schleife unbestimmt oft durchlaufen, das Programm also nicht en­den. Das kann dann sinnvoll sein, wenn Sie die Schleife durch eine Bedingung abbrechen wollen, die nicht direkt von der Laufvariablen abhängt.

for ($i = 1;;$i=$i+1):
  if ($i > 10):
    break;
  endif;
  echo "$i<br>";
 endfor;

Man wird übrigens kaum ein Listing finden, bei dem ein Ausdruck wie $i=$i+1 steht. Fast alle Pro­grammierer nutzen die Kurzform $i++.

Aufgabe 5:
Erstelle eine PHP-Seite, die die Zahlen von 1 bis 100 untereinander ausgibt. Variiere das Programm dann so, dass es zehn Zeilen mit jeweils zehn Zahlen ausgibt.

2. Grafikfähigkeiten von PHP

Die Programmiersprache PHP verfügt über umfangreiche Grafik-Funktionen, zumindest auf Linux-Servern.

Bevor man auf die Details eingehen kann, sind ein paar Informationen über die HTML-Header-Datei­en notwendig. Wenn der Webserver eine Datei von der Festplatte lädt, dann ermittelt er den Typ der Datei (Text, Image, Video, ...) anhand der Dateiendung. Bevor er das erste Byte der Datei dann an den Browser übermittelt, teilt er diesem per Header-Zeile mit, welchen Dateityp er erwarten muss. Dieser Mechanismus ist bei PHP-Scripten außer Kraft gesetzt, da die Endung immer .php lautet und der Webserver nicht wissen kann, ob das Script einen Text oder eine Grafik erzeugt. Daher muss PHP die passende Header-Zeile erzeugen. Wenn der Benutzer keine eigene Angabe macht, dann teilt PHP den Typ text/html mit. Diese Stan­dardvorgabe muss man für eine Grafikausgabe natürlich ändern, wozu man den header-Befehl be­nutzt, der unbedingt vor jeglicher anderen Ausgabe-Zeile erfolgen muss. Im vorliegenden Fall also:

header("Content-Type: image/png");

Ein Beispiel für die Grafikfunktionen zeigt das folgende (vollständige!) Listing.

Informationssysteme-php-bild.png
<?php 
# Demonstration der Grafikmoeglichkeiten von PHP
#
# vor dieser ersten Zeile darf keine! Ausgabe erfolgen
header("Content-Type: image/png");

# Zeichenflaeche definieren
$width = 200;
$height = 200;
$image = imagecreate($width,$height);

# Farben definieren
$black=imagecolorallocate($image,   0 ,   0, 0);
$red  =imagecolorallocate($image, 255 ,   0, 0);
$blue =imagecolorallocate($image, 0   ,   0, 255);
$white=imagecolorallocate($image, 255 , 255, 255);

# Zeichnen
imageline($image,0,    0,$width-1,  0, $red);
imagerectangle($image, 0, 0, 160, 160, $red);
imagearc($image, 50,50,95,75,0,360,$blue);
imagefill($image, 50,50,$blue);

# Zeichnung erzeugen

imagepng($image);
imagedestroy($image);

?>

Hier werden einfach ein paar grafische Elemente dargestellt. Ungewöhnlich ist, dass man die Farben die man benutzen will erst definieren muss. Außerdem wird die erste definierte Farbe (hier Schwarz) auch als Hintergrundfarbe benutzt.

Man kann an ein derartiges Script auch Informationen übergeben und mit ihm auch Texte als Grafiken darstellen, wie das folgende Beispiel zeigt.


<?php
header("Content-Type: image/png");

$text=$_REQUEST['mail'];
$width = 200;
$height = 100;

$image = imagecreate($width,$height);

$black=imagecolorallocate($image,   0 ,   0, 0);
$red  =imagecolorallocate($image, 255 ,   0, 0);
$blue =imagecolorallocate($image, 0   ,   0, 255);
$white=imagecolorallocate($image, 255 , 255, 255);

imageline($image,0,    0,$width-1,  0, $red);
imageline($image,$width-1,  0,$width-1,$height-1, $red);
imageline($image,$width-1,$height-1,  0,$height-1, $red);
imageline($image,  0,$height-1,  0,  0, $red);

imagefill($image, 2, 2, $white);
imagestring($image, 3, 5, 5, $text, $blue);

imagepng($image);
imagedestroy($image);

?>

Das Script erwartet die Übergabe einen Parameters mail, wobei die Methode keine Rolle spielt. Eine Aufrufmöglichkeit wäre also:

grafik.php?mail=test@test.com

Die weiteren Funktionen des Scripts sind relativ selbsterklärend. Wirklich erzeugt wird die Abbil­dung übrigens erst mit dem Kommando

imagepng($image).

Wobei auch der Typ der Grafik festgelegt wird. In vielen älteren Beispielen findet man hier oft noch imagegif, was aus lizenzrechtlichen Gründen heute aber meist nicht mehr zur Verfügung steht.


3. Formulare in HTML und ihre Auswertung in PHP

Im Text wollen wir nicht auf die Grundlagen von HTML eingehen, dafür gibt es unter http://www.teamone.de/selfhtml/ eine sehr gute Anleitung. Lediglich auf die Arbeit mit Formularen soll hier eingegangen werden.

Alle Eingaben, die wir in den folgenden Abschnitten programmieren, erfolgen in ein HTML-Formu­lar. Ein Formular besteht mindestens aus den folgenden Tags: (Kursiv gesetzte Wörter sind Platzhalter für eigene Bezeichner)

<form action=”http://www.debacher.de/php/auswert.php” method=”get”>
 <input type=”text” name=”name” size=”Size” maxlength=”Länge”>
 <input type=”submit” value=”Absenden”>
 <input type=”reset”    value=”Verwerfen”>
 </form>

Mit dem Einleitungs-Tag muss ein Programm angegeben werden, das die Eingabedaten auswertet, in diesem Fall ein Programm namens auswert.php. Zusätzlich muss angegeben werden, wie dieses Pro­gramm die Daten erhält. Dazu gibt es die Möglichkeiten get und post. Bei der Methode get werden die Daten einfach an die URL des Auswertungs-Programmes angehängt:

auswert.php?name=Meier&vorname=Klaus

Bei der Methode post sieht man diese Daten nicht, da eine Art Dialog erfolgt. Bei der Programment­wicklung ist die Methode get praktischer, im endgültigen Programm ist post vorteilhafter.

Die zweite Zeile definiert ein Eingabefeld mit dem Namen name und der Größe Size. Diese Angabe betrifft nur die Darstellung auf dem Bildschirm. Die Maximalzahl der Zeichen die eingegeben wer­den kann wird auf den Wert Länge festgelegt. Normalerweise hat ein Formular natürlich mehr als ein Eingabefeld. Die einzelnen Felder werden da­bei durch ihre Namen unterschieden. Wichtig für jedes Formular ist auch ein Knopf zum Abschicken. Dazu dient der Typ submit. Die Da­ten im Formular werden ausgelesen und an das Auswertprogramm übergeben. Üblich in Formularen ist auch ein Resetknopf. Klickt man auf diesen Knopf, so werden alle Eingabefelder gelöscht.


Ergänzungen zu Formularen Als action kann anstelle eines eigentlichen Auswertprogrammes auch eine Mail verschickt werden:

<form action=”mailto:debacher@hsan.hh.schule.de” method=”post”>

Das Eingabefeld vom Typ „text” erlaubt auch die Angabe eines Wertes, der vorab in das Feld einge­tragen wird.

<input type=”text” name=”name” value=”Klausi”>

Diese Möglichkeit ist besonders dann wichtig, wenn man mittels Formular vorhandene Datensätze än­dern möchte.

Es stehen innerhalb eines Formulars nicht nur Eingabezeilen zu Verfügung.

Hidden

Eine Angabe der folgenden Art:

<input type=”hidden” name=”name” value=”Klausi”>

bewirkt keinerlei Darstellung auf dem Bildschirm. Dieses Feld wird mit seinem Wert einfach nur an das Auswertprogramm übergeben, ohne dass der Benutzer Eingabe machen kann oder überhaupt et­was von diesem Feld bemerkt. Dieser Tag macht nur Sinn, wenn ein VALUE mit angegeben wird.

Password

Auch dies ist nur eine Variation des Types Text.

<input type=”password” name=”name”>

Hierbei wird der Eingabetext nicht bzw. in Form von Sternchen auf dem Bildschirm dargestellt.

Textarea

Mit diesem Tag wird ein Eingabefeld definiert, dessen Höhe und Breite festgelegt werden müssen

<textarea name=”name” ROWS=“Höhe“ COLS=“Breite“>
 Vorgabetext 
</textarea>

Dem Eingabefeld kann man leider keine Maximalzahl von Zeichen übergeben. Höhe und Breite be­ziehen sich auf die Bildschirmdarstellung. Innerhalb des Bereiches kann gescrollt werden. Vorgaben werden hier nicht mit dem Value-Tag eingetragen, sondern zwischen Anfangs- und End­tag gesetzt.

Auswahlfelder

Will man keine freie Eingabe zulassen, sondern dem Benutzer nur die Auswahl zwischen vorgegebe­nen Werten ermöglichen, dann bietet sich die folgende Kombination an:

<select name=”name” size=“Zeilen“>
 <option value=”wert”>Beschreibungstext
 <option selected value=”wert”>Beschreibungstext
 ...
</select>

Hiermit stellt man dem Benutzer ein Feld zur Verfügung, das mit einem Mausklick geöffnet wird und die angegebenen Einträge zur Auswahl stellt. Nachdem ein Eintrag angeklickt wurde schließt sich das Auswahlfenster wieder. Ein Wert darf durch Zusatz von SELECTED als voreingestellt gekennzeichnet werden. Dieser Wert erscheint dann auch im geschlossenen Eingabefeld.

Der Select-Tag erlaubt zusätzlich das Schlüsselwort MULTIPLE, welches die Auswahl mehrerer Elemente gleichzeitig erlaubt. Für die Nutzung mittels PHP muss dann der Feldname auch ein Array kennzeichnen, also die eckigen Klammern beinhalten:

<select name=”name[]” multiple size=“Zeilen“>
 <option value=”wert”>Beschreibungstext
 ...
</select>

Checkboxen

Die Verwendung von Auswahlfeldern ist sehr platzsparend. Manchmal möchte man aber alle Optio­nen immer auf dem Bildschirm sehen, dann arbeitet man besser mit Checkboxen

<input type="checkbox" name="name1" value="wert1">Text1
<input type="checkbox" name="name2" value="wert2">Text2

Für jeden der Einträge taucht auf dem Bildschirm ein ankreuzbares Kästchen auf. Diese Kästchen sind voneinander unabhängig. Es können also z.B. alle Kästchen oder kein Kästchen angekreuzt sein. Lässt man den VALUE-Eintrag weg, so wird im Zweifelsfall der Wert on genommen.


Radiobuttons

Will man erreichen, dass immer nur eine Möglichkeit aus einer Auswahl markiert werden kann, dann arbeitet man besser mit Radiobuttons:

<input type=”radio” name=”name” value=”eintrag1”>Text1
<input type=”radio” name=”name” value=”eintrag2”>Text2

Hier haben alle Felder den gleichen Namen aber unterschiedliche Werte.

Ein kleines Beispiel

Das folgende Beispiel kann als Einstieg in ein eigenes Gästebuch dienen. Konkret handelt es sich hier um das Eingabeformular:

<!-- Formular für eine Telefonliste von Uwe Debacher 2004-->
 <html><head><title>Telefonliste</title></head>
 <body><center><h1>Telefonliste-Eingabeformular</h1></center>
 <form action="telefon.php" method="get">
 <!-- Ein normales Eingabefeld -->
 Name<br> 
 <input type="text" name="name" size="20" maxlength="50">
 <p>Vorname<br>
 <input type="text" name="vorname" size="20" maxlength="50">
 <p>Telefonnummer<br>
 <input type="text" name="telefon" size="20" maxlength="50">
 <p><input type="submit" value="Absenden">
 <input type="reset"  value="Verwerfen">
 </form>
 </body></html>

Lädt man die Seite in einen Browser, so ergibt sich folgendes Bild:

Informationssysteme-formular.png

Aufgabe 6: Erstelle ein einfaches HTML-Formular analog zu obigem Beispiel und speichere es im gleichen Verzeichnis ab, wie die bisherigen PHP-Dokumente.


Auswertung des Telefonlisten-Formulares

Nach diesen Einführungen in HTML nun das Programm zur Auswertung unseres Formulars. Das fol­gende Programm wertet die Daten aus und gibt eine Rückmeldung an den Benutzer:

<!-- Auswertungsprogramm fuer Telefonliste  letzte Aenderung am 17.4.04 -->
 <html><head><title>Telefonliste Auswertung</title></head><body>
 <center><h1>Telefonliste Auswertung</h1></center>
 <? 
   if (empty($_REQUEST['name'])):
      $_REQUEST['name']="Namenlos";
   endif; 
   echo "Name:    " . $_REQUEST['name'] . "<p>"; 
   echo "Vorame:  " . $_REQUEST['vorname'] . "<p>"; 
   echo "Telefon: " . $_REQUEST['telefon'] . "<p>"; 
 ?>
 </body></html>

In diesem Programm tauchen die Variablen $_REQUEST['name'], $_REQUEST['vorname'] und $_REQUEST['telefon'] auf, die den Namen der Felder im Formular entsprechen. PHP richtet für jedes der übergebenen Felder automatisch einen gleichnamigen Eintrag im Array $_REQUEST ein, sofern eine Eingabe gemacht wurde Falls keine Eingabe gemacht wurde ist der zugehörige Eintrag nicht eingerichtet. Das Vorhanden­sein einer Variablen kann mit if (empty($_REQUEST['name'])) abgefragt werden.

Die Zeile ist recht interessant, PHP wertet Variablen nämlich im Kontext aus. In der Zeile liegt ein boolescher (logischer) Kontext vor. Dann liefert jede vorhandene Variable TRUE und eine nicht vor­handene FALSE.

Aufgabe 7:
Erstelle das Auswert-Programm nach obiger Vorlage passend zu dem Formular aus Aufgabe 6 und teste das Zusammenspiel.

Aufgabe 8:
Erstelle ein eigenes Formular und das zugehörige Auswertscript. Das Formular könn­te z.B. das Bestellformular für einen Pizza-Dienst sein.

Hinweis: Eine Speicherung der Daten ist bisher nicht vorgesehen, die Grundlagen dafür fol­gen in den nächsten Abschnitten.

4. Umgebungsvariablen und Sicherheit

In vielen älteren Beispielen wird innerhalb von PHP direkt Bezug genommen auf die Feldna­men innerhalb des Formulars. Wenn es im Formular ein Input-Feld name gab, dann stand innerhalb von PHP direkt die Variable $name zur Verfügung. Dieses Service von PHP ist nicht ganz risikolos, wie das folgende Beispiel aus der PHP-Dokumentati­on zeigt:

<?php
 if ($username) {  // kann vom User mit get/post/cookies übermittelt werden
   $good_login = 1;
 }
 
 if ($good_login == 1) { // kann vom User mit get/post/cookies übermittelt werden
   fpassthru ("/highly/sensitive/data/index.html");
 }
 ?>

Ein Aufruf mit:

globals.php?good_login=1

würde in diesem Fall die Sicherheitsmechanismen überlisten, da ich dem PHP-Script von außen belieb­ige Variablen und ihre Werte unterschieben kann. Die Variablen können übrigens sowohl per get, als auch per post oder gar über den Cookie-Mechanismus übermittelt werden. Wenn das Script nicht auf die korrekte Initialisierung seiner Variablen achtet, dann wird es leicht angreifbar.

Aus diesem Grund ist in den aktuellen Versionen von PHP in der Konfigurationsdatei php.ini diese Art der Variablenübergabe deaktiviert. Normalerweise findet sich dort die Zeile:

register_globals = Off

nur wenn man diese Verändert zu

register_globals = On

stehen die globalen Variablen wie gewohnt zur Verfügung. Nach einer Änderung an dieser Konfigu­rationsdatei muss übrigens der Webserver Apache neu gestartet werden, um die Einstellungen zu re­gistrieren.

Da die Parameter-Übergabe an ein PHP-Script auch in den aktuellen Versionen auch bei register_globals = Off möglich sein muss haben die PHP-Entwickler eine sicherere Alternative entwickelt.

Es stehen dazu (ab PHP 4.1.0) mehrere assoziative Arrays zur Verfügung.

$_ENV[]		beinhaltet die Umgebungsvariablen 
$_SERVER		Felder die über den Webserver zur Verfügung stehen wie z.B. SERVER_NAME
$_GET[]		beinhaltet nur die per get übermittelten Felder
$_POST[]		beinhaltet nur die per post übermittelten Felder
$_COOKIE[]		nur die per Cookie übermittelten Felder
$_REQUEST[]		fasst die Arrays $_GET, $_POST und $_COOKIE zusammen.

Das folgende Listing zeigt den Umgang mit diesen Arrays.

<?php
 if($_GET['username']):
   $good_login = 1;
   fpassthru ("/highly/sensitive/data/index.html");
 endif;
 ?> 

In aktuellen Listings sollte man möglichst nur mit diesen assoziativen Arrays arbeiten. In der Über­gangszeit kann es notwendig sein noch mit den globalen Variablen zu arbeiten. Recht lästig ist es, wenn man auf einem System arbeitet, bei dem die globalen Variablen deaktiviert sind, man aber mit vorhandenen Skripten arbeiten möchte, die diese noch nutzen. Aber auch dafür gibt es innerhalb von PHP eine Lösung.

<?php
  if (!empty($_GET)):
        extract($_GET);
    endif;
    if (!empty($_POST)):
        extract($_POST);
    endif;
 ?>


5. Ein umfangreicheres Beispiel

Im folgenden HTML-Quelltext sind fast alle Möglichkeiten berücksichtigt:

<!-- Bespielformular von Uwe Debacher 2000 -->
 <html><head><title>Beispielformular</title></head><body>
 <center><h1>Beispielformular</h1></center>
 <form action="auswert.php" method="get">
 
 <!-- Ein normales Eingabefeld -->
 Wie heißt du?<br> 
 <input type="text" name="name" size="20" maxlength="50">

 <!-- Ein Textfeld -->
 <p>Sage mir deine Meinung:<br> 
 <textarea name="meinung" rows="3" cols="60">Ich habe keine eigene
 Meinung</textarea> 

 <!-- Ein Auswahlfeld -->
 <p>Welches Verkehrsmittel benutzt du zur Schule? 
 <select name="verkehrsm" size="1">
   <option value="b">BUS
   <option value="a">Auto
   <option selected value="f">Fahrrad
 </select>

 <!-- Checkboxen -->
 <p>Besuchst du einen oder mehrere der folgenden Leistungskurse?:<br>
 <input type="checkbox" name="mathe">Mathematik
 <input type="checkbox" checked name="info">Informatik

 <!-- Radiobuttons -->
 <p>Wie gefällt dir diese Schule?:<br>
 <input type="radio" name="urteil" value="s">Sehr gut   
 <input type="radio" name="urteil" checked value="g">Gut   
 <input type="radio" name="urteil" value="m">Mittel   
  
 <p><center> 
 <input type="submit" value="Absenden">
 <input type="reset"  value="Verwerfen">
 </center>
 </form>
 </body></html>

Der Browser macht daraus die folgende Darstellung:

Informationssysteme-formular1.png

Klickt man einfach nur auf „Absenden” ohne weitere Eingaben zu machen, so erscheint folgende URL in der Eingabezeile:

 http://localhost/auswert.php?name=&meinung=Ich+habe+keine+eigene+Meinung&verkehrsm=f&info=on&urteil=g

Damit sieht man genau, welche Daten an das Auswertungs-Programm übergeben werden.


Das Programm zur Formularauswertung

Nach diesen Einführungen nun das Programm zur Auswertung unseres Formulars. Das Programm wertet die Daten aus und gibt eine Rückmeldung an den Benutzer:

<!-- Auswertungsprogramm fuer das Bespielformular von Uwe Debacher,
    erstellt am 18.09.97
    letzte Aenderung am 11.04.2005 -->
 <html><head><title>Auswertung</title></head><body>
 <CENTER><H1>Auswertung</H1></CENTER>
 Hallo <b>
 <? if (!empty($_REQUEST['name'])):
     $name=$_REQUEST['name']; 
   else:
     $name="Namenlos";
   endif; 
   if (!empty($_REQUEST['meinung']))
      $meinung=$_REQUEST['meinung'];
   if (!empty($_REQUEST['verkehrsm']))
      $verkehrsm=$_REQUEST['verkehrsm'];
   if (!empty($_REQUEST['mathe']))
      $mathe=$_REQUEST['mathe'];
   if (!empty($_REQUEST['info']))
      $info=$_REQUEST['info'];
   if (!empty($_REQUEST['urteil']))
      $urteil=$_REQUEST['urteil'];
   echo $name ?>
 </b><p>
 <? switch($verkehrsm):
  case "b":
    echo "Hoffentlich bekommst du im Bus immer einen Sitzplatz";
    break;
  case "a":
    echo "Wo bleibt das Umweltbewußtsein? Fahr doch mit dem Bus";
    break;
  default:
    echo "Das Fahrrad ist doch ein umweltfreundliches Verkehrsmittel";
    break;
  endswitch; ?>

 <p>die Meinung:<br><i>
 <?echo $meinung ?>
 </i><br>zeigt deutlich, daß es dir auf dieser Schule <b>
 <? if ($urteil=="s"):
    echo "sehr gut";
  elseif ($urteil=="g"):
    echo "gut";
  else:
    echo "nicht so gut";
  endif; ?>
 </b> gefällt.<p>Als Leistungskurse hast du angegeben:<br>
 <? if ($mathe):
   echo "Mathematik<br>";
  endif;
  if ($info):
   echo "Informatik<br>";
  endif; ?>
 </body></html>

Es ergibt sich die folgende Ausgab­e:

Informationssysteme-formular2.png

In dem zugehörigen Listing sind nor­male HTML-Befehle und PHP-Befehle sauber getrennt.

Man darf aber sogar innerhalb von Strukturen die PHP-Sequenz beenden um normale HTML-Befeh­le einzubinden. Das spart jeweils den Echo-Befehl. Die Trennung hat noch einen weiteren Vorteil. Da im Echo-Befehl Textkonstanten in Anführungsstriche gesetzt werden müssen, machen viele HTML-Tags Probleme, da dort ebenfalls Anführungsstriche auftauchen. Diese „inneren” Anfüh­rungsstriche müssen dann als \” dargestellt werden, was die Übersichtlichkeit verringert. Aus:

<A HREF=”test.htm”>Nur ein Test</A> 

würde dann

echo ”<A HREF=\”test.htm\”>Nur ein Test</A>”;

6.Authentifizierung

Für die Zugriffssteuerung von Webseiten gibt es mehrere Möglichkeiten. Über eine spezielle Header­zeile, über einen Mechanismus der Webservers oder über PHP-Mechanismen.

Headerzeile

Das folgende Code-Fragment muss ganz am Anfang jeder PHP-Seite auftauchen, bevor irgendein HTML-Code geschrieben wird.

<?
  if (empty($_SERVER['PHP_AUTH_USER'])) {
    header("WWW-authenticate: basic realm=\"My Realm\"");
    header("HTTP/1.0 401 Unauthorized");
    exit;
  } else {
    $user=$_SERVER['PHP_AUTH_USER'];
    $pass=$_SERVER['PHP_AUTH_PW'];
    if (($user=="Uwe") && ($pass=="geheim")) {
      # statt mit den Konstanten zu vergleichen koennte man auch eine 
      # Datenbank abfragen.
      # Wenn alles ok ist, dann geht es unten weiter.
    } else {
      echo "<html><body>An diese Seiten darfst du nicht ran :-)</body></html>";
      # Hier alternativ Header-Zeilen wiederholen, wenn mehrfache Passwort-Versuche erlaubt sein sollen
      exit;
    }
  }
 ?> 
 
 <html><head><title>Authentifizierung erfolgreich</title></head>
 <body>
 Die Authentifizierung war erfolgreich!
 </body></html>

Hier wird zuerst getestet, ob die Variable $_SERVER['PHP_AUTH_USER'] vorhanden ist, der Besucher also schon einmal eine Anmeldung vorgenommen hat. Wenn nicht, dann wird über eine HTML-Header Zeile ein Anmeldefenster aufgebaut.

Wenn die Benutzervariable vorhanden ist, dann prüft man den Benutzernamen und das Passwort ge­gen eine eigene Datenbank. Ist alles OK ist, dann wird die Seite weiter abgearbeitet, ansonsten mit EXIT abgebrochen.

Arbeiten mit .htaccess

Bei den meisten Webservern kann man die Zugriffsrechte auf einzelne Verzeichnisse regeln, indem man dort eine Datei .htaccess ablegt. In dieser Datei tauchen die gleichen Befehle auf, wie in der Konfigu­rationsdatei des Webservers. Die Datei könnte z.B. folgenden Inhalt haben:

AuthType Basic
AuthName Passwortsicherung
AuthUserFile .htpasswd
Require valid-user

Sollen nur ganz bestimmte Benutzer ein Verzeichnis sehen können, so kann man die letzte Zeile auch durch z.B.

Require user meyer

ersetzen. Die Benutzernamen und Passworte, die natürlich verschlüsselt, stehen z.B. in der Datei .htpasswd. Diese Datei muss gegen Fremde Zugriffe geschützt sein. Einträge in dieser Datei erzeugt man mit dem Programm htpasswd:

/usr/bin/htpasswd2  -c  .htpasswd  meyer

Danach muss man dann zweimal das Passwort angeben. Der Schalter -c (create) ist nur zum Erzeu­gen der Datei beim ersten Aufruf notwendig. Die .htaccess hat den beschriebenen Effekt aber nur, wenn die Webserver-Konfiguration es grund­sätzlich erlaubt. Auch hier stehen die beiden Variablen $_SERVER['PHP_AUTH_USER'] und $_SERVER['PHP_AUTH_PW'] innerhalb des PHP-Programmes zur Verfügung, beide unverschlüsselt!

Authentifizierung mit PHP und Sitzungen

Die aktuellen Versionen von PHP bieten eine Möglichkeit an Daten über mehrere Seiten hinweg zu erhalten, die Sessions (Sitzungen). Dabei wird beim Start einer Sitzung eine SessionID erzeugt, das ist eine zufällige Zeichenkette wie z.B. 5b339af0eb839d2e4cecbaf9a7708a61

Damit lässt sich die Sitzung eindeutig identifizieren und innerhalb der Sitzung können beliebig Da­ten abgelegt werden. Diese Daten stehen dann jeder Sitzung mit der gleichen SessionID zur Verfü­gung.

Um beim Aufruf mehrerer Seiten den Zusammenhang zur gleichen Sitzung deutlich zu machen muss nur die SessionID übergeben werden. Das kann auf mehrere Arten geschehen, am einfachsten ist die Möglichkeit per Cookie. Sofern der Browser Cookies erlaubt legt PHP ein Cookie an, welches die SessionID beinhaltet. Sofern der Browser jetzt eine weitere Seite aufruft steht über dieses Cookie die ID zur Verfügung. Das Cookie bleibt solange erhalten, bis der Browser geschlossen wird.

Sofern der Browser also Cookies akzeptiert ist die Programmierung von Sessions ganz einfach, an­sonsten muss man die SessionID wie Formulardaten als Parameter übergeben. Das folgende Script wertet ein Anmeldeformular mit den Eingabefeldern name und passwd aus und stellt das Ergebnis in Sitzungsvariablen zur Verfügung.

<?php
   session_start();
 ?>
 
 <html><head></head><body>
 <h1>Formular-Auswertung</h1>
 
 <?php
    echo "Angegeben wurden folgende Daten:<p>";
    echo "Benutzername: " . $_REQUEST['name'] ."<br>";
    echo "Passwort:     " . $_REQUEST['passwd'] . "<p>";
    echo "Diese Daten werden jetzt unter der<br>Sitzungs-ID ";
    echo  session_id() . " gespeichert<p>";
    $_SESSION['userName']        =   $_REQUEST['name'];
    $_SESSION['userPasswd']      =   $_REQUEST['passwd'];
 ?>
 <a href="weiter.php">Weiter</a>
 </body></html>


Ganz wesentlich ist hier der Aufruf der Funktion session_start(). Falls noch keine Sitzung aktiv ist wird eine neue eingerichtet. Falls schon eine Sitzung aktiv ist, also z.B. ein Sitzungs-Cookie gefun­den wurde, wird diese geöffnet und die zugehörigen Variablen stehen wieder zur Verfügung.

Wichtig ist, dass die Zeile vor allen anderen Ausgaben aufgerufen wird

Will man nun Sitzungsdaten bewahren, so legt man sie einfach in dem Array $_SESSION ab, wie das hier im Beispiel mit dem Benutzernamen und dem Passwort geschieht. Innerhalb dieses Arrays können beliebige Daten (auf dem Server) abgespeichert werden, die dann alle über die ID der Sitzung zur Verfügung stehen. In allen weiteren Seiten kann man nun auf die gespeicherten Daten zugreifen:

<?php
   session_start();
 ?>
 
 <html><head><body>
 <h1>Anwendung mit Session</h1>
 
 <?php
    // Gibt den Inhalt der wiederhergestellten Variablen aus.
    echo "<p>Hallo " . $_SESSION['userName'] . ",";
    echo "<p>Passwort " . $_SESSION['userPasswd'] . ",";
    echo "<p>Session-id: " . session_id();
 ?>
 </body></html>

Hier wird zuerst wieder die Sitzung geöffnet. Anschließend stehen dann die gespeicherten Daten zur Verfügung.

Natürlich kann auch dieses Script weitere Daten innerhalb der Sitzung speichern, ändern oder lö­schen.

Eine Sitzungsvariable, hier z.B. userPasswd kann man mit session_unregister('userPasswd'); jeder­zeit löschen.

Die Sitzungsdaten werden meistens im Dateisystem gespeichert, unter Linux im Verzeichnis /tmp oder /var/lib/php. Dort existiert dann die Datei sess_5b339af0eb839d2e4cecbaf9a7708a61 mit folgendem In­halt:

userName|s:10:"Klaus Mann";userPasswd|s:6:"Geheim";

Man sollte daher alle Daten löschen, wenn sie nicht mehr benötigt werden. Alle Variablen kann man auf einen Schlag löschen mit session_unset(); mit session_destroy(); kann man die gesamte Sitzungs­datei entfernen. Der Aufruf der Funktion session_destroy() kann auch am Anfang eines Anmelde­scriptes sinnvoll sein, um einen definierten Anfangszustand zu erzielen ohne den Browser beenden zu müssen.

Wenn Seiten über eine zentrale Anmeldeseite geschützt werden sollen, dann muss immer geprüft wer­den, ob die Anmeldedaten zur Verfügung stehen. Wenn keine Daten vorhanden sind, weil z.B. die Anmeldeseite übersprungen wurde, dann muss der Benutzer zur Anmeldeseite verwiesen wer­den.

Ein paar Hinweise zur Sicherheit von Sessions

In der PHP-Dokumentation findet sich zur Sicherheit von Sessions der folgende Hinweis:

"Das Session-Modul bietet keine Garantie dafür, dass Informationen, die Sie in einer Session spei­chern, nur vom Benutzer gesehen werden können, der die Session erzeugt hat. Sie müssen zusätzli­che Maßnahmen ergreifen, um die Integrität der Session ihrer Wichtigkeit entsprechend angemessen aktiv zu schützen."

Das System zur Übertragung der ID per Cookie ist übrigens sicherer, als das zur Übertragung der ID per Formulardaten, speziell bei Übertragung per Methode get. Beim Speichern oder Übermitteln der URL würde dann auch die SessionID mitgeliefert werden, wodurch ein unauthorisierter Zugriff auf die Seiten möglich wird.

Weitere Informationen über PHP

PHP ist so weit verbreitet, dass es auch eine umfangreiche Online-Dokumentation gibt. Ein paar der möglichen Adressen:

http://www.php.net/			Die Quelle, die Homepage der PHP-Group.
http://www.selfphp.info/		Anleitung analog zu Selfhtml.
http://www.php-center.de/
http://www.php-homepage.de/