PHP ist eine serverseitige, in
HTML
eingebettete Scriptsprache - oder mit anderen
Worten: PHP-Scripte werden auf dem Server ausgeführt, im Gegensatz z.B. zum üblichen
JavaScript und Java
. Der Programmcode wird in die
HTML-Quelldatei geschrieben und somit i.A. nicht in einer extra PHP-Datei abgelegt. Als Script werden Programme bezeichnet, die keine eigenständigen Programme
sind, weil sie nicht kompliziert genug sind und andere Programme benötigen, um ausgeführt
zu werden.
Im Gegensatz zu HTML und JavaScript erscheint der eigentliche PHP-Code i.A. nicht auf der
Clientseite, d.h. der Quellcode, den man sich im Browser auch ansehen kann, enthält für
gewöhnlich keinen PHP-Code. Der
HTML-Code wird beim Abruf der Webseite, wie bei normalen Seiten auch, 1:1 an den Client
geschickt; der PHP-Code wird durch den Server ausgeführt und die Ausgabe dann, zusammen
mit den nicht interpretierten HTML-Scriptanteilen, an den Client gesandt. Es ist auch
möglich, PHP-Scripte ganz ohne (sichtbare) Ausgabe laufen zu lassen - was durchaus sinnvoll
sein kann.
Immer wenn man sich fragt, ob etwas möglich ist, ist zu überlegen, ob dazu eine Aktion auf dem Server (wo die Webseite liegt) oder auf dem Client (wo die Webseite angezeigt wird) notwendig ist. Z.B.: Ist es möglich, mit einem PHP-Befehl die aktuelle Webseite auszudrucken? Die Antwort ist ganz einfach: Damit auf dem Client die Seite ausgedruckt wird, muß dem Browser ein Befehl übermittelt werden. Da PHP aber auf dem Server ausgeführt wird, kann es diesen Befehl folglich nicht selbst in die Tat umsetzen. Auf dem Client wird aber z.B. JavaScript ausgeführt, das einen Befehl anbietet, der die Seite ausdruckt (sofern JavaScript aktiviert ist). Für viele andere Aktionen ist aber nicht einmal JavaScript nötig.
Im vorigen Kapitel wurde SQL beschrieben, jetzt wird PHP erklärt. Dies sind zwei
voneinander unabhängige Sprachen, die erst einmal nichts miteinander zu tun
haben! Auch wenn es Funktionen in beiden Sprachen gibt, die ähnlich heißen, können
sie sich doch deutlich unterscheiden. Im weiteren Verlauf wird gezeigt, wie man die beiden
Programmiersprachen zusammenführt. Auch dann muß man sich weiter im Klaren darüber sein,
was SQL und was PHP ist.
1 <? echo "Hello world!"; ?> 2 <?php echo "Hello world!"; ?> 3 <script language="php"> echo "Hello world!"; </script>Die erste Möglichkeit ist die kürzeste und damit bei vielen die beliebteste (wer ist nicht gerne faul?). Sie ist allerdings nicht XML
Die Sprache PHP ist hauptsächlich von C, aber auch von Java und Perl (die ihrerseits von C
beeinflußt wurden) geprägt. Aber auch für Pascal/Delphi-Programmierer ist die Sprache nicht
schwer zu erlernen.
Grundsätzlich gilt (merken!): Eine Anweisung wird immer mit einem ; abgeschlossen
und eine Funktion bzw. einen Funktionsaufruf erkennt man an runden Klammern ().
$var = 123; echo 'Die Variable $var hat den Wert 123!\n'; echo "Die Variable $var hat den Wert 123!\n";Das erste echo gibt Die Variable $var hat den Wert 123!
\
n aus, das
zweite hingegen Die Variable 123 hat den Wert 123! mit folgendem
Zeilenumbruch.
echo "Say \"Hello World\" my friend";Die Ausgabe bei diesem echo ist Say Hello World! my friend . Wie man sieht, müssen doppelte Anführungsstriche, die ausgegeben werden sollen, besonders gekennzeichnet werden. Dieses Vorgehen nennt man Escapen
$var1 = "Hallo"; $var2 = "Welt!"; echo $var1," ",$var2; echo $var1." ".$var2; print ($var1." ".$var2); $res = print ($var1." ".$var2);
$a = $b;
Wenn beide Operanden bei der Division vom Typ integer (ganzzahliger Wert) sind, ist das Ergebnis ebenfalls integer. Ist ein Operand eine Kommazahl, wird das Ergebnis auch eine Kommazahl.
Befehle wie $a = $a + 5 kann man etwas abkürzen:
$a += 5; // entspricht $a = $a + 5; $a *= 2; // entspricht $a = $a * 2; $i++; // entspricht $i = $i + 1; $i--: // entspricht $i = $i - 1;
$a = "Hello "; $b = $a . "World!"; // jetzt ist $b = "Hello World!"Auch hier lassen sich Befehle der Form $a = $a . noch etwas Text abkürzen:
$a = "Hello "; $a .= "World!";
|
|
Der Unterschied zwischen den beiden UND und ODER liegt in deren Priorität verglichen mit anderen Operatoren.
|
echo "Noch kein Kommentar!"; /* Dies ist ein Kommentar, der auch ueber mehrere Zeilen gehen kann */ // Dies ist wieder ein Kommentar, // der jeweils bis zum Ende der Zeile geht echo "Kein Kommentar mehr!";Die erste und die letzte Zeile sind Befehle, der Rest sind Kommentare.
int, integer | Integer |
real, double, float | Double |
boolean | Boolean |
string | String |
array | Array |
object | Objekt |
Wird einer Integervariablen ein Wert außerhalb des oben genannten Wertebereichs zugewiesen, erfolgt die Umwandlung in den Typ double.
Man kann Zahlen nicht nur in dem uns geläufigen Dezimalsystem (Basis: 10) eingeben. Es gibt auch noch das hexadezimale System (Basis: 16) und Oktalsystem (Basis: 8). Damit PHP weiß, was wir meinen, wird bei Hexadzimalzahlen ein 0x und bei Oktalzahlen eine 0 vorangestellt. Diese Zahlensysteme werden häufig wegen ihrer stärkeren Hardware-Nähe benutzt. Für uns sind sie im Moment eher weniger interessant.
Betrachten wir als erstes die doppelten Anführungszeichen (). Um
z.B. innerhalb der Anführungszeichen eines echo- oder
print-Befehls ein Anführungszeichen zu schreiben (so, daß es
ausgegeben wird), muß dieses mit einem Backslash (\)
versehen werden, weil es sonst den String beenden würde. Buchstaben mit einem
vorangestellten Backslash werden als escaped
characters bezeichnet. Eine Übersicht der escaped characters gibt es in
Tabelle 7.6.
|
Auch bei den einfachen Anführungszeichen gibt es escaped characters: Es können genau zwei verwendet werden, nämlich \ (einfaches Anführungszeichen) und \\ (Backslash).
Ein String ist im Prinzip ein Array aus Zeichen. Dadurch kann man problemlos auf einzelne Zeichen zugreifen. Z.B. wird mit $string[n] auf das n-te Zeichen im String zugegriffen. Erfordert eine Funktion als Parameter nun unbedingt ein richtiges Array, muß der String erst konvertiert werden. Die einfachste mir bekannte Möglichkeit ist mit Hilfe einer kleinen for-Schleife (hier in eine Funktion verpackt):
/** * Die Funktion wandelt einen String in ein Array um * und gibt dieses zurück * * @param string Der Text, der umgewandelt werden soll * @return array Array mit den einzelnen Buchstaben * des Textes */ function str2array($text){ $ar = array(); for ($i=0; $i<strlen($text); $i++){ $ar[] = $text[$i]; } return $ar; }
Die bisher unbekannten Befehle sollen erstmal nicht weiter stören; sie werden weiter unten erklärt. Mehr zu Funktionen im Kapitel 7.7.
Ein kleines Beispiel zu den bis hierher beschriebenen Datentypen:
Die Funktion int floor(float number) schneidet die Nachkommastellen ab und gibt
einen Integer zurück.
$a = 1234; // $a ist ein Integer $b = (double) $a; // $b ist ein Double mit dem Wert 1234 $a = 0123; // Oktalzahl (entspricht 83 dezimal) $a = 0xbad; // Hexadezimalzahl // (entspricht 2989 dezimal) echo floor((0.1+0.7)*10); // Ausgabe ist 7
$monat[1] = "Januar"; $monat[2] = "Februar"; $monat[3] = "Maerz"; $monat[4] = "April"; $monat[5] = "Mai"; $monat[6] = "Juni"; $monat[7] = "Juli"; $monat[8] = "August"; $monat[9] = "September"; $monat[10] = "Oktober"; $monat[11] = "November"; $monat[12] = "Dezember";Oder als Tabelle:
Zeile | Name |
---|---|
1 | Januar |
2 | Februar |
3 | Maerz |
4 | April |
5 | Mai |
6 | Juni |
7 | Juli |
8 | August |
9 | September |
10 | Oktober |
11 | November |
12 | Dezember |
Bei dieser Tabelle spricht man von einer 1-dimensionalen Tabelle, weil eine Koordinate (die Zeilennummer) ausreicht, um jedes Feld eindeutig zu bestimmen. Der Index (=Zeilennummer) wird in eckigen Klammern hinter dem Array-Namen angegeben.
Wenn man neben dem Monatsnamen auch die Anzahl der Tage im jeweiligen Monat
abspeichern will, braucht man eine 2-dimensionale Tabelle:
Zeile | Name | Tage |
---|---|---|
1 | Januar | 31 |
2 | Februar | 28 |
3 | Maerz | 31 |
4 | April | 30 |
5 | Mai | 31 |
6 | Juni | 30 |
7 | Juli | 31 |
8 | August | 31 |
9 | September | 30 |
10 | Oktober | 31 |
11 | November | 30 |
12 | Dezember | 31 |
Und das ganze in PHP:
$monat[1]["Name"] = "Januar"; $monat[1]["Tage"] = 31; $monat[2]["Name"] = "Februar"; $monat[2]["Tage"] = 28; $monat[3]["Name"] = "Maerz"; $monat[3]["Tage"] = 31; $monat[4]["Name"] = "April"; $monat[4]["Tage"] = 30; $monat[5]["Name"] = "Mai"; $monat[5]["Tage"] = 31; $monat[6]["Name"] = "Juni"; $monat[6]["Tage"] = 30; $monat[7]["Name"] = "Juli"; $monat[7]["Tage"] = 31; $monat[8]["Name"] = "August"; $monat[8]["Tage"] = 31; $monat[9]["Name"] = "September"; $monat[9]["Tage"] = 30; $monat[10]["Name"] = "Oktober"; $monat[10]["Tage"] = 31; $monat[11]["Name"] = "November"; $monat[11]["Tage"] = 30; $monat[12]["Name"] = "Dezember"; $monat[12]["Tage"] = 31;
In diesem Beispiel sehen wir zwei wichtige Eigenschaften von Arrays in PHP: Zum einen werden bei mehreren Dimensionen die Indizes einzeln in eckigen Klammern hinter dem Array-Namen angegeben. Zum anderen kann man bei PHP, im Gegensatz zu gewöhnlichen Programmiersprachen, für die Indizes beliebige Datentypen verwenden. Dadurch werden sogenannte assoziative Arrays möglich.
Wie kann man sich n-dimensionale Arrays vorstellen? Bei 3 Dimensionen ist es noch relativ einfach: Nimmt man mehrere 2-dimensionale Arrays und legt diese aufeinander, hat man die 3. Dimension. Ab der 4. Dimension wird das schon etwas schwerer. Aber im Zweifelsfall muß man sich die Arrays nicht vorstellen, sondern nur Daten in ihnen speichern.
In PHP gibt es neben Variablen auch Konstanten. Bei Konstanten ist, wie der Name
schon sagt, der Wert nicht veränderlich, außerdem sind sie überall abrufbar. Weitere
Unterschiede zu Variablen sind, daß Konstanten nur Werte von
Primitivtypen annehmen können und überhaupt
grundsätzlich von Variablen unterschieden werden müssen: Konstantennamen bestehen nur aus
alphanumerischen Zeichen, werden also nicht mit einem Dollarzeichen eingeleitet,
und sind völlig unabhängig von Variablen gleichen Namens. Um die Unterscheidung deutlich
zu machen, nimmt man daher für die Namen von Konstanten häufig nur Großbuchstaben.
Konstanten werden auch grundsätzlich anders definiert, nämlich mittels einer PHP-Funktion
namens define(). Als ersten Parameter übergibt man dieser Funktion den Namen der
zu definierenden Konstante und als zweiten deren Wert.
Folgendes Beispiel sollte das Gesagte verdeutlichen:
$var = "variabler Wert"; define("CONST", "konstanter Wert"); $var = CONST; echo $var; $CONST = "Problem?";
Der Beispielcode würde zu keinem Problem führen, denn CONST hat
weiterhin den Wert, der der Konstante mittels define() zugewiesen wurde;
gleichzeitig hat durch die Zuweisung in Zeile 3 auch $var den Wert der
Konstante angenommen.
Durch die letzte Zeile wird einfach eine neue Variable angelegt, die denselben Namen hat wie die Konstante. So sollte man jedoch ausdrücklich nicht programmieren! Es sollte nicht allzu schwierig sein, einen anderen Namen zu finden...
Zu einem Fehler würde es erst dann kommen, wenn man in der letzten Zeile das Dollarzeichen entfernte. Dann nämlich würde etwas versucht, was per definitionem nicht erlaubt ist: einer Konstanten einen neuen Wert zuweisen. Da in PHP für die Definition einer Konstanten jedoch eine Funktion benutzt wird, kommt man auch nicht so schnell durcheinander.
if (expr) statementexpr ist Platzhalter für die Bedingung und statement für den Befehl, der bei erfüllter Bedingung ausgeführt werden soll. Als Beispiel:
if ($a>$b) print "a ist groesser als b";Falls man mehr als einen Befehl hat, der ausgeführt werden soll, so ist auch das möglich. Man muß die Befehle nur in geschweifte Klammern einschließen:
if ($a>$b) { print "a ist groesser als b"; $b = $a; }
Man kann natürlich auch nur einzelne Befehle in geschweifte Klammern einschließen (und sei es nur, um einheitlich zu programmieren).
if ($a>$b) print "a ist groesser als b"; if ($a<=$b) print "a ist nicht groesser als b";...oder aber den ELSE-Zweig verwenden:
if ($a>$b) print "a ist groesser als b"; else print "a ist nicht groesser als b";
Analog zu IF kann man auch hier mehrere Befehle pro Zweig (IF, ELSE) angegeben; in diesem Fall müssen diese Anweisungen in geschweiften Klammern geschrieben werden. Kombinationen (z.B. geschweifte Klammern bei IF, aber keine bei ELSE) sind möglich.
if ($a > $b) { print "a ist groesser als b"; } elseif ($a == $b) { print "a ist gleich b"; } else { print "a ist kleiner als b"; }
<?php if ($a<$b): ?> <h1>a ist kleiner als b</h1> <?php endif; ?>Der HTML-Text wird nur dann ausgegeben, wenn die Bedingung A kleiner B erfüllt ist. Es können auch mehrere HTML-Zeilen benutzt werden. Hier machen geschweifte Klammern natürlich keinen Sinn, wie auch im folgenden Fall.
(Bedingung?Rückgabewert wenn true:Rückgabewert wenn false)An einem konkreten Beispiel:
<?php echo ($a < $b?"a ist kleiner als b":""); ?>Ich jedoch mag diese Syntax in der Regel nicht besonders, weil sie mir zu unübersichtlich ist. Mein Co-Autor ist da anderer Ansicht. ;-) Ein prima Anwendungsbeispiel für diese Kurzform ist die Funktion printf, die in Kapitel 7.8.1 beschrieben wird.
WHILE (expr) statementDie Bedeutung der WHILE-Schleife ist einfach: Solange die Bedingung expr erfüllt ist, wird die Anweisung statement ausgeführt. Falls die Bedingung von Anfang an nicht erfüllt ist, wird die Anweisung überhaupt nicht ausgeführt. Analog zu IF müssen mehrere Anweisungen, die zur selben WHILE-Schleife gehören, in geschweifte Klammern eingeschlossen werden.
Man kann auch die alternative Syntax nehmen:
WHILE (expr) : statement ... ENDWHILE;Das Ergebnis der folgenden Beispiele ist identisch; beide geben die Zahlen von 1 bis 10 aus.
/* Beispiel 1 */ $i=1; while ($i<=10) { print $i++; // $i wird erst ausgegeben und // dann inkrementiert // inkrement = Nachfolger // = um eins erhoeht (bei Zahlen) } /* Beispiel 2 */ $i=1; while ($i<=10): print $i; $i++; endwhile;
$i=0; do { print $i; } while ($i>0); // $i wird genau einmal ausgegebenFür Pascal/Delphi-Kenner:
FOR (expr1; expr2; expr3) statementDer erste Ausdruck expr1 wird genau einmal, am Anfang, ausgeführt. Damit initialisiert man in der Regel die Variable.
Analog zu IF müssen mehrere Anweisungen, die zur selben FOR-Schleife gehören, in geschweifte Klammern eingeschlossen werden.
Die FOR-Schleife kann im Prinzip auch mit einer WHILE-Schleife nachgebildet werden. Allgemein ausgedrückt (mit den oben verwendeten Bezeichnern) sähe das dann so aus:
expr1; while (expr2){ statement expr3; }
Die folgenden Beispiele geben jeweils die Zahlen von 1 bis 10 aus:
/* Beispiel 1 */ for ($i=1; $i<=10; $i++) { print $i; } /* Beispiel 2 */ for ($i=1;;$i++) { if ($i > 10) { break; } print $i; } /* Beispiel 3 */ $i=1; for (;;) { if ($i>10) { break; } print $i; $i++; } /* Beispiel 4 */ $i=1; while ($i<=10){ print $i; $i++; }Das erste Beispiel ist natürlich das geschickteste. Im vierten Beispiel ist die FOR-Schleife mit Hilfe von WHILE nachgebildet worden. Wir sehen als erstes die Initialisierung ($i wird auf 1 gesetzt). Die WHILE-Schleife läuft so lange, wie die Laufbedingung erfüllt ist ($i muß kleiner/gleich 10 sein). Dann kommt die eigentliche Anweisung (Ausgabe der Variablenwerte) und als letztes wird $i inkrementiert
Mit break wird die aktuelle Schleife verlassen.
Hier zwei Beispiele, die dasselbe Ergebnis ausgeben - einmal mit einer Reihe von IF-Anweisungen und einmal mit einer SWITCH-Anweisung gelöst:
/* Beispiel 1 */ if ($i == 0) { print "i ist gleich 0"; } if ($i == 1) { print "i ist gleich 1"; } /* Beispiel 2 */ switch ($i) { case 0: print "i ist gleich 0"; break; case 1: print "i ist gleich 1"; break; }
Es ist wichtig zu wissen, wie die SWITCH-Anweisung arbeitet, um Fehler zu vermeiden. Bei der SWITCH-Anweisung wird Zeile für Zeile (wirklich, Anweisung für Anweisung!) abgearbeitet. Am Anfang wird kein Code ausgeführt. Nur dann, wenn eine CASE-Anweisung mit einem Wert gefunden wird, der gleich dem Wert des SWITCH-Ausdruckes ist, fängt PHP an, die Anweisungen auszuführen. PHP fährt fort, die Anweisungen bis an das Ende des SWITCH-Blockes auszuführen oder bis es das erste Mal auf eine BREAK-Anweisung stößt. Wenn man keine BREAK-Anweisung an das Ende einer CASE-Anweisung schreibt, fährt PHP fort, Anweisungen über den folgenden Fall auszuführen. Z.B.:
/*Beispiel 3 */ switch ($i) { case 0: print "i ist gleich 0"; case 1: print "i ist gleich 1"; }
Falls $i gleich 0 sein sollte, würden beide Anweisungen ausgegeben, was in diesem Fall nicht erwünscht wäre.
Dieses Verhalten kann aber auch bewußt genutzt werden, wie man in den folgenden Fällen sieht:
/*Beispiel 4 */ switch($i) { case 0: print "i ist gleich 0"; break; case 1: case 2: print "i ist gleich 1 oder 2"; } /*Beispiel 5 */ switch($i) { case 0: print "i ist gleich 0"; case 1: case 2: print "i ist gleich 0 oder 1 oder 2"; }
Ein spezieller Fall ist der default-Fall. Dieser Fall trifft auf alles zu, was nicht von den anderen Fällen abgedeckt wird.
/* Beispiel 6 */ switch ($i) { case 0: print "i ist gleich 0"; break; case 1: print "i ist gleich 1"; break; default: print "i ist ungleich 0, 1"; }
include("dateiname");fügt an dieser Stelle den Inhalt der Datei dateiname ein. Dadurch ist es möglich, Quellcode, der in mehreren Dateien benötigt wird, zentral zu halten, so daß Änderungen einfacher werden.
Die Datei, die eingefügt wird, wird als HTML-Code interpretiert, deshalb muß, wenn in der Datei nur PHP-Code steht, diese Datei mit <?php anfangen und mit ?> aufhören (bzw. mit anderen PHP-Code-Markierungen, siehe Kapitel 7.2).
Wenn include() in Verbindung mit Bedingungen oder Schleifen eingesetzt wird, muß es immer in geschweiften Klammern geschrieben werden.
/* So ist es falsch */ if ($Bedingung) include("Datei.inc"); /* So ist es richtig */ if ($Bedingung){ include("Datei.inc"); }
test.txt
Dies ist ein einfacher Text.<br> Die Variable i hat den Wert <?php echo $i; ?>.<br>
test1.txt
Datei test1.txt
test2.txt
Datei test2.txt
Aber jetzt zu den Beispielen:
echo "Erstmal ein einfaches include/require<br>\n"; $i = 5; include("test.txt"); require("test.txt");
Die Ausgabe des Scripts ist, wie zu erwarten, folgende:
Erstmal ein einfaches include/require<br> Dies ist ein einfacher Text.<br> Die Variable i hat den Wert 5.<br> Dies ist ein einfacher Text.<br> Die Variable i hat den Wert 5.<br>
Auch in Schleifen können include() und require() verwendet werden.
echo "\nKleine for-Schleife fuer include<br>\n"; for ($i=1;$i<=3;$i++){ include("test.txt"); } echo "\nKleine for-Schleife fuer require<br>\n"; for ($i=1;$i<=3;$i++){ require("test.txt"); }
Auch hier ist die Ausgabe, wie zu erwarten:
Kleine for-Schleife für include Dies ist ein einfacher Text. Die Variable i hat den Wert 1. Dies ist ein einfacher Text. Die Variable i hat den Wert 2. Dies ist ein einfacher Text. Die Variable i hat den Wert 3. Kleine for-Schleife für require Dies ist ein einfacher Text. Die Variable i hat den Wert 1. Dies ist ein einfacher Text. Die Variable i hat den Wert 2. Dies ist ein einfacher Text. Die Variable i hat den Wert 3.
Als letztes ein Beispiel, wo man einen Unterschied zwischen include() und require() sehen kann:
echo "\nKleine for-Schleife fuer include<br>\n"; for ($i=1;$i<=3;$i++){ include("test$i.txt"); } echo "\nKleine for-Schleife fuer require<br>\n"; for ($i=1;$i<=3;$i++){ require("test$i.txt"); }
Hier gibt es eine Unterschied zwischen PHP3 und PHP4. Die Ausgabe bei PHP3 ist folgende:
Kleine for-Schleife für include<br> Datei test1.txt Datei test2.txt <br> <b>Warning</b>: Failed opening 'test3.txt' for inclusion in <b>.... Kleine for-Schleife für require<br> Datei test1.txt Datei test1.txt Datei test1.txt
Die Ausgabe von PHP4:
Kleine for-Schleife für include<br> Datei test1.txt Datei test2.txt <br> <b>Warning</b>: Failed opening 'test3.txt' for inclusion (include_.... Kleine for-Schleife für require<br> Datei test1.txt Datei test2.txt <br> <b>Fatal error</b>: Failed opening required 'test3.txt' (include_....
Die include()-Anweisung wird bei PHP3 und PHP4 identisch behandelt. In beiden Fällen wird versucht die Datein test1.txt,test2.txt und test3.txt einzufügen, wobei letzteres mangels vorhandener Datei nicht funktioniert.
Bei require() sieht das ganze etwas anders aus. PHP3 verhält sich, wie ich es erwartet habe. Die Datei wird einmal eingefügt und dann wird der Inhalt der Datei mehrmals aufgerufen. Bei PHP4 verhält sich die require() merkwürdigerweise wie die include() Anweisung. :-/
Der Sinn ist einfach: Bei umfangreichen Webseiten gibt es häufig eine Datei, die die zentralen Funktionen enthält. Da diese in den Webseiten benötigt werden, fügt man sie immer am Anfang ein. Soweit kein Problem. Sobald aber mehrere zentrale Funktionsdateien existieren, die sich auch untereinander benötigen, wird es schwierig, weil jede nur einmal eingefügt werden darf.
Bei einigen Programmiersprachen findet eine Unterscheidung zwischen Funktionen statt, die einen Wert zurückgeben und solchen, die keinen Wert zurückgeben. Z.B. in Pascal/Delphi gibt es neben den sog. Funktionen, die einen Wert zurückgeben, sog. Prozeduren, die keinen Wert zurückgeben. PHP macht hier, genau wie C und C++, keinen Unterschied.
Die Syntax lautet wie folgt:
function foo($arg_1, $arg_2, ..., $arg_n) { echo "Example function.\n"; return $retval; }Die Funktion bekommt die Argumente Arg_1 bis Arg_n übergeben und gibt den Wert der Variablen retval zurück. Wird kein return in der Funktion benutzt, hat man dasselbe Verhalten wie bei einer Prozedur in Pascal/Delphi. Rückgabewerte müssen (im Gegensatz zu Pascal/Delphi) nicht abgefragt werden.
Ein kleines Beispiel:
function my_sqr($num) { // gibt das Quadrat von $num zurueck return $num * $num; } echo my_sqr(4); // gibt 16 aus my_sqr(4); // ruft die Funktion auf, // es passiert aber nichts // (der Rueckgabewert wird ignoriert)
Variablenparameter werden mit einem & im Funktionskopf gekennzeichnet.
Ein kleines Beispiel:
function foo1 ($st) { $st .= 'und etwas mehr.'; // gleichbedeutend mit // $st = $st.'und etwas mehr.'; } function foo2 (&$st) { $st .= 'und etwas mehr.'; } $str = 'Dies ist ein String, '; echo $str; //Ausgabe:'Dies ist ein String, '; foo1 ($str); echo $str; //Ausgabe:'Dies ist ein String, '; foo2 ($str); echo $str; //Ausgabe: //'Dies ist ein String, und etwas mehr.';
Programmieren ist eine Sache. So zu programmieren, daß nicht nur man selbst, sondern auch
andere den Code später in möglichst kurzer Zeit verstehen und daraufhin auch erweitern
können, eine andere. Man darf auch nicht vergessen, daß es
passieren kann, daß man selbst irgendwann mal -- ein Jahr später oder so -- noch etwas
ändern will oder muß. Dabei ist es im Prinzip gar nicht so schwer: Das Ziel läßt sich
erreichen, indem man strukturiert, kommentiert und abstrahiert (d.h. einen Codeabschnitt
im Kontext betrachtet) sowie auf Wiederverwendbarkeit achtet. Für letzteres hat sich die
objektorientierte Denkweise als hilfreich erwiesen und auch in PHP Einzug gehalten (siehe
Kapitel 17). Selbst Kommentieren will gelernt sein --
hier bietet sich PHPDOC (Kapitel 13) an.
Wenn es jedoch zur Struktur kommt, fragt sich mancher angesichts ellenlanger Codekonstrukte schnell, wie man dem beikommen soll. Da wird geschachtelt, was das Zeug hält, Zeichen werden wild escaped und Parameter derart in Strings eingebettet, daß selbst der Autor des Scripts sich nicht mehr an eine Änderung heranwagen möchte. Viele Autoren scheinen einfach nicht zu wissen, welch überaus hilfreiche und strukturierende Funktionen PHP von Hause aus bietet. Vielleicht tragen ja diese Zeilen dazu bei, daß sich das ändert -- ich hoffe es jedenfalls.
Ähnlich wie in der Sprache C, von der PHP bekanntlich stark beeinflußt ist,
bietet unsere Scriptsprache die Funktionen printf() und sprintf().
Während printf() von print() abgeleitet ist, also letzlich
Text direkt ausgibt, dient sprintf() dazu, die Ausgabe der Funktion
als Argument (Parameter) einer weiteren Funktion oder einfach als Wert einer
Zuweisung zu benutzen.
int printf (string format [, mixed args...])
Auf den ersten Blick mag das sehr verwirren und zur Frage führen, was daran denn einfacher sein soll. Bevor ich das beantworten kann, muß ich aber erst einmal vollständig erklären, was man mit printf() machen kann.
Im einfachsten Fall, wenn der zweite Parameterteil entfällt, verhält sich
printf() genauso wie print(). Anders jedoch, wenn mehr als
nur ein String übergeben wird: Dann spielt die Funktion ihre Stärken aus.
Im ersten Parameter, dem String, können nämlich Platzhalter eingebaut werden,
die durch das ersetzt werden, was hinter dem String in Form weiterer Argumente
angegeben wird. Im Normalfall gibt es also genau so viele zusätzliche
Argumente, wie Platzhalter in den String eingebaut wurden -- der übrigens
auch vollständig in einer Variable enthalten sein kann.
Die genannten Platzhalter werden grundsätzlich mit einem Prozentzeichen
% eingeleitet, alles andere wird 1:1 ausgegeben -- ausgenommen
natürlich Ausgabe-Formatierungszeichen wie \n. Will
man nun das Prozentzeichen selbst ausgeben, muß man es durch zwei Prozentzeichen
ausdrücken. Reines Ersetzen allein ist jedoch noch lange nicht alles,
was uns diese Funktion bietet. Vielmehr kann man mithilfe der Platzhalter
genau vorgeben, wie der Wert, der an entsprechender Stelle eingefügt wird,
formatiert werden soll. Hierbei reichen die Möglichkeiten von der Festlegung
auf einen bestimmten Typ wie Zahlen zu verschiedenen Basen bis hin zum
Zurechtschneiden, Ausrichten und Auffüllen von Daten.
Die beiden wichtigsten Platzhalter sind übrigens %s und %d. Während erstgenannter einen beliebigen String als Wert akzeptiert, wird bei letzerem der Wert als Integer interpretiert und als Dezimalzahl ausgegeben. Alle Werte, die kein Integer sind, werden kurzerhand in eine 0 verwandelt. Auf diese Weise kann man also sicher stellen, daß an einer bestimmten Stelle im auszugebenden String auch wirklich eine Zahl steht. Die Tabelle Platzhalter listet alle erlaubten Platzhalter auf.
|
Zwischen dem einen Platzhalter einleitenden Prozentzeichen und dem Buchstaben, der die Typisierung des Platzhalters bestimmt, können noch weitere Angaben zur Formatierung gemacht werden. Diese sind allesamt optional und müssen, wenn sie angegeben werden, in folgender Reihenfolge auftreten:
Insgesamt ergibt sich somit folgende Syntax für Platzhalter:
%[Füllzeichen][Ausrichtung][Länge][Nachkommastellen]Typisierung
Im Allgemeinen braucht man die optionalen Angaben aber recht selten, so daß man dann ja immer noch mal nachlesen kann und es sich nicht wirklich merken muß.
Folgende Beispiele demonstrieren, wie sich das eben gelernte nun tatsächlich einsetzen läßt:
$tag = 13; $monat = 5; $jahr = 2009; $format = "%02d.%02d.%04d\n"; printf($format, $tag, $monat, $jahr); printf($format, 2*$tag, $monat, $jahr+2);
Gibt 13.05.2009 und ein anderes wichtiges Datum aus.
$betrag1 = 12.95; $betrag2 = 57.75; $betrag = $betrag1 + $betrag2; echo $betrag." "; printf("%01.2f", $betrag);
Gibt 70.7 70.70 aus.
Ist nun eine der Variablen für die Platzhalter im Formatierungs-String von anderen
abhängig, müßte normalerweise eine if-Abfrage vor dem Funktionsaufruf
getätigt werden. Ist diese Abfrage jedoch simpel, so kann man praktischerweise
auch die alternative Kurzvariante benutzen, die in Kapitel 7.2.12 vorgestellt
wurde. Um klar zu machen, daß es sich um eine solche handelt -- und ggf. auch, um
Ergänzungen mittels des Punkt-Operators zu erlauben --, sollte man diese in runden Klammern schreiben.
Das folgende Beispiel gibt für die Zahlen von 0 bis 9 jeweils aus, ob sie gerade oder ungerade ist:
for ($i=0;$i<10;$i++) printf("%d ist %sgerade.\n", $i, ($i%2==0 ? "" : "un") );
Seit PHP-Version 4.06 kann man die Argumente (zur Erinnerung: das sind die zusätzlichen Parameter, deren Werte anstelle der Platzhalter ausgegeben werden) durchnumerieren und entsprechend referenzieren. Dadurch ergibt sich nicht nur die Möglichkeit, Argumente in der Reihenfolge ihres Auftretens bei der Ersetzung zu vertauschen, sondern auch bestimmte Argumente mehrfach zu platzieren, dabei jedoch ggf. verschieden zu formatieren. Eine Referenz auf ein Argument definiert man nun mittels folgender Syntax:
%[Argumennummer\$][sonstige Formatierung]Typisierung
Folgendes Beispiel einer Sprach-angepaßten Datumsausgabe verdeutlicht die Vorteile:
// Angenommen, in $lang stehe die Sprache if ($lang == "de") $text = "Heute ist der %1\$d.%2\$d.%3\$04d."; elseif ($lang == "en") $text = "Today's date is %3\$04d-%2\$02d-%1\$02d."; $tag = 13; $monat = 5; $jahr = 2009; // Ausgabe je nach Sprache: // de -> Heute ist der 13.5.2009 // en -> Today's date is 2009-05-13 printf($text,$tag,$monat,$jahr);
sprintf() läßt sich besonders gut im Zusammenhang mit SQL-Abfragen (siehe
auch nächstes Kapitel) besonders gut einsetzen, weil man damit den eigentlichen
Abfrage-String sauber von den Werten trennen kann, die in PHP-Variablen stecken.
Das Prinzip ist immer das gleiche: Der eigentlichen Abfragefunktion
mysql_query() übergibt man als einzigen Parameter das
sprintf()-Konstrukt, das den SQL-String zusammenbaut und zurückgibt
(der Empfänger ist, bedingt durch die Schachtelung, die Abfragefunktion).
Innerhalb dieses Konstruktes herrscht eine einfache Zweiteilung: der erste Parameter
definiert das String-Grundgerüst, also i.A. alle SQL-Befehle und Vergleichsoperatoren;
die restlichen Parameter geben die Quellen (Variablen) für die Werte an, die die im
String-Grundgerüst einzubauenden Platzhalter ersetzen. Für diese Variablen gilt
übrigens, daß man sie mittels addslashes() behandeln sollte, falls
ihre Werte möglicherweise Hochkommata enthalten könnten -- diese werden durch
die erwähnte Funktion mittels Backslash escaped. Für die Rückwandlung bei der
Ausgabe an anderer Stelle steht die Funktion stripslashes() zur Verfügung,
die mit htmlentities() kombiniert gerade bei der HTML-Ausgabe
nützlich ist.
Eine schöne Aufgabe zum Gesagten findet sich in Kapitel 9.2.3.
Mit der Funktion number_format() bietet PHP die Möglichkeit, eine Zahl
zu formatieren. Insbesondere im Zusammenhang mit Internationalisierung läßt
sich diese Funktion nutzen, um Fließkommazahlen, die in PHP standardmäßig
bekanntlich entsprechend der amerikanischen Normen formatiert werden, anderen
Formaten entsprechend umzuwandeln, z.B. dem deutschen.
Die Syntax ist wie folgt, wobei wahlweise ein, zwei oder vier Parameter angegeben werden können (nicht drei!):
string number_format (float number [, int decimals [, string dec_point , string thousands_sep]])
Wird nur die zu formatierende Zahl als einziger Parameter übergeben, so wird diese mit einem Komma (,) als Trennzeichen zwischen Tausenden und ohne Nachkommastellen ausgegeben.
Bei zwei Parametern wird die Zahl mit decimals Stellen hinter dem Komma ausgegeben. Auch hier trennt wieder ein Komma jede Tausenderstelle; die Nachkommastellen werden vom ganzzahligen Wert durch einen Punkt getrennt.
Die Ausgabe bei Angabe aller vier Parameter schließlich unterscheidet sich durch die bei nur zweien dadurch, daß sie die Zeichen für den Dezimaltrenner und das Tausender-Trennzeichen (in dieser Reihenfolge) verwendet.
Achtung: Es wird nur das erste Zeichen des Tausender-Trennzeichens für die Ausgabe benutzt!
Das Beispiel verdeutlicht, wofür diese Funktion vornehmlich benutzt werden kann:
function Euro ($preis) { return sprintf("%s EUR\n", number_format($preis, 2, ',', '.') ); } echo Euro(17392.48365); // Ausgabe: 17.392,48 EUR