PHP und *SQL

PHP: Hypertext Preprocessor (ursprünglich "Personal Home Page Tools") ist eine Skriptsprache mit einer an C bzw. C++ angelehnten Syntax, die hauptsächlich zur Erstellung von dynamischen Webseiten oder Webanwendungen verwendet wird. PHP ist Open-Source-Software.

MySQL ist ein Relationales Datenbankverwaltungssystem der schwedischen Firma MySQL AB. MySQL ist als Open-Source-Software für verschiedene Betriebssysteme verfügbar und bildet die Grundlage für dynamische Webauftritte. Alternativ zu MySQL kann auch PostgreSQL als Datenbanksystem verwendet werden.

PostgreSQL ist ein freies objektrelationales Datenbanksystem (ORDBMS). Es hat eine Entwicklungsgeschichte die bis in die frühen Achtzigerjahre zurückreicht und wird seit 1997 laufend von einer Open-Source-Community weiterentwickelt.

Die Angaben der verwendeten Übungsbeispiele stehen aktualisiert zum Download bereit

Arbeitsumgebung und vorgeschlagene Tools

Bevor man PHP Dateien auf seinem Rechner testen kann, gilt es einige Programme und Tools zu installieren. Theoretisch ist es nötig, den Webserver Apache, die Skriptsprache PHP und den Datenbankserver MySQL jeweils separat in dieser Reihenfolge zu installieren. Will man jedoch nur einen "kleinen" Testserver für die lokale Websiteentwicklung, so kann man auch XAMPP anstatt der drei installieren. XAMPP stellt die drei Produkte unter Microsoft Windows zur Verfügung und ist für Anfänger leichter zu bedienen. Für produktive Server ist es jedoch weniger zu empfehlen, wobei in diesem Fall ohnehin eine Linux-basierte Installation die bessere Alternative ist (sudo apt-get install apache2 php5 mysql-server php5-mysql phpmyadmin für die MySQL Variante, sudo apt-get install apache2 php5 postgresql php5-pgsql pgadmin3 für die PostgreSQL Variante).

Da HTML ein Standard des W3C ist, gibt es viele verschiedene Tools, um Webseiten und Bildinhalte zu erstellen und diese anzuzeigen. Aus technischen und menschlichen Gründen sind Open Source Programme für die Verwendung im Unterricht ideal. Da der Kurs leider auf Microsoft Windows (und nicht auf einer von mir bevorzugten Linuxdistribution) basiert schlage ich folgende Tools vor:

  • Texteditor: Notepad++
    • Einstieg ist einfach, daher geht keine Zeit für das Erlernen verloren; dennoch sehr mächtig und flexibel
    • auch für CSS, Javascript, PHP und viele andere Sprachen geeignet
    • [Strg]+[Alt]+[Shift]+X lädt die aktuell editierte Seite in Firefox
    • Codevervollständigung mit [Strg]+[Space]
    • Wortvervollständigung mit [Strg]+[Shift]+[Space]
    • Unterstützt Zen Coding
  • Webbrowser: Firefox oder Chromium
    • schnell, einfach zu bedienen, relativ sicher und sehr gute Implementierung der W3C Standards
    • schnelle Source-Ansicht per [Strg]+[u]
    • kann den Source einzelner Frames anzeigen
    • Personal Bookmark leiste zum schnellen Öffnen von Seiten
    • Bookmark drag & drop
    • zahllose Erweiterungen, die den HTML Code einer Seite lokal auf Fehler überprüfen und beim Entwickeln helfen
    • IE und andere Browser sollten aber auch zum Testen der Seiten verwendet werden
  • FTP Client: Filezilla
    • kann neben FTP auch sichere Übertragungsprotokolle wie SFTP
    • der beste mir bekannte FTP Client für Microsoft Windows
  • Bildbearbeitungsprogramm: GIMP (GNU Image Manipulation Program)
    • sehr mächtiges Bildbearbeitungsprogramm, dass vor allem fuer die Aufbereitung von Bildern für Websteiten, aber auch für den Druck sehr gut geeignet ist
    • gutes Tool zur Farbauswahl fü HTML und CSS

Alle Programme stehen für mehrere Betriebssysteme (Windows, Linux,...) zur Verfügung. Um einen reibungslosen Ablauf zu gewährleisten, steht während dem Kurs ein Linuxrechner mit dem Apache Webserver und PHP und MySql Unterstützung zur Verfügung. Weiters ist auf dem Rechner ein FTP und ein SSH Server installiert, um beim Upload der Dateien keine Zeit zu verlieren.

Alle Programme stehen für mehrere Betriebssysteme (Windows, Linux,...) zur Verfügung. Um einen reibungslosen Ablauf zu gewährleisten, steht während dem Kurs ein Linuxrechner mit dem Apache Webserver, PHP, MySql und PostgreSQL zur Verfügung. Weiters sind auf dem Rechner ein Samba und ein SSH Server installiert, um beim Upload der Dateien keine Zeit zu verlieren.

