Die Programmiersprache PHP Diese Zusammenfassung ist nicht für blutige Anfänger gedacht, sondern eher als eine Art Stütze für jene, die sich bereits etwas mit PHP vertraut gemacht haben. Die wichtigsten Regeln und Befehle werden hier anhand kurzer Beispiele erläutert. Dabei gilt es zu beachten, dass alle Schlüsselwörter und vordefinierten Funktionen fett geschrieben sind und optionale Parameter in eckigen Klammern stehen. Ausserdem sind nur Statements mit einem Semikolon abgeschlossen, die auch als solche einen Sinn ergeben (d.h. genau so im Quelltext vorkommen könnten). Es gibt keine Garantie auf die Richtigkeit und Vollständigkeit dieser Kurzzusammenfassung. Mehr Informationen zu PHP findet man auf den am Ende des Dokuments genannten Websites. Grundlegendes PHP läuft im Produktivbetrieb i.d.R. auf einem Apache Server (meist Linux) und wird im Gegensatz zu JavaScript nicht auf dem Computer des Users ausgeführt, sondern auf dem Server (Ein Interpreter wandelt den Quellcode in Echtzeit um, es ist keine Kompilierung nötig). Normalerweise kontaktiert der Webbrowser den http-Server über die URL und bekommt die verlangte Datei zurück (falls diese existiert). Wenn aber die angeforderte Datei die Endung .php hat, wird diese erst durch den Parser gejagt, der den enthaltenen php-Code auswertet. Die so entstandene neue html-Seite wird dem Browser zurückgeliefert. Damit ist es eigentlich ausgeschlossen, dass Besucher ohne Hacker-Kenntnisse den php-Code zu sehen zu bekommen, da selbst der Browser keine „Ahnung“ hat, wie die Datei erzeugt wurde. Zum Erstellen eines PHP-Programms benötigt man einen Texteditor (etwa Notepad++) sowie ein Framework (etwa XAMPP). Für die Ausführung muss auf dem Computer ein Webserver mit PHP laufen, oder aber man lädt die Dateien zum Testen immer auf einen PHP-fähigen Server im Internet hoch. Dateiendung ist jeweils .php. Syntax: Befehle werden mit einem Semikolon abgeschlossen und sind grundsätzlich case sensitive, Blöcke werden in geschweifte Klammern geschrieben. PHP-Code kommt zwischen folgende Markierungen (alles andere wird als html interpretiert): <?php … ?> Sonderzeichen müssen evtl. maskiert werden (z.B. \", oder stattdessen &quot;) Auskommentieren von Code durch /* */ resp. // Variablendeklaration durch ein Dollar-Zeichen, ohne Angabe eines Datentyps (wird erst bei der Wertzuweisung festgelegt). Explizite Typkonvertierungen sind erlaubt (int, float, string, boolean): $zahl1 = (int)$zahl2; Konstanten werden nicht über das Dollarzeichen angesprochen und auch nicht ausgewertet in Strings. Arrays können nicht konstant sein. Definition: define("VS", "1.02"); Funktionen: Rückgabewert = Funktionsname(Parameter); function uhrzeit($wert) { … return ($wert); } echo "uhrzeit($wert)"; // Syntax eines Funktionsaufrufs // Funktionsdefinition // wird nicht ausgewertet in einem String! Scope: In Funktionen sind ausserhalb definierte Variablen nicht gültig (resp. werden neu definiert). Ausserdem gibt es weder Pointer noch Referenzen, d.h. alle in einer Funktion berechneten Werte müssen aus- oder zurückgegeben werden. Befehle Operatoren und math. Funktionen: +, -, *, /, %, ., +=, ++, .=, exp, sqrt, pow, bcpow, abs, sin, asin, min, max, log, rand, ceil, floor, bindec, hexdec, rad2deg, pi Vergleichsoperatoren und Verknüpfungen: ==, !=, <>, <=, >=, &&, ||, or, and Datentypen prüfen: gettype($test_var) if ($test_var != (INT)$test_var) is_float($test_var) is_numeric($test_var) ctype_digit($test_var) // um welchen Datentypen handelt es sich? // ist es ein Integer? // ist es eine Fliesskommazahl? // ist es eine Zahl? // ist es eine Ganzzahl? Die Programmiersprache PHP | 1 Strings: echo "hallo Welt $v"; echo 'hallo Welt $v'; strpos($var, "…") trim($var [,…]) strtolower($var) sprintf("%01.2f", $zahl); strlen($var) implode([$sign,] $var) str_replace($s, $r, $var) Vordefinierte Variablen: $_SERVER['PHP_SELF'] $_SERVER['REMOTE_ADDR'] $_SERVER['HTTP_HOST'] $_SERVER['REDIRECT_URL'] $_SERVER['REDIRECT_STATUS'] $_GET['variablenname'] $_POST['variablenname'] // Dateinamen des ausgeführten Skripts (relativ zum Wurzelverzeichnis) // IP-Adresse des Rechners, der die Seite angefordert hat // Domainname // die ursprünglich aufgerufene URL // ursprünglicher Statuscode (Fehlercode bei nicht existierenden Seiten) // greift auf die angegebene Variable eines Formulars zu (Get-Methode) // greift auf die angegebene Variable eines Formulars zu (Post-Methode) Datum und Uhrzeit: date("d.m.y") date("H:i:s") // Textausgabe (Variablen werden ausgewertet) // Textausgabe (Variablen werden nicht ausgewertet) // Position des gesuchten Strings in $var (falls vorhanden, sonst 0) // entfernt whitespaces [oder andere Zeichen] am Anfang & Ende // String in lower case konvertieren (ebenso existiert strtoupper) // Ausgabe formatieren – hier 2 Nachkommastellen // Anzahl der Zeichen // verbindet Array-Elemente zu einem String // ersetzt alle $s in $var durch $r // gibt das Datum aus (d = Tag, m = Monat und y resp. Y = Jahr) // gibt die Urzeit aus (H = Stunde, i = Minute, s = Sekunde) Kontrollstrukturen: if ($number == "4") { … } elseif (…) { … } else { … } switch ($number) { case "4": … break; … default: … break; } while ($number < 10) { … } do { … } while ($number < 10); for (int $i = 0; $i < 10; $i++) { … } foreach ($arrayname as $i => $x) { … } // alle Elemente durchgehen (Index in i, Wert in x) Dateizugriff: $handle = fopen ("test.txt", r); $size = filesize("test.txt"); if (filetype($filename) == 'file') { … } $inhalt = fgets($handle, 4096); $inhalt = fread($handle, $size); fclose($handle); $handle = fopen ("test.txt", w); fwrite($handle, $inhalt); is_dir opendir readdir closedir // weitere Modi: a, a+, w, w+, r+ // liefert die Dateigrösse // ist es eine Datei? // liest eine Zeile ein, max. 4096 Zeichen // liest die ganze Datei ein // Funktionen für Verzeichnisse Arrays: $col[] = array("red", "blue"); $col[] = "yellow"; $col [15] = "green"; print_r($col); $a['surname'] = "Fritz"; $a[] = array('key1' => value1, …); count($col) sort($col); $new = array_unique($col); $a[0][surname] = "Fritz"; array_multisort($sortby, MODE, $a); array_slice($a, 0, 4) explode($sign, $string) split("\|", $string, $maxNumElem) list($v1, $v2) = array("…", "…"); // Initialisierung eines Arrays // wird automatisch in das nächste freie Feld geschrieben // Zugriff auf das 16. Element (Elem. 4 – 15 ungenutzt) // gibt den Inhalt des Arrays formatiert aus // Assoziatives Array (Zugriff auf Elemente über Keys) // muss eine gerade Anzahl Elemente sein // gibt die Anzahl der Elemente des Arrays zurück // Array sortieren aufsteigend (rsort für absteigend) // ‚löscht‘ doppelte Einträge (falls gleiche Datentypen) // mehrdimensionales Array // mehrdim. Array sortieren (SORT_ASC / SORT_DESC) // liefert ein Array mit den ersten vier Einträgen von $a // gibt ein Array aus Strings zurück (Trennzeichen $sign) // zerlegt Zeichenkette in ein Array (Trennzeichen ist hier |) // weist Variablen zu, als wären sie ein Array Weitere nützliche Funktionen für Arrays: array_diff (Unterschiede zw. 2 Arrays), in_array (Wert vorhanden?), min (Element mit niedrigstem Wert), max, array_merge, range (Array mit Unter- und Obergrenze), shuffle (mischen), asort (nach Wert sortieren, aber Indices beibehalten), arsort, ksort (nach Index sortieren), krsort Mails versenden: Die Programmiersprache PHP | 2 $header = "MIME-Version: 1.0\n"; $header .= "Content-type: text/html; charset=iso-8859-1\n"; // oder text/plain $header .= "From: $absender\nReply-To: $antwortemail\n"; $header .= "Cc: $cc\nX-Mailer: PHP ". phpversion(); if (mail($empfaenger, $betreff, $mailtext, $header)) { echo "mail sent"; } Einbinden von Programmbibliotheken: include('folder/file.php'); require('folder/file.php'); require_once('folder/file.php'); // Programm wird weiter ausgeführt, falls nicht vorhanden // Programm bricht ab, falls Datei nicht gefunden wird // verhindert, dass eine Datei mehrmals eingebunden wird Ist auch praktisch, wenn man z.B. bei jeder Datei auf der Homepage denselben Header verwenden möchte (einfach include an der entsprechenden Stelle). Include-Dateien sollten die Endung .php haben. Sessions. Daten des Benutzers während der gesamten Nutzungsdauer zwischenspeichern (bis der Browser geschlossen wird oder die Zeit abgelaufen ist): session_start(); // neue Session starten (muss GANZ am Anfang einer Datei stehen) $_SESSION['test'] = 1; // eine Sessionsvariable anlegen session_cache_limiter(); // gibt die maximale Gültigkeitsdauer einer Session aus session_cache_limiter(20); // setzt den Timeout-Wert (in Minuten) unset($_SESSION['test']); // gezielt eine Sessionsvariable zerstören Grafiken erstellen (etwa für CAPTCHA): <img src="generate_png.php" /> $bild = ImageCreateTrueColor($w, $h); $bild = ImageCreateFromPNG($filename); $c = ImageColorAllocate($bild, $r, $g, $b); ImageFilledRectangle($bild, $x, $y, $w, $h, $c); ImageFilledEllipse($bild, $x, $y, $w, $h, $c); ImageString($bild, $nr, 0, 0, $email, $c); ImagePNG($bild); ImageDestroy ($bild); // grafikerzeugende php-Datei in html einbinden // Bild anlegen (alternativ imagecreate) // Bild aus png-Datei laden // eine Farbe erstellen // Rechteck zeichnen: Mittelpunkt x, y // eine Ellipse zeichnen // Text hinzufügen ($nr ist eine Zahl) // Bild erzeugen // Ressourcen freigeben Objektorientierte Programmierung (OOP). Vorteile: übersichtlich, wiederverwertbar, erweiterbar, Sichtbarkeit und Zugriff einschränkbar. Alles wird als ein Objekt betrachtet, das Attribute (Eigenschaften) und Methoden (Dienstleistungen) besitzt. Die Klasse bildet den Bauplan, das Objekt den fertigen Bau (Instanz). Klassen können von anderen Klassen abgeleitet werden – öffentliche Attribute und Methoden werden dabei weitervererbt. class test extends basis // test ist eine von basis abgeleitete Klasse { public $name; private $name2; function getName() { echo $this->name2; }; } $obj1 = new test; $obj1->name = "hallo welt"; // oder var $name; (veraltet) // Funktionen direkt inline definieren // neues Objekt erstellen // Direktzugriff auf public-Variablen Weitere nützliche Funktionen: empty($_GET['email']) isset(…) exit(…) phpinfo(); exif_read_data($filename) htmlentities($string) round($var, 2) readfile($filename); // prüft, ob das Formularfeld ‚email‘ leer ist // prüft die Existenz einer Variablen // beendet das aktuelle Skript und gibt eine Meldung aus (wie die) // gibt Informationen über den Webserver und die PHP-Installation aus // EXIF-Daten von jpg-Dateien auslesen // Zeigt html / php-Code an, ohne diesen auszuwerten // rundet die angegebene Zahl auf 2 Nachkommastellen // liest den Inhalt einer Datei und schreibt ihn in den Ausgabepuffer MySQL Datenbanken Datenbank = Sammlung von Informationen über ein Thema (in einer Tabelle) Datenbanksystem = Datensammlung + Verwaltungssystem (Daten erfassen, verändern, suchen und auswerten) Die Zeilen enthalten i.d.R. die Einträge (Datensätze), die Spalten der Tabelle die Attribute. Jeder Datensatz hat eine eindeutige ID (Schlüssel), damit eine Verwechslung ausgeschlossen ist. Grundprinzip: keine doppelten Daten (Datenredundanz möglichst gering halten) Tabellen aufteilen und verknüpfen: reduziert den Verwaltungsaufwand und die Datenredundanz erheblich Die Programmiersprache PHP | 3 Primärschlüssel (z.B. ID, darf nur einmal vorkommen in einer Tabelle) und Fremdschlüssel (ist der Primärschlüssel einer anderen Tabelle, kann deshalb auch mehrfach vorkommen) Ein Datenfeld hat einen Namen, einen Datentyp (string, int, float) und eine (max. zulässige) Länge. Entity Relationship Model: Beziehungen zwischen den Entitäten (Objekte von aus der realen Welt abgebildeten Modellen). Jede Entität hat verschiedene Attribute. Darstellung: Entitäten als Rechtecke, Beziehungen als Rauten und Attribute als gerundete Rechtecke darunter. MySQL einrichten unter XAMPP: Aktivität prüfen (per phpinfo oder auf localhost), auf localhost/phpmyadmin eine neue Datenbank einrichten (Reiter SQL), Datendatei laden und ausführen lassen (Fenster SQL-Befehle). Daten auswählen: SELECT [rechenoperation|funktionsauswahl] [DISTINCT] spaltenname1, spaltenname2 // Distinct schliesst inhaltlich gleiche Werte aus [spaltenname3 AS `new name`] // Spaltenüberschrift ändern FROM tabellenname [WHERE bedinungen1 [OR bedingung2] [AND bedingung3] [<`value`]] [GROUP BY spalten] [HAVING aggregatfunktionen] [ORDER BY spalte1 [ASC] [DESC] [, spalte2 [ASC] [DESC]]] [LIMIT [Anfang][Zeilenanzahl]] SELECT * FROM datenbankname; // alle Spalten auswählen Auf einzelne Spalten (oder auf alle Spalten) können Aggregatsfunktionen angewendet werden: MIN() MAX() COUNT() SUM() AVG() // Minimum, Maximum, Anz. Elem., Summe, Durchschnitt Datumsfunktionen (YEAR, WEEKDAY, MONTH, DAYNAME, WEEK, DAYOFMONTH, DAYOFYEAR, DAYOFWEEK, QUARTER, TO_DAYS) erwarten als Parameter jeweils ein Datum und können etwa für die WHERE-Bedingungen zur Hilfe gezogen werden. Im folgenden Beispiel müssten in der Spalte spalteX natürlich Datumsdaten vorhanden sein: YEAR(spalteX) > 1980 // liefert nur Einträge mit Datum neuer als 1980 Konstanten definieren: Alle benötigten Konstanten sollten in eine Datei ausgelagert und mit require_once eingebunden werden. Dazu zählen MYSQL_HOST (meist localhost), MYSQL_BENUTZER, MYSQL_KENNWORT, MYSQL_DATENBANK. Verbindung zwischen PHP und MySQL: $db = mysql_connect(MYSQL_HOST, MYSQL_BENUTZER, MYSQL_KENNWORT); // Verbindungsaufbau if (!$db) { echo mysql_error(); } $sql = "CREATE DATABASE `name`"; // Befehl „DB ‚name‘ anlegen“ erstellen $result = mysql_query($sql); // Befehl ausführen $selected = mysql_select_db(MYSQL_DATENBANK); // eine Datenbank auswählen $sql = "CREATE TABLE `tab1` ( `spalte1` INT(10) NOT NULL // NOT NULL = Feld darf nicht leer sein AUTO_INCREMENT PRIMARY KEY, // AUTO_INCREMENT = autom. ID schreiben `spalte2` VARCHAR(150) NULL // VARCHAR(150)= Inhalt ein String, <=150 Zeichen ) ENGINE = MYISAM"; $result = mysql_query($sql); // MySQL-Anweisung ausführen $sql = "INSERT INTO `tab1` ( `spalte1`, `spalte2` ) VALUES ( NULL, 'test' ); "; // Werte in Tabelle einfügen $sql = "SELECT * FROM tab1"; // alle Spalten von ‚tab1‘ auswählen $result = mysql_query($sql); while ($zeile = mysql_fetch_array($result, MYSQL_ASSOC)) { echo $zeile['spalte1']; // spalte1 aller Zeilen ausgeben … } mysql_free_result($result); $sql = "SELECT // die Spalten zweier Tabellen verknüpfen tab2.spalteZ, tab1.spalteY FROM tab2 LEFT JOIN tab1 ON tab2.spalteX = tab1.spalteY"; // Verknüpfungsbedingung Weitere nützliche Funktionen: Die Programmiersprache PHP | 4 CurDate() error_reporting(E_ALL); mysql_error(); mysql_num_rows($result) // liefert das aktuelle Datum zurück // sorgt dafür, dass alle Fehlermeldungen angezeigt werden // gibt die letzte Fehlermeldung zurück // liefert die Anzahl Zeilen Tipps und Hinweise für Datei- und Ordnernamen nur Kleinbuchstaben und Bindestrich resp. Underline verwenden mitten in html kann auch php aufgerufen werden und umgekehrt anstelle der Operatoren + - * / können auch die Befehle bcadd, bcsub, bcmul und bcdiv verwendet werden Aufgepasst bei Gross- und Kleinschreibung! Falsch geschriebene Variablennamen führen oft zu langer Fehlersuche, da die anders geschriebene Variable einfach neu angelegt / definiert wird. <> bedeutet dasselbe wie != (ungleich) PHP-Programme müssen nicht immer sichtbar sein (also Endung .php). Content-Management-System (CMS) mit dem Namen TYPO3 z.B. ist auch ein PHP-Programm: <meta name="generator" content="TYPO3 4.1 CMS" /> XAMPP ist eine Zusammenstellung eines Installationspaketes, das alle wichtigen Bestandteile enthält (PHP, Apache, MySQL, etc.). Zur Installation der Lite-Variante einfach „setup_xampp.bat“ aufrufen, anschliessend „xampp_start.exe“ öffnen und im Browser „localhost“ eintippen (Hinweis: Kommandofenster nicht schliessen!). Die eigenen Programme kommen in den Ordner „htdocs“ des Installationsverzeichnisses. Die Programme können dann über den Befehl „http://localhost/[Ordnername in htdocs]/Dateiname.php“ ausgeführt werden. Ein @ vor einem Befehl sorgt dafür, dass keine Fehlermeldung ausgegeben wird In doppelten Anführungszeichen $_GET (und andere Hashes) wie folgt benutzen: "$_GET[var_name]" Empfehlenswerte Erweiterungen für den Browser Firefox: FirePHP und FireFTP CATPCHA = Completely Automated Public Turing test to tell Computers and Humans Apart, sind Grafiken mit Buchstaben und Zahlen zur Identifikation eines menschlichen Users (Spam vermeiden etc.). Eine Message-Box kann mit folgendem Befehl aufgerufen werden (Umweg über JavaScript): echo "<script>alert('ungültige E-Mail Adresse')</script>"; Error Handling: Im Allgemeinen sollten Fehler abgefangen und adäquat behandelt werden. Es ist sogar empfehlenswert, sich bei schwerwiegenden Fehlern (etwa kein Zugriff auf eine Datenbank eine fehlende Datei) eine Mail senden zu lassen, damit der Fehler schnellstmöglich behoben werden kann. Vor dem Eintragen von Daten in eine SQL-Tabelle überprüfen, ob der Eintrag bereits existiert (Redundanz vermeiden). Bei MySQL-Befehlen wird zwischen ' und ` unterschieden; letzteres wird nur für Tabellen-, Spalten- und Datenbanknamen verwendet. Für das Anlegen und Abändern von Datenbanken und Tabellen sollte phpMyAdmin verwendet werden (einfacher und komfortabler). Statt SELECT * besser die wirklich benötigten Spalten angeben (ist schneller). Sicherheit Überall dort, wo Besucher der Homepage die Möglichkeit haben, Text zu hinterlassen (etwa einen Gästebucheintrag), ist besondere Vorsicht geboten. Die Eingabe muss in jedem Fall auf Anführungsstriche, htmlund JavaScript-Tags, aber auch auf seine inhaltliche „Korrektheit“ und etwaige enthaltene URLs zu zwielichtigen Seiten überprüft werden. In PHP können Tags und weitere „Störenfriede“ bequem mit den Befehlen array_walk, strip_tags und htmlspecialchars eliminiert werden. E-Mail Adressen sollten nie als Text auf der Homepage angezeigt werden. Am sichersten ist die Verwendung von Bildadressen. Für alle Dateien, die zwingend benötigt werden (etwa Konfigurationen), require statt include verwenden. Immer die Dateiendung .php verwenden, wo PHP-Code drin steht. Auch inkludierte Files ohne PHP-Code sollten die Dateiendung .php haben (sonst läuft man Gefahr, dass die Besucher den Quelltext zu sehen bekommen). Die Programmiersprache PHP | 5 Übertragene Daten sollten immer überprüft und nie direkt verwendet werden (bei $_GET und $_POST), insbesondere dann, wenn diese Parameter Dateinamen spezifizieren (im Notfall mit einer Liste von zulässigen Dateinamen vergleichen). Information Hiding (Tarnung): expose_php = off versteckt die php-Notiz im Fileheader; damit nun auch z.B. .html-Files geparst werden, muss folgende Zeile in die .htaccess-Datei im Stammverzeichnis: AddType application/x-httpd-php .html Schreibrechte in allen Homepageverzeichnissen und für möglichst alle Files einschränken und Directory-Listings vermeiden (entweder in jedes Verzeichnis eine index.html-Datei setzen oder eine .htaccess-Datei mit folgendem Inhalt im Stammverzeichnis der Homepage platzieren: Options -Indexes Vorsicht mit Cookies: Diese können leicht geklaut werden. Auch bei Sessions ist Vorsicht geboten: Weder Passwörter noch andere wichtige Daten sollten in Sessions abgelegt werden. Während der Entwicklungsphase alle Fehlermeldungen anzeigen lassen, auf dem Server wenn möglich alle deaktivieren (Fehlermeldungen können Angreifern viel verraten). error_reporting(E_ALL); ini_set("display_errors", "off"); ini_set("display_startip_errors", "off"); // resp. "on" zum Debuggen HTML-Tipps Alle Marken, die nicht durch ein </…> wieder abgeschlossen werden, sollten mit einem /> geschlossen werden: <br /> für Formulare: mit GET werden die Daten über die URL-Zeile übergeben (einerseits für jeden sichtbar, andererseits beschränkt). Alternativ kann POST verwendet werden: <form action="" method="POST" name="" id=""> … </form> Hidden-Felder als versteckte Informationsträger in Formularen nutzen: <input type="hidden" name="Name" id="ID" value="Wert" /> <pre> … </pre> wird für vorformatierten Text verwendet, der genau so dargestellt werden soll, wie er zwischen diesen Markierungen steht Konkrete Beispiele Link für “zurück”: if (isset($_SERVER['HTTP_REFERER'])) { echo "<br /><a href=\"$_SERVER[HTTP_REFERER]\">< back</a><br /><br />"; PDFs erzeugen. Dies geht ganz einfach mit der kostenlosen Hilfsbibliothek FPDF: require('fpdf.php'); // Bibliothek fpdf einbinden $pdf = new FPDF(); // neues PDF erzeugen $pdf->AddPage(); // Seite hinzufügen $pdf->SetFont('Arial', 'B', '12'); // Schrift Arial, Grösse 12, fett $pdf->Cell(40, 10, 'Hello World'); // Rechteck (Höhe 10, Breite 40) $pdf->Output(); // PDF anzeigen im Browser Verzeichnis einlesen: $verzeichnis = "."; if (is_dir($verzeichnis)) { if ($handle = opendir($verzeichnis)) { while ($file = readdir($handle)) { … } closedir($handle); } // aktuelles Verzeichnis (wo php-Datei gespeichert ist) // ist es ein (gültiges) Verzeichnis? // Verzeichnis öffnen // Verzeichnis einlesen (liefert alle Dateinamen) // Verzeichnis schliessen Eine Datei als „Anhang“ definieren, damit beim Öffnen der Datei im Browser sofort der „Speichern unter“-Dialog angezeigt wird (muss ganz oben in der Datei eingefügt werden!): <?php header("Content-Type: application/octet-stream"); header("Content-Disposition: attachment; filename=\"$save_as_name\""); ?> Die Programmiersprache PHP | 6 Quellen und Links http://www.php-kurs.com [2009-02-25] http://www.selfphp.de [2009-02-25] http://www.buxaprojects.com/phpkurs [2009-02-25] http://www.php-experts.de [2009-02-25] http://www.php.net [2009-02-25] http://www.html-seminar.de [2009-03-31] Version 1.1, 2009-04-07 © 2009 by Reto Da Forno | www.kcdev.ch.vu Die Programmiersprache PHP | 7