Nach der Installation aller Programme empfiehlt es sich den Apache Webserver und das als Modul dazuinstallierte PHP zu testen. Dafür legt man eine Datei test_installation.php mit

<?php phpinfo() ?>
als Inhalt an und kopiert diese in sein htdocs Verzeichnis. Danach kann man in Mozilla Firefox unter http://localhost/test_installation.php versuchen, die Datei zu anzuzeigen. Wird eine Seite mit Informationen über die PHP Installation angezeigt, so hat die Installation geklappt. Eventuell ist es nötig, die Ports 80 (http), 443 (https) und 3306 (mysql) in der Firewall zu deaktivieren, wenn ein Zugriff von Fremdmaschinen gestattet werden soll.

Grundlegendes PHP

Der PHP Code wird in .php Dateien gespeichert. Diese Dateien können exklusiv PHP Code beinhalten oder eine Mischung aus PHP und (X)HTML. Im Fall einer Mischung ist der PHP Code durch spezielle Tags zu kennzeichnen.

<?php
  // this is a comment
  /* this is a long comment
     that spans over multiple rows */
  print "This is PHP Code.<br />";
  echo "This is PHP Code as well.<br />";
?>

Im obigen Beispiel sind echo und print identisch verwendet. Tatsächlich nimmt print aber genau ein Argument und hat einen Rückgabewert während echo zwar keinen Rückgabewert hat, jedoch mehrere Argumente nehmen kann. Um das Beispiel zu testen ist es nötig, bereits einen funktionierenden Webserver mit PHP Unterstützung installiert und gestartet zu haben. Versucht man das Beispiel direkt in einen Webbrowser zu laden, so kennt sich dieser nicht aus, da er PHP nicht interpretieren kann. Dies erledigt ein in den Server installiertes Modul. Wenn der Browser die Seite (durch Zugriff auf den Server) anzeigt, so interpretiert der Server zuerst den PHP Code und schickt an den Browser nur den resultierenden (X)HTML Code (obwohl der Dateiname nach wie vor auf .php endet).

Variable

Eine Variable in PHP ist immer (sowohl beim Zuweisen als auch beim Abrufen) durch ein führendes $-Zeichen gekennzeichnet.

<?php
  // here we assign a value to a variable
  $testVar = 6;
  // and now we retrieve it
  echo $testVar;
?>

Bei der Verwendung von Variablen (sowie allen anderen Namen in PHP) ist besonders auf Groß- und Kleinschreibung zu achten. Will man innerhalb einer Funktion eine ausserhalb definierte Variable verändern, so empfiehlt sich die Verwendung des Schlüsselwortes global.

<?php
  // change a global variable
  global $testVar;
  $testVar = 6;
?>

Analog können Variablen als statisch deklariert werden, was bedeutet, dass sie zwar nicht global sind, jedoch am Ende einer Funktion nicht gelöscht werden. Dazu dient das Schlüsselwort static.

<?php
  // define a static variable
  static $testVar = 0;
  // increment the static variable
  $testVar = $testVar + 1;
?>

Dabei ist es bemerkenswert, dass static $testVar = 0; nur beim ersten Aufruf einer Funktion einen Effekt hat. Nachdem die Variable als statisch deklariert wurde, wird sie nicht bei jedem Aufruf wieder auf 0 gesetzt. Neben diesen beiden Typen gibt es auch sogenannte Superglobals. Diese Variablen stehen automatisch in jedem Skript zur Verfügung. Ein besonders nützliches Beispiel ist

<?php
  echo htmlentities($_SERVER["PHP_SELF"]);
?>

welche es ermöglicht, ein Skript nocheinmal aufzurufen, da $_SERVER["PHP_SELF"] den Namen des aktuellen Skripts (der aktuellen PHP Datei) beinhaltet. htmlentities() ist eine Funktion, die (eventuell gefährliche (X)HTML Tags escaped.

Will man Werte definieren, die sich während des Programablaufes nicht ändern können, so verwendet man Konstanten. Solche Konstanten sind eigentlich keine Variablen, aufgrund gewisser Ähnlichkeiten nehme ich sie aber auch in diesen Abschnitt. Anders als Variablen ist hierbei, dass es sich empfiehlt, lediglich Großschreibung für ihre Namen zu verwenden und dass die Namen nicht mit einem $ Zeichen beginnen. Eine Konstante kann mit

<?php
  define("NAME", value);
  echo NAME; // alternative: constant(strConstName);
?>

definiert und verwendet werden. Nützliche, bereits in PHP vordefinierte Konstanten sind zum Beispiel

__FILE__ // filename incl. path of php script
__LINE__ // line number in the current php script

Bedingte Ausführung und Schleifen

Im folgenden wird nur ganz kurz die Syntax der einzelnen Schleifen dargestellt, auf eine Erklärung wird verzichtet. Falls der Code nicht klar sein sollte, empfehle ich, damit zu experimentieren, da dies die beste Art ist, Programmieren zu lernen.

if (expression) {
  ...
} elseif (expression) {
  ...
} else {
  ...
}
$myVar = condition & value_if_true : value_if_false;
switch ($variable) {
  case label1:
    ...
    [break;]
  case label2:
    ...
    [break;]
  case label3:
    ...
    [break;]
  default:
    ...
}
while (condition) {
  ...
}
do {
  ...
} while (condition);
for ([initialization]; condition; modification) {
  ...
}

Um die Ausführung einer Schleife ganz abzubrechen, verwendet man das break; Statement. Um die aktuelle Iteration abzubrechen und mit der nächsten Iteration weiterzumachen, verwendet man continue;.

Datentypen

PHP versucht, so gut es geht, Datentypen automatisch zu konvertieren. Sollte es jedoch einmal nötig sein, einen Datentyp explizit zu konvertieren, so muss man den Datentyp "casten" (die englische Bezeichnung dafür ist "type casting")

(int), (integer)
(bool), (boolean)
(float), (double), (real)
(string)
(array)
(object)

Funktionen

Eine Funktion in PHP wird mit dem Keyword function deklariert. Funktionsnamen sind in PHP nicht "case-sensitive"! Funktionen sind nützlich, um den Code zu strukturieren, lesbarer zu machen und um ihn besser immer und immer wieder verwenden zu können. Eine Funktion sollte genau eine Aufgabe erfüllen - nicht mehr und nicht weniger und ihr Name sollte diese Aufgabe beschreiben - daher ist es oft sinnvoll, den Namen der Funktion mit einem Verb beginnen zu lassen. Wenn die Funktion mehr als eine Sache macht und man daher Schwierigkeiten hat, die Funktion treffend zu benennen, so ist das ein gutes Anzeichen dafür, dass man die Funktion wohl besser in mehrere Teilfunktionen aufteilen sollte. Die Syntax einer "normalen" Funktion sieht so aus (die optionalen Funktionsargumente sind durch die eckige Klammer angedeutet)

<?php
  function myFunction([$arg1, $arg2, $arg3="defaultvalue", ...]){
    // does stuff
    [return $stuff;]
  }
  // call the function
  myFunction();
?>

Ein Rückgabewert kann mit return erstellt werden, welches die Funktion auch sofort beendet, wenn es aufgerufen wird. Die Verwendung von return ist nicht verpflichtend, aber in den meisten Fällen sinnvoll, denn so kann man das Ergebnis einer Funktion einfach in einer Variable speichern und dadurch später weiterverwenden.

var $result = doStuff($myArg);

Um ein Argument (einen Parameter) an die Funktion nicht als Wert, sondern als Referenz zu übergeben, muss man ein & vor das Argument stellen

<?php
  function myFunction(&$refArg){
    // does stuff
    $refArg = "result";
  }
?>

Einige wichtige Funktionen

function_exists($funName) testet, ob eine Funktion definiert ist
include_once($filename) oft ist es sinnvoll, Funktionen in eine gesonderte Datei auszulagern, um diese von vielen PHP Dateien aus benutzen zu können; include_once($filename) macht es möglich, die Funktionen aus anderen PHP Dateien zu verwenden; wird die gesuchte Datei nicht gefunden, so wird lediglich eine Fehlermeldung ausgegeben
isset($var) gibt TRUE zurück, wenn eine Variable nicht den Wert NULL hat
md5($string) gibt einen md5 Hash der Variable $string zurück
require_once($filename) gleich wie include, jedoch wird wird die Ausführung des Programms sofort beendet, wenn die gesuchte Datei nicht gefunden werden kann
strcmp($str1,$str2) gibt 0 zurück, wenn zwei Strings den gleichen Text haben
strcasecmp($str1,$str2) gibt 0 zurück, wenn zwei Strings den gleichen Text haben, wobei Groß- und Kleinschreibung ignoriert werden
var_dump($var) zeigt den Inhalt einer Variable zum Debuggen an

Eine komplette Funktionsreferenz findet sich auf http://www.php.net (die Deutsche Version ist unter http://www.php.net/manual/de/ erreichbar).

Arrays

In PHP kann man auf zwei Arten von Arrays zugreifen - jene, die "normal" mit einer Zahl (von 0 beginnend) indiziert werden und jene, bei denen jedem Element ein Schlüssel zugeordnet ist. Letztere sind zum Beispiel praktisch, um Konfigurationsdaten zum speichern. Will man den ersten Typ verwenden, so genügt folgende Syntax

<?php
  $myArray[] = "first value";
  $myArray[] = "second value";
?>

Für den zweiten Typ muss man in den eckigen Klammern den Schlüssel (engl. key) angeben. Im Key können auch Leerzeichen und manche Sonderzeichen enthalten sein (von deren Verwendung ich aber abrate).

<?php
  $myArray["key1"] = "first value";
  $myArray["key2"] = "second value";
?>

Will man eine Schleife über alle Werte eines Arrays laufen lassen, so hilft das foreach Konstrukt

<?php
  foreach ($myArray as $key => $value) {
    // do stuff
  }
?>

Eine andere Möglichkeit auf alle Elemente eines Arrays zuzugreifen bieten die Sprachkonstrukte list($var1,$var2,...) und each($array). Ersteres erlaubt es, mehreren Variablen in einem Schritt einen Wert zuzuordnen und letzteres gibt das aktuelle Paar von Key und Value des Arrays zurück bevor es auf den Arrayzeiger auf das nächste Element zeigen lässt. Nach dem letzten Arrayelement gibt each($array) den Wert FALSE zurück. Angewandt sieht das Ganze so aus

<?php
  while(list($key,$value) = each($myArray)) {
    // do stuff
  }
?>

Array Funktionen

array($val1,$val2,...) gibt einen Array mit den in den Klammern angegebenen Werten zurück; es kann auch die $key => $value Schreibweise verwendet werden
asort($array) analog zu sort($array), jedoch bleiben die Schlüssel den Werten zugeordnet; es wird für assoziative Arrays verwendet;
is_array($var) true, wenn $var ein Array ist
ksort($array) analog zu asort($array), jedoch wird nach Schlüsseln anstatt nach Werten sortiert
sizeof($array) gibt die Anzahl der Elemente eines Arrays zurück; ist synonym zu count($array) zu verwenden
sort($array) gibt ein neues Standardarray mit neuen Keys zurück, dessen Werte aufsteigend sortiert sind;

Objekte und Klassen

Objektorientierte Programmierung ist ein versuch, Programmierung mehr an die Denkweise von "normalen" Menschen anzupassen. Wir denken sehr häufig in angreifbaren Objekten, wodurch es logisch erscheint, auch Programmcode in virtuelle Objekte zu verpacken, die Eigenschaften und Methoden haben. Klassen sind am besten als Objektfabriken vorstellbar. Klassen werden in der Regel in eigenen Dateien angelegt, um sie einfacher wiederverwenden zu können. Eine Klasse sieht grob wie folgt aus (per Konvention schreibt man den ersten Buchstaben des Namens einer Klasse groß)

<?php
  class MyClass {
    
    public function __construct([$arg1, ...]) {
      // PHP 5.0 constructor
      $this->var1 = 0;
    }

    public function doStuff([$arg1, ...]){
      // does stuff
    }
    
    private $var1;
    protected $var2; 
    public $var3;
  }
?>

Die erste Funktion im obigen Beispiel ist ein Konstruktor - sie wird beim Erstellen einer neuen Instanz der Klasse aufgerufen. Eine Konstruktorfunktion hat die Syntax __construct([arg1, ...]). Um auf eine Variable oder eine Methode der Klasse innerhalb der Klasse zuzugrefen, so muss this->varname verwendet werden, wobei this für die aktuelle Instanz der Klasse steht. Ein neues Objekt auf Basis der Klasse (eine neue Instanz) wird mit den Schlüsselwort new erstellt

<?php
  $myObject = new MyClass();
?>

Auf öffentliche (public) Funktionen und Variable einer Instanz kann mit dem -> Operator zugegriffen werden

<?php
  $myObject->doStuff();
?>

Klassen können auch durch Unterklassen erweitert werden. Dies ist sinnvoll, wenn verschiedene Klassen viele gemeinsame Eigenschaften und Funktionen haben - zum Beispiel könnte man eine Klasse Car erstellen und den Unterklassen Renault und Volvo die Eigenschaften von Car "vererben"

<?php
  class Car {
    public function __construct(){
      // do stuff
    }
    public static myVar = 0;
  }
  class Renault extends Car {
    public function __construct(){
      parent::__construct();
      // do more stuff
    }
  }
?>

Bereits vorhandene Methoden können einfach überschrieben (overridden) werden. Will man dabei die Funktionalität der Funktion der Elternklasse (auch Superklasse genannt) nicht verlieren, so hilft das parent Schlüsselwort. Will man eine Funktion oder Variable nicht einer Instanz, sondern der Klasse zuordnen, so verwendet man das Schlüsselwort static. Auf eine solche Funktion bzw. Variable kann dann mit dem :: Operator zugegriffen werden (ein direkter Zugriff über eine Instanz ist dann nicht möglich).

Car::myVar = 3;

Kommunikation mit MySQL

PHP hat einige integrierte Funktionen zur Kommunikation mit MySQL. Ihre Benutzung ist relativ einfach und sei im Folgenden durch ein Beispiel mit Kommentaren beschrieben (das Beispiel verwendet die ebenso zum Download angebotene, sehr simple Datenbank store). Es muss ein Datenbankbenutzer mit dem Namen test und dem Passwort 12345 auf dem lokalen MySQL Server existieren, damit das Beispiel funktioniert.
db_login.php.gz, mysql_connect_php.php.gz, store.sql.gz

Nach dem Hinunterladen erstellen wir eine leere Datenbank store und den Datenbankbenutzer. Danach verwenden wir die Datei store.sql, um die Struktur der Datenbank zu erstellen und diese auch mit Daten zu füllen

shell> mysql -u root -p
mysql> CREATE DATABASE store;
mysql> GRANT ALL ON store.* TO 'test'@'localhost' IDENTIFIED BY '12345';
mysql> exit;
shell> mysql -u root -p -D store < store.sql

Dieser Weg ist zwar recht "schön und einfach", jedoch kann er für große Anwendungen sehr problematisch sein, da der erstellte PHP Code nur mit MySQL funktioniert. Will man sich die Option offenhalten, andere Datenbanken mit dem gleichen Code anzusteuern und dadurch unabhänigeren (imho besseren) Code zu schreiben, sollte man das Datenbankmodul von PEAR (PHP Extension and Application Repository) verwenden. Die unterstützten Datenbankverwaltungssysteme sind fbsql, ibase, informix, msql, mssql, mysql, mysqli, oci8, odbc, pgsql, sqlite und sybase. Die Installation des Datenbankteils von PEAR unter Linux geht wie gewohnt sehr einfach

sudo apt-get install php-db

Da dies aber nur ein Einführungskurs ist, bleibt das "Entdecken" von PEAR jedem selbst überlassen, jedoch gibt mysql_connect_pear.php.gz eine zu dem obigen Beispiel korrespondierende, erste Orientierung. Viel Spass & "Happy Hacking"!

Generieren eindeutiger IDs

Manchmal ist es nötig, beim Einfügen von null für Primärschlüsselfelder mit AUTO_INCREMENT, den generierten Wert auszulesen, da man ihn eventuell in eine oder mehrere andere Tabellen eintragen muss. Ein Beispiel dafür ist, beim Einfügen eines neuen Buches in eine Buchtabelle gleichzeitig die zugehörigen Autoren in der Autorentabelle einzutragen. Für dieses Problem gibt es zwei Vorgehensweisen. Die einfachere, welche jedoch nur mit MySQL funktioniert ist

$last_id = mysql_insert_id();

Diese Funktion gibt jene ID zurück, die beim letzten Aufruf von INSERT INTO für eine AUTO_INCREMENT Spalte generiert wurde. Diese ID kann dadurch beim Einfügen in andere Tabellen verwendet werden. Da die alternative Vorgehensweise auf PEAR aufbaut, wird sie hier nicht beschrieben. Dennoch sei darauf hingewiesen, dass es zu Komplikationen kommt, wenn die PEAR Funktion nextId mit Tabellen verwendet wird, die auch aus anderen Quellen (das heisst, ohne die Verwendung von nextId) befüllt werden.

Formulare

Um auf ein Fomularfeld zugreifen zu können stellt PHP die Variablen $_GET["fieldName"] und $_POST["fieldName"] zur Verfügung. fieldName ist dabei jener Text, der im name Attribut eines input Tags erscheint.

<?php
  $strValue = $_GET["fieldName"];
  ...
  <input type="text" name="fieldName" />
?>

Ein recht wichtiger Tip ist, Feldern, die mehrere Werte zurück geben, ein Array als Namen zuzuweisen, da sonst nur der zuletzt ausgewählte Wert gespeichert werden würde

<?php
  ...
  <input type="checkbox" name="arrayName[]" value="val1" />
  ...
  <input type="checkbox" name="arrayName[]" value="val2" />
  ...
  $values = $_GET["arrayName"];
?>

wobei beim Abrufen mit $GET["arrayName"] keine eckigen Klammern zu schreiben sind. Das action Attribut des Formulars zeigt dabei oft auf die aktuelle Datei, was zum Beispiel so aussieht

<form action="<?php echo(htmlentities($_SERVER['PHP_SELF'])); ?>" method="GET">

Sessions

Damit sich ein authentifizierter Benutzer nicht auf jeder Seite, die er ansieht, neu anmelden muss, verwendet man Sessions. Alternativ könnte man auch normale Cookies und URL passing verwenden, wobei Sessions mit den zugehörigen Session Cookies zu bevorzugen sind. Gründe dafür sind, dass sie unter Verwendung einer verschlüsselten Verbindung relativ sicher sind, die meisten Browser Session Cookies akzeptieren und dass Sessions recht einfach zu verwalten sind. Nachdem man einen Benutzer authentifiziert hat, kann man eine Session mit

<?php
  session_start();
?>

beginnen. Im Array $_SESSION[] kann man dann jene Werte speichern, die man in anderen PHP Dateien verwenden will. Das ist natürlich schneller und weniger kompliziert, als sie jedesmal in einer Datenbank abzulegen. Zum Authentifizieren kann man dabei zum Beispiel $_SESSION['user_id'] = $user_id; verwenden. Dieser Variable weist man einen Wert in jener PHP Datei zu, die für die Authentifizierung zuständig ist. Danach kann man in jeder weiteren PHP Datei prüfen, ob sie definiert ist und falls sie das nicht ist, leitet man den Benutzer zur Anmeldeseite weiter. Das Ganze kann dann so aussehen

<?php
  session_start();
  if (!isset($_SESSION['user_id'])){
    header("location:session3_form.php");
  }
?>

Der obige PHP Code muss ganz am Anfang jeder Seite stehen, für die eine Anmeldung nötig ist - noch bevor man irgendeinen Output (zum Beispiel mit echo) an den Browser sendet. Eine Überprüfung des Inhaltes der Variablen ist nicht mehr nötig, die Tatsache, dass sie gesetzt ist, reicht aus (da man sie erst setzt nachdem man überprüft hat, ob der Benutzer eine gültige Kombination aus Benutzernamen und Passwort eingegeben hat). Wenn man eine Session beendet, muss der Benutzer sich neu anmelden, um die gesicherten Seiten zu sehen. Um das zu tun, verwendet man folgenden Code

<?php
  session_start();
  session_destroy();
?>

Templates

Nur als kleiner Ausblick seien Templates bzw. Template Engines erwähnt. Sie dienen dazu, den PHP Programmcode vom Layout (XHTML und CSS) zu trennen. Eine der bekannteren Templateengines ist Smarty. Eine Installation unter Debian GNU/Linux erfolgt durch

sudo apt-get install smarty

Benutzer anderer Betriebssysteme können Smarty über die Projekthomepage, http://www.smarty.net/ beziehen, auf der sich auch gute Dokumentation befindet.

Einführung in MySQL

Einige Hinweise zur Installation von MySQL sowie von phpmyadmin unter Linux finden sich unter linux_administration.php#mysql. Auf dieser Seite wird auch das Erstellen von Backups besprochen. Nachdem man sich mit

shell> mysql [-h localhost] -u root

in den MySQL Server eingeloggt hat, stehen einige Befehle zur Verfügung

describe tblName; gibt Informationen über eine Tabelle (desc ist synonym zu describe)
help; zeigt die vollständige Liste der MySQL Kommandos und eine kurze Erklärung dazu an; help command; gibt Hilfe zu einem spezifischen Kommando;
quit; beendet den Client
source fileName führt MySQL Code aus einer Datei aus
use dbName; wählt die als Argument gegebene Datenbank aus
show databases|tables; zeigt verfügbare Datenbanken bzw. Tabellen an

Die folgenden Statements setzen das Administrationspasswort (SET PASSWORD), erstellen eine Datenbank (CREATE DATABASE; Datenbanknamen dürfen keine Leerzeichen enthalten und sind unter Linux case-sensitive) und einen neuen Benutzer, der alle Rechte an der Datenbank hat (GRANT; ALL ist synonym zu ALL PRIVILEGES)

mysql> SET PASSWORD = PASSWORD('your_password');
mysql> CREATE DATABASE your_database;
mysql> GRANT ALL ON your_database.* TO 'new_user'@'localhost'
    ->    IDENTIFIED BY 'new_user_password';

In der Folge kann man sich nur mehr mit dem richtigen Passwort anmelden und der Aufruf von MySQL ändert sich zu

shell> mysql [-h localhost] -u username -p

Nach dem Verbinden können wir die Datenbank auswählen, mit der wir arbeiten wollen

mysql> USE your_database;

Nach der Auswahl der Datenbank erstellen wir eine Tabelle mit der Syntax

mysql> CREATE TABLE tblName (
    -> column1Name DATATYPE (SIZE) OPTIONS,
    -> column2Name DATATYPE (SIZE) OPTIONS,
    -> ...,
    -> PRIMARY KEY (columnXName));

In der obigen Syntax können die OPTIONS zum Beispiel die Werte NOT NULL (das Feld darf nicht leer sein) oder AUTO_INCREMENT annehmen. Die Anzahl der Spalten ist natürlich beliebig. Ein konkretes Beispiel könnte so aussehen

mysql> CREATE TABLE users (
    -> user_id INT NOT NULL AUTO_INCREMENT,
    -> username VARCHAR (35),
    -> PRIMARY KEY (user_id));

In der folgenden Tabelle sind einige relevante Datentypen aufgelistet (eine vollstaendige Liste mit Erklärungen findet sich auf http://dev.mysql.com/doc/refman/5.0/en/data-types.html)

DATE, TIME, DATETIME Datums- und Zeitangaben; die aktuellen Werte können als Defaultwert übergeben werden (DEFAULT CURRENT_TIME|CURRENT_DATE)
FLOAT[(M,D)] Dezimalzahl mit M Stellen vor und D Stellen nach dem Komma
INT[(M)] Integer (Ganzzahl); die Defaultgrösse beträgt 11
VARCHAR(M) String; es gibt keine Defaultgrösse, also muss immer ein Wert dafür angegeben werden

Das Eingeben von Daten mit dem MySQL Client folgt der Syntax

mysql> INSERT INTO tblName [COLUMNS (col1, col2, ...)] VALUES (val1, val2, ...);

Wird dabei der COLUMNS Teil weggelassen, müssen die Werte in der Reihenfolge der Spalten wie sie in der Tabelle definiert sind eingegeben werden. Als konkretes Beispiel

mysql> INSERT INTO USERS VALUES (NULL,"gerald");

Verändern vorhandener Tabellen

Auch nachdem eine Tabelle bereits Daten enthält kann man sie und ihre Spalten bis zu einem gewissen Grad verändern (ich empfehle jedoch, schon vor Eingabe der Tabellen gründlich zu überlegen, um nachträgliche Änderungen so gut es geht zu vermeiden)

mysql> ALTER TABLE tblName RENAME tblNewName;
mysql> ALTER TABLE tblName MODIFY colName DATATYPE (SIZE) [FIRST|AFTER otherColName];
mysql> ALTER TABLE tblName ADD colName DATATYPE (SIZE) [FIRST|AFTER otherColName];
mysql> ALTER TABLE tblName CHANGE colName colNewName DATATYPE (SIZE) [FIRST|AFTER otherColName];
mysql> ALTER TABLE tblName DROP colName;
mysql> DROP TABLE tblName;

Die wohl beste Referenz über die verschiedenen CREATE und ALTER Befehle findet man in der englischen Dokumentation von Mysql.

Abfragen

Der Sinn von Datenbanken liegt darin, die Daten abrufen zu können - und zwar in genau der Form, die man benötigt. Die dafür verwendeten Abfragen haben die Grundform

mysql> SELECT col1[, col2,...] FROM tblName[,tbl2,...] [WHERE CLAUSE] [ORDER BY CLAUSE];

Um alle Spalten einer Tabelle anzuzeigen (also einfach die ganze Tabelle anzuzeigen) verwendet man

mysql> SELECT * FROM tblName;

Um mit dem Schlüsselwort WHERE das Resultat zu filtern, kann eine beliebige Bedinung eingegeben werden. Wollen wir nur die Daten vom Benutzer "gerald" anzeigen, so verwenden wird

mysql> SELECT * FROM users WHERE username = "gerald";

Die mit WHERE angegebene Bedingung kann auch mit AND, OR, NOT, sowie mit dem Einsatz von Klammern aufgebaut werden. Wenn man Daten von mehreren Tabellen anzeigt, so empfiehlt sich die Schreibweise tblName.colName statt lediglich den Namen der Spalte zu schreiben (dies vermeidet einen Fehler, wenn mehrere Tabellen die gleiche Spalte haben).

Will man die Daten beispielsweise aufsteigend nach der Spalte username sortieren, so verwendet man

mysql> SELECT * FROM users ORDER BY username;

Will man sinnvoll Daten von mehreren Tabellen abfragen, so verwendet man JOIN (implizit oder explizit, je nach Bedarf).

mysql> SELECT tbl1.*, tbl2.colName FROM tbl1, tbl2 WHERE tbl1.id=tbl2.id;

Im obigen Beispiel werden die Tabellen mit der in beiden vorkommenden Spalte id verknüpft. Ohne die Verknüpfung würde die Abfrage das Kartesische Produkt beider Tabellen zur Folge haben. Leichter als im obigen Beispiel geht das ganze mit einem NATURAL JOIN, bei dem die angegebenen Tabellen automatisch über ein gleichnamiges Feld miteinander verknüpft werden

mysql> SELECT * FROM tbl1 NATURAL JOIN tbl2;

Das gleiche geht mittels JOIN ON auch, wenn es keine gleichnameige Spalte gibt

mysql> SELECT * FROM tbl1 JOIN tbl2 ON tbl1.id=tbl2.id;

Will man sich einiges an Tipparbeit ersparen, so kann man Aliases für Tabellennamen mit dem Schlüsselwort AS verwenden

mysql> SELECT * FROM tbl1 AS t1 JOIN tbl2 AS t2 ON t1.id=t2.id;

wobei nach der Definition des Alias nur mehr dieser verwendet werden darf. Will man zwei Tabellen so verknüpfen, dass von der ersten (linken) alle Werte angezeigt werden und von der zweiten nur die Werte, die in der verknüpften Spalte der ersten Tabelle auch existieren, dann verwendet man ein LEFT JOIN

SELECT * FROM tbl1 LEFT JOIN tbl2 ON tbl1.colName = tbl2.colName;

Wildcards

Um bei einer Abfrage Wildcards verwenden zu können gibt es das LIKE Kommando. Das Prozent Zeichen (%) dient als Platzhalter für beliebig viele Zeichen, das Underscore Zeichen (_) ist ein Platzhalter für genau ein Zeichen

mysql> SELECT * FROM tblName WHERE colName LIKE expression;

Um mit dem obigen Beispiel alle Benutzer zu finden, deren Benutzername mit einem "g" beginnt schreibt man

mysql> SELECT * FROM users WHERE username LIKE "g%";

Löschen und Verändern von Daten

Um Daten aus der Datenbank zu löschen, verwendent man das DELETE Kommando. Ohne WHERE werden alle Daten aus der Tabelle gelöscht

mysql> DELETE FROM tblName [WHERE CLAUSE];

Ein schnelles Löschen von allen Daten in einer Tabelle ist mit

mysql> TRUNCATE TABLE tblName;

möglich. Zum Verändern der Daten verwendet man das UPDATE und das SET Kommando. Falls man hier auf WHERE vergisst, so werden alle Werte der Tabelle verändert

mysql> UPDATE tblName SET colName=value [WHERE CLAUSE];

Gruppieren von Informationen

Wie in allen mir bekannten SQL basierten Datenbanken ist es natürlich auch möglich, Daten zu Gruppieren und Funktionen über die gruppierten Daten zu verwenden. Die allgemeine Syntax dafür ist

mysql> SELECT col1, FUNCTION(col2) FROM tblName GROUP BY col1;

Will man zum Beispiel in einer Tabelle mit Rechnungen von Kunden nach den Kundennamen gruppieren und ihre Einkaufssummen (Spalte "value") ausrechnen, so verwendet man

mysql> SELECT name, SUM(value) FROM invoices GROUP BY name;

Häufige Funktionen

AVG(colName) Durchschnitt der Werte
COUNT(colName) Anzahl der Werte
MAX(colName) grösster Wert
MIN(colName) kleinster Wert
SUM(colName) Summe der Werte

Index

Wenn man besonders oft nach Werten in einer Spalte sucht oder die Tabelle nach einer Spalte sortiert, ist es sinnvoll, die Spalte mit einem Index zu versehen

mysql> CREATE [UNIQUE] INDEX indName ON tblName (colName);

Weiss man schon beim erstellen einer Tabelle, dass man einen Index auf eine Spalte anwenden will, so kann man gegen Ende der Tabellendefinition ein

-> ...
-> INDEX|UNIQUE indName (colName));
schreiben.

Datenbankfunktionen

Aufgrund der grossen Anzahl und Komplexität dieser Funktionen sind hier nur einige beispielshaft aufgelistet

CONCAT(str1, str2[,...]) konkateniert Zeichenketten
DATE_ADD(date,INTERVAL expr unit) addiert (DATE_SUB subtrahiert) Datumsangaben; ein Beispiel ist SELECT DATE_ADD('1997-12-31 23:59:59', INTERVAL 1 DAY);
LCASE(str) konvertiert alle Buchstaben zu Kleinbuchstaben
NOW() gibt das aktuelle Datum inklusive der Uhrzeit zurück; CURDATE() und CURTIME() geben analog nur das Datum bzw. nur die Uhrzeit zurück
TRIM(str) schneidet führende und abschliessende unsichtbare Zeichen (Whitespace) ab; alternativ abzuschneidende Zeichen können auch angegeben werden

Hier noch ein Beispiel der Verwendung einer solchen Funktion ("price" und "name" sind Spaltennamen)

mysql> SELECT CONCAT('The price of ',name,' is ', price) FROM products;

Das Ganze geht auch ohne eine Tabelle zu referenzieren

mysql> SELECT NOW();

Für eine komplette Liste mit detaillierten Informationen bietet der MySQL Client wie oben erwähnt eine eigene Hilfefunktion

mysql> HELP functions;

Einführung in PostgreSQL

Einige Hinweise zur Installation und Einrichtung von PostgreSQL unter Linux sowie zum Erstellen von Datenbankbackups finden sich unter linux_administration.php#postgres.

Links

Hier folgt eine (unsortierte) Aufstellung einiger der im Kurs gezeigten Webseiten.

Link kurze Beschreibung
http://dev.mysql.com/doc/ Referenzhandbuch zu MySQL in mehreren Sprachen inklusive Deutsch
http://www.php.net/ Tolle Ressourcen zu PHP (Referenzen zu zahlreichen Bibliotheken etc.)
[Valid XHTML 1.1!]