Zugriff auf eine mysql-Datenbank mittels php


Um ein wenig die Arbeitsweise von Joomla zu beleuchten, habe ich hier einen Grundkurs in Datenbankanbindung mittels php zusammengestellt. Als Datenbank findet dabei mysql, die populäre OpenSource-Datenbank verwendung. Ein wenig Grundkenntnisse in php schaden allerdings nicht, da ich hier nicht auf die Grundlagen von php eingehe, sondern lediglich wie man mittels php-Befehlen auf eine Datenbank zugreifen kann, bzw. diese verwaltet. Um eine Datenbank inklusive Tabelle zu erstellen, kann man entweder php-Befehle nutzen oder sich des Tools phpmyadmin bedienen, welches ein Webfrontend für mysql zur Verfügung stellt und damit die Verwaltung erheblich vereinfacht. Meine Anleitung bezieht sich auf eine lokale Webserver-Umgebung auf einem Debian-System bestehend aus Apache2, mysql5 und php5. Welche Datenbank und welche Tools zur Einrichtung man beim hauseigenen Provider zur Verfügung hat, muß jeder selbst rausfinden. Doch bevor wir loslegen müssen wir erstmal den Zeichensatz von mysql auf den Linux-Standard UTF-8 eichen....

mysql von latin1 auf utf-8 umstellen

Ich weiß nicht, wer auf das schmale Brett gekommen ist einen mysql-Server unter Linux mit dem Windows-ähnlichem Zeichensatz latin1 als Standard-Zeichensatz zu kompilieren und ob sich das in Zukunft mal bessert, aber bei meiner Installation von mysql unter Debian lenny war es leider so. Und dabei ist der Standard-Zeichensatz von Linux und mitterweile auch für Webseiten im Internet UTF-8. Welcher Zeichensatz unter mysql verwendung findet, kann man mittels des Kommandozeilen-Tools mysql herausfinden. Dazu loggt man sich mittels mysql -u root -p auf dem mysql-Server ein und gibt am Eingabe-Prompt den Befehl status ein. Steht in der Ausgabe
Server characterset: latin1
Db characterset: latin1
Client characterset: latin1
Conn. characterset: latin1

ist der Standard-Zeichensatz latin1. Nun muß man verstehen, wie Daten zwischen einer Webseite und mysql ausgetauscht werden. Leider hilft es nicht alleine den Server mit einer Konfigurations-Datei auf default-character-set=utf8 zu stellen, da standardmäßig beim server ein sogenannter "handshake" eingestellt ist, d.h. der Client (in dem Fall die Webseite mit den php-Befehlen) und der mysql-Server handeln per Befehl aus, welcher Zeichensatz verwendung findet. Wird in der Webseite mittels php kein Befehl wie mysql_query("SET NAMES 'utf8'"); gleich nach dem öffnen der Verbindung gesendet, nimmt der Server den einkompilierten Default-Wert und das ist latin1. Schreibt man nun mittels einer Webseite und php-Befehlen utf-8-Datensätze in mysql, werden diese in latin1 konvertiert und beim Abruf wieder zurück konvertiert. Das heißt, daß man auf der Seite der HTML/PHP-Dokumente gar keinen Unterschied merkt und immer alles schön in utf-8 ist. Greift man aber mittels phpmyadmin auf die Datenbank zu, sehen Sonderzeichen (ä ö ü ß) natürlich so aus: ä ö ü ß. Das liegt daran, daß die uns vorliegenden Datensätze ja in latin1 sind, während die phpmyadmin-Umgebung auf utf-8 gestellt ist. Also hat man zwei Möglichkeiten: Entweder muß bei jedem Datenbankaufruf mittels php der
SET NAMES-Befehl gesendet werden oder man stellt den Server per Default auf utf-8 und stellt zusätzlich die Aushandlung des Zeichensatzes ab. Dazu erstellt man in dem Verzeichnis
/etc/mysql/conf.d/ eine Datei mit beliebigem Namen und der Endung .cnf. Ich nenne sie jetzt mal default_character.cnf. In selbige trägt man folgendes ein:

[client]
default-character-set = utf8

[mysqld]
collation_server=utf8_unicode_ci
character_set_server=utf8
skip-character-set-client-handshake

Der Zusatz skip-character-set-client-handshake schaltet die Aushandlung zwischen Clients und Server ab und somit nimmt der Server per Default den angegebenen UTF-8-Zeichensatz.

mysql-Datenbank einrichten mittels phpmyadmin

Nachdem wir nun den korrekten Zeichensatz haben, beginnen wir mit dem Erstellen unserer Datenbank. Dazu bedienen wir uns des Tools phpmyadmin, welches man mittels eines Browsers und der url http://localhost/phpmyadmin/ aufruft. Als Login verwenden wir den Benutzernamen root und das Paßwort, welches man bei der Installation von mysql vergeben hat. Im Feld "Neue Datenbank anlegen"

Joomla-Datenbank anlegen

kann man den Namen der Datenbank vergeben. Als nächsten Schritt kann man eine neue Tabelle erstellen und die Anzahl der Spalten festlegen. Nennen wir unsere Tabelle mal schlicht "liste" und geben wir ihr 3 Spalten.

Tabelle anlegen
Anschließend kann man die einzelnen Spalten benennen und den Datentyp vergeben. Unsere erste Spalte erhält den Namen id und wird ein automatischer Zähler, welcher auch als Primärschlüssel dient. Dazu wählen wir den Datentyp INT, wählen im Dropdown-Menü "auto_increment" und setzen den Punkt für Primärschlüssel. Die zweite Spalte nennen wir hersteller und die Dritte typ. Diese Spalten sind vom Typ VARCHAR, welcher eine begrenzte Anzahl von Zeichen zuläßt (siehe Länge). In unserem Fall 30 Zeichen.
Spalten benennen

Nach einem Klick auf Speichern ist das Gerüst unserer Datenbank fertig eingerichtet und bereit zur Verwendung. Nun geht es an die Verknüpfung mittels php.

Datensätze eintragen mittels php - einfache Form

Zuerst erstellen wir eine eigene php-Datei die die Verbindungsdaten enthält. Diese Datei wird später mittels include in unser Eingabeformular eingebunden. Es ist aus zwei Gründen sinnvoll die Verbindungsdaten in eine eigene Datei auszulagern. Einmal kann man sie dann für jede Aufgabe, ob eintragen, löschen oder abrufen immer wieder verwenden und zum Anderen kann man sie in ein eigenes Verzeichnis verschieben, daß man mittels einer htaccess-Datei und deny from all (siehe vorheriges Kapitel) gegen unbefugten Zugriff schützen kann. Immerhin steht in der Datei das Paßwort für die Datenbank im Klartext drin. Die Datei speichern wir unter dem Namen zugriff.inc.php und hat folgenden Inhalt:

<?php
//Zugangsdaten
$user="root"; //Benutzername für den MySQL-Zugang
$password="passwort"; //Passwort
$host="localhost"; //Name oder IP-Adresse des Rechners mit MySQL
$dbname="autos"; //Datenbankname

//Verbindung aufbauen
mysql_connect($host, $user, $password) or die("Verbindung fehlgeschlagen");
mysql_select_db($dbname) or die("Die Datenbank existiert nicht.");
?>

Die Variablen sind natürlich selbsterkärend, bzw. steht die Erklärung als Kommentar dahinter. Mittels mysql_connect wird versucht eine Verbindung zur Datenbank aufzubauen. Sollte dies fehlschlagen, weil der Benutzername oder das Passwort falsch sind, wird mittels die die Fehlermeldung "Verbindung fehlgeschlagen" ausgegeben. Mit mysql_select_db wird versucht die Datenbank zu öffnen. Schlägt auch das fehl, weil die Datenbank nicht gefunden wurde, wird ebenfalls eine Meldung "Die Datenbank existiert nicht" ausgegeben.

Nun zu unserem Eingabe-Formular. Für die Eingabe der Daten benutzen wir das form-Tag, also simplen HTML-Code. Mittels dieses Tags kann man eigene Eingabeformulare für Datenbanken entwerfen. Unsere Datei hat folgenden Inhalt:

<html>
<head>
<title>mysql Datenbankanbindung mittels php</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>

<body>

<h3>Fahrzeug-Liste</h3>

<form action="index.php" method="post">
<table>
  <tr>
    <td align="right">
        <p>Hersteller <input name="hersteller" type="text" size="30" maxlength="30"></p>
        <p>Typ <input name="typ" type="text" size="30" maxlength="30"></p>
        <p><input type="submit" name="aufnehmen" value="Aufnehmen"></p>
    </td>
  </tr>
</table>
</form>

<?php
if(isset($_POST["aufnehmen"]))
{
include("zugriff.inc.php");

$hersteller=$_POST["hersteller"];
$typ=$_POST["typ"];

$sql="INSERT INTO liste(hersteller, typ) VALUES('$hersteller', '$typ')";

mysql_query($sql);
mysql_close();
}
?>

</body>
</html>

Die Datei speichern wir unter dem Namen index.php ab. Unser Formular geht von <form> bis </form> und besteht aus 3 Formularelementen. Zwei Texteingabezeilen (input type="text") mit einer Länge und maximalen Eingabe von 30 Zeichen und einem sogenannten submit-Button, welcher die Formulardaten abschickt. Sehr wichtig ist die Bezeichnung name für alle Elemente, denn das was man in die Textfelder eingibt, wird nach dem drücken auf den submit-Button unter der Namensangabe als Variablenwert gespeichert und ist so mittels php abrufbar. Sogar der submit-Button bekommt nach dem drücken einen Variablen-Wert. Es ist die value-Angabe. Die Option action legt das Folge-Dokument fest, welches beim Klick auf den submit-Button aufgerufen wird. Diesem Dokument werden mit dem Aufruf die generierten Variablen übergeben. In unserem Fall ist es dasselbe Dokument, damit natürlich der php-Code im unteren Teil ausgeführt wird. Die Option method legt die Methode der Variablenübergabe fest. Es gibt post und get. Der Unterschied besteht darin, daß bei get alle Variablen an die url angehängt werden, was bei vielen Variablen zu einer sehr langen url führt. Der Vorteil ist, daß diese url und somit die Variablen gespeichert werden kann. Der Nachteil ist, daß urls eine begrenzte Länge haben, also funktioniert bei zuviel Variablen die url nicht mehr. Das ist auch schon der ganze HTML-Code der hier noch für eine bessere Formatierung in eine Tabelle gepackt wurde, welche sich innerhalb unseres Formulars befindet. Da wir in unserem Beispiel lediglich eine Tabellenzelle haben, könnte sich das Formular auch innerhalb der Tabelle befinden. Wo ist der Unterschied? Befindet sich ein Formular innerhalb einer Tabelle, muß es innerhalb einer Tabellen-Zelle (innerhalb eines <td>-Elements) abgeschlossen sein. Bei einer Tabelle mit mehreren Zellen entstehen dadurch viele unabhängige Formulare. Möchte man lediglich ein formatiertes Formular haben, muß die Tabelle wie hier innerhalb des Formulars sein!

Nach dem HTML-Code folgt der php-Code. Eingeleitet wird php mittels <?php und beendet mit ?>. Alles dazwischen wird als php-Befehle interpretiert. Die allererste Zeile enthält die if-Abfrage isset($_GET["aufnehmen"]), welche verhindert daß die php-Befehle sofort beim Seitenaufbau ausgeführt werden und somit schon Eintragungen in die Datenbank vorgenommen werden (welche natürlich nur leere Felder enthalten würden, da ja noch keine Variablen generiert wurden). Wie schon erwähnt hat unser submit-Button ungedrückt noch keinen Variablen-Wert und bekommt nach dem drücken den Wert von value. Mit isset (is set=ist gesetzt) wird abgefragt, ob die Variable einen Wert enthält, ergo ob der Button gedrückt wurde. Folglich wird der folgende php-Code nur ausgeführt, wenn der Button gedrückt wurde. Mittels include werden die Verbindungsdaten in das Dokument eingebunden. Danach erfolgt die Übergabe der html-Variablen in php-Variablen mittels $_POST. Anschließend wird der Einfügebefehl für die Datenbank in der Variablen $sql abgelegt. Mit
INSERT INTO tabelle(erste spalte,nächste spalte,...) VALUES ('$Variable','$Variable','...') werden die Variablen-Werte den Spalten übergeben. Dabei ist zu beachten, daß STRING-Werte in einfache Anführungsstriche einzuschließen sind. mysql_query($sql); schickt den Befehl an die Datenbank und mit mysql_close(); wird sie wieder geschlossen. Damit ist unser simples Eingabeformular fertig und ein Aufruf wie http://localhost/index.php startet das Dokument. Allerdings hat unser Eingabeformular so wie es jetzt ist noch zwei Schwächen: es werden keine Werte überprüft, also ob überhaupt etwas in die Felder geschrieben wurde und obwohl das Dokument nach dem Abschicken der Daten mittels des submit-Buttons leer erscheint, bewirkt ein manuelles Neuladen der Seite mittels F5 oder des Aktualisieren-Buttons daß die vorher eingegeben Daten erneut verschickt werden(der Browser gibt einen entsprechenden Hinweis aus: "Um diese Seite anzuzeigen, müssen die von Iceweasel gesendeten Daten erneut gesendet werden, wodurch alle zuvor durchgeführten Aktionen wiederholt werden"). Das Verhalten des Browsers ist logisch. Da die Seite mit einer Variablen-Übergabe aufgebaut wurde, muß der Browser zum Neuladen diesen Vorgang wiederholen. Unser submit-Button hat also seinen Wert noch und somit wird die if-Schleife erneut ausgeführt und ein weiterer Eintrag in der Datenbank getätigt. Obwohl es zwar unwahrscheinlich ist, daß jemand die Seite aktualisiert, finde ich es doch besser auf Nummer sicher zu gehen und dieses Verhalten zu unterbinden.

Datensätze eintragen mittels php - erweiterte Form (mit Sicherheitsabfragen)

Um wirklich sicher zu sein, daß nur eingegebene Werte in die Datenbank übernommen werden, müssen wir also unsere Variablen wieder auf Null zurücksetzen. Leider kann man dies nur erreichen, wenn man die Seite neu aufruft, denn selbst ein unset($_POST); nimmt zwar den Variablen ihren Wert, aber bei einer Aktualisierung verfährt der Browser natürlich trotzdem wie zuvor und übergibt sie erneut. Die Lösung dafür liegt in einer weiteren if-Abfrage und besagtem Neuaufruf der Seite im Header der Datei. Also erweitern wir unseren Code um besagte Kopfzeilen und fügen auch noch gleich eine Abfrage ein, ob überhaupt eine Eingabe getätigt wurde. Unser Code sieht dann wie folgt aus:

<?php
if(isset($_POST["aufnehmen"]))
{
header("refresh: 3; url=http://localhost/index.php");
}
?>

<html>
<head>
<title>mysql Datenbankanbindung mittels php</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>

<body>

<h3>Fahrzeug-Liste</h3>

<form action="index.php" method="post">
<table>
  <tr>
    <td align="right">
        <p>Hersteller <input name="hersteller" type="text" size="30" maxlength="30"></p>
        <p>Typ <input name="typ" type="text" size="30" maxlength="30"></p>
        <p><input type="submit" name="aufnehmen" value="Aufnehmen"></p>
    </td>
  </tr>
</table>
</form>

<?php
if(isset($_POST["aufnehmen"]))
{
include("zugriff.inc.php");

$hersteller=$_POST["hersteller"];
$typ=$_POST["typ"];

if(empty($hersteller) || empty($typ))
{
echo "Bitte alle Spalten ausfüllen!<br>";
echo "Seite wird in 3 Sekunden neu geladen...<br>";
}
else
{
$sql="INSERT INTO liste(hersteller, typ) VALUES('$hersteller', '$typ')";
mysql_query($sql);
echo "Daten wurden aufgenommen.<br>";
echo "Seite wird in 3 Sekunden neu geladen...<br>";
}
mysql_close();
}
?>

</body>
</html>

Wie man sieht, haben wir im Kopf diesselbe Abfrage wie sie schon im unteren Teil Verwendung fand, nämlich ob unser submit-Button gedrückt wurde. Der Befehl header("refresh: 3; url=http://localhost/index.php"); bewirkt, daß nach 3 Sekunden (refresh: 3) die unter url angebene Adresse aufgerufen wird. Da die Adresse das eigene Dokument ist, wird die Seite einfach komplett neu geladen. Trotz unserem "Reload" der Seite wird der Rest der Seite ausgeführt. Somit kann man noch auf die Datenübergabe hinweisen und daß die Page nach 3 Sekunden neu geladen wird. Oder man ändert die Kopfzeile in header("Location: http://localhost/index.php"); und lädt die Seite ohne Verzögerung neu.
Die if-Abfrage empty($variable) bewirkt dasselbe wie isset nur umgekehrt. isset liefert True wenn die Variable gesetzt wurde und empty wenn nicht. Somit werden nur Einträge in die Datenbank geschrieben, wenn auch etwas in die Eingabe-Felder geschrieben wurde.

Inhalt der Datenbank anzeigen lassen

Nun da wir unsere Datenbank mit Werten gefüllt haben, wollen wir diese auch wieder anzeigen lassen. Dabei hilft uns folgendes Listing:

<html>
<head>
<title>mysql Datenbankanbindung mittels php</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>

<body>

<h3>Inhalt der Datenbank &quot;autos&quot;</h3>

<?php
include("zugriff.inc.php");

$anzeige = mysql_query("SELECT * FROM liste");
echo "<table border=\"1\" cellpadding=\"10\">\n";
while($row = mysql_fetch_object($anzeige))
{
echo "<tr><td>", $row->ID, "</td>";
echo "<td>", $row->hersteller, "</td>";
echo "<td>", $row->typ, "</td></tr>\n";
}
echo "</table>";
mysql_close();
?>

</body>
</html>

Den Anfang macht natürlich wie bei jedem Datenbankzugriff unsere Verbindungsdaten die wir mittels include einbinden. Anschließend wird die Abfrage generiert und in die Variable $anzeige geschrieben. Dabei bedeutet SELECT * FROM liste soviel wie "wähle alles (der Stern als Platzhalter für alles) aus der Tabelle liste". Anschließend wird mittels echo eine Tabelle generiert und durch die while-Schleife Spalte für Spalte mit den Datensätzen aus der Datenbank gefüllt. Das Kernelement der while-Schleife bildet hier mysql_fetch_object, welches aus unserer Datenbankabfrage die einzelnen Objekte (in dem Fall die einzelnen Datensätze) ausschneiden kann. Mittels $row->spalte kann man die einzelnen Spalten übergeben. Interessant ist hier der Zeilenvorschub \n, welcher zwar keinen Zeilenvorschub in der Ausgabe des Webdocuments bewirkt (das macht natürlich nur <br>), aber einen Zeilenvorschub im Code bewirkt. Dadurch wird der Code bei einer späteren Einsicht mittels des Webbrowsers ein wenig übersichtlicher, da nicht alles in eine Zeile gequetscht wird.

Inhalt der Datenbank anzeigen - Ausgabe Seitenweise

Jetzt wirds ein wenig komplizierter, denn eine große Datenbank mit vielen Einträgen Seitenweise ausgeben und als zusätzliche Schwierigkeit in einem Dokument, dafür braucht man schon ein paar mehr if-Abfragen. Fangen wir mit dem kompletten Listing an:

<?php

include("zugriff.inc.php");

// Anzahl der Einträge ermitteln für die Berechnung der Seiten
$sqlbefehl = "SELECT COUNT(*) AS anzahl FROM liste";
$ergebnis_gesamt = mysql_query($sqlbefehl);
$array = mysql_fetch_array($ergebnis_gesamt);
$gesamtanzahl = $array["anzahl"];

// Seiten zuweisen
if(empty($_GET["seite"]))
{
$seite=1;
}
else {
$seite=$_GET["seite"];
}

if(empty($_GET["zeilenzahl"]))
{
$zeilenzahl=25;
}
else {
$zeilenzahl=$_GET["zeilenzahl"];
}

// Seitenanzahl berechnen
$seitenanzahl=ceil($gesamtanzahl/$zeilenzahl);

if($seite>$seitenanzahl)
{
$seite=$seitenanzahl;
}

$startpos=($seite-1)*$zeilenzahl;
if($startpos<0)
$startpos=0;
$endpos=$startpos+$zeilenzahl;

$alphabet=$_GET["alphabet"];

// Sortierung nach ID - Abfrage-Befehl generieren
if($alphabet=="on")
{
$abfrage = mysql_query("SELECT * FROM liste ORDER BY id LIMIT $startpos,$zeilenzahl");
}
else{
$abfrage = mysql_query("SELECT * FROM liste LIMIT $startpos,$zeilenzahl");
}

$currentcount = mysql_num_rows($abfrage);

?>

<html>
<head>
<title>mysql Datenbankanbindung mittels php</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>

<body>
<h3>Inhalt der Datenbank Seitenweise</h3>

<table width="100%" border="0" cellpadding="0" cellspacing="0">
  <tr>
    <td>

<?php

// Gesamtanzahl der Einträge ausgeben
echo "Gesamtanzahl der Einträge: ",$gesamtanzahl,"<br>";

// Drop-Down-Menü für die Einstellung der Zeilen pro Seite
echo "<form action=\"index.php\" method=\"get\">";
echo "<input type=\"hidden\" name=\"alphabet\" value=\"$alphabet\">";
echo "<input type=\"hidden\" name=\"seite\" value=\"$seite\">";
echo "Gewählte Einstellung: ",$zeilenzahl," Einträge pro Seite.
<select size=\"1\" name=\"zeilenzahl\" onchange=\"this.form.submit();\">
<option>wählen</option>
<option>100</option>
<option>50</option>
<option>25</option>
<option>10</option>
</select>";
echo "</form>\n";

// Checkbox für die Sortierung nach Alphabet
echo "<form action=\"index.php\" method=\"get\">";
echo "<input type=\"hidden\" name=\"zeilenzahl\" value=\"$zeilenzahl\">";
echo "<input type=\"hidden\" name=\"seite\" value=\"$seite\">";
echo "Sortiert nach Alphabet
<input type=\"checkbox\" name=\"alphabet\" value=\"on\"";
if($alphabet=="on")
{
echo " checked=\"checked\"";
}
echo " onchange=\"this.form.submit();\">";
echo "</form>\n";

// Anzeige der momentanen Einträge auf der Seite und Gesamtanzahl der Seiten
echo "Eintrag ";
if($currentcount==0)
{
echo "0";
}
else {
echo ($startpos+1);
}
echo " bis ",($startpos+$currentcount)," von ",$seitenanzahl," Seiten";

// Seitenweiterschaltung
echo "<form action=\"index.php\" method=\"get\">";
echo "<input type=\"hidden\" name=\"zeilenzahl\" value=\"$zeilenzahl\">";
echo "<input type=\"hidden\" name=\"alphabet\" value=\"$alphabet\">";

if($seitenanzahl<2)
{
echo "&nbsp;";
}
else {
if($seite==1)
{
echo "Seite ",$seite,"<input type=\"submit\" name=\"seite\" value=\"",($seite+1),"\">";
}
else if($seite==$seitenanzahl)
{
echo "<input type=\"submit\" name=\"seite\" value=\"",($seite-1),"\"> Seite ",$seite;
}
else {
echo "<input type=\"submit\" name=\"seite\" value=\"",($seite-1),"\">";
echo " Seite ",$seite," ";
echo "<input type=\"submit\" name=\"seite\" value=\"",($seite+1),"\">";
}
}

echo "</form>\n\n";

// Auslesen der Datenbank und Ausgabe in einer Tabelle
echo "<table border=\"1\" cellpadding=\"10\">\n";
echo "<tr><th>ID</th><th>Hersteller</th><th>Typ</th></tr>";
while($row = mysql_fetch_object($abfrage))
{
echo "<tr>";
if(empty($row->ID))
{
echo "<td>&nbsp;</td>";
}
else {
echo "<td>", $row->ID, "</td>";
}

if(empty($row->hersteller))
{
echo "<td>&nbsp;</td>";
}
else {
echo "<td>", $row->hersteller, "</td>";
}

if(empty($row->typ))
{
echo "<td>&nbsp;</td>";
}
else {
echo "<td>", $row->typ, "</td>";
}
echo "</tr>\n";
}
echo "</table>\n";

mysql_close();

?>

    </td>
  </tr>
</table>

</body>
</html>

Diesmal öffnen wir gleich im Kopf unserer Seite mit der include-Anweisung die Datenbank. Mit dem sql-Befehl SELECT COUNT(*) AS anzahl FROM tabelle erreichen wir eine Zählung aller Einträge in der Datenbank. Diese Zählung müssen wir in ein Array schreiben und können die Zahl anschließend der Variablen $gesamtanzahl übergeben. Anschließend wir die momentane Seite definiert. Im Falle, daß das Dokument das erste Mal geöffnet wurde, ist die Seitenvariable noch nicht definiert und bekommt den Standardwert $seite=1 zugewiesen. Die Seitenvariable wird später durch die Seitenweiterschaltung im Wert erhöht oder erniedrigt. Nach diesem Prinzip -mittels if-Abfragen- werden allen für die Berechnung der Seiten unbedingt benötigten Variablen Standardwerte zugewiesen. Als Nächstes erfolgt die Zuweisung der Einträge pro Seite in der Variablen $zeilenzahl. Nun haben wir beide Werte um die Anzahl der benötigten Seiten zu berechnen. Dazu teilen wir die Anzahl der Einträge pro Seite durch die Anzahl der Einträge in der Datenbank und runden das Ergebnis mittels ceil auf. ceil rundet bei einem Kommawert auf die nächst höhere Ganzzahl auf und ist daher wie geschaffen für die Ermittlung unserer benötigten Seiten. Die folgende if-Abfrage dient nur zur Sicherheit um sicherzustellen, daß der Wert der Seite in einem gültigem Bereich liegt. Bei einer Umschaltung der Einträge pro Seite soll die momentan aktuelle Seite beibehalten werden, jedoch kann es bei der Umschaltung von einem niedrigen auf einen hohen Wert sein, daß die betreffende Seite gar nicht existiert. In dem Fall wird durch die if-Abfrage auf die letzte Seite gewechselt. Mit der vorher festgelegten Seite können wir den Startwert $startpos unserer Einträge pro Seite ermitteln. Das geht ganz einfach indem wir die Seite um -1 herabsetzen und mit der Anzahl der Einträge pro Seite multiplizieren. Anschließend berechnen wir noch den Endwert $endpos für die LIMIT Anweisung in der Datenbankabfrage. Für eine korrekte Berechnung der tatsächlichen Einträge pro Seite (auf der letzten Seite können es ja weniger Einträge sein) ist diese Angabe allerdings nicht zu gebrauchen. Diesen Wert berechnen wir mittels mysql_num_rows, welcher die aus der Datenbank empfangenen Zeilen wiedergibt und in der Variablen $currentcount speichert. Dadurch ist es möglich im Kopf unseres Dokuments eine exakte Angabe "Einträge von ... bis ..." zu machen. Natürlich müssen wir vorher unsere Daten aus der Datenbank abfragen um einen gültigen Wert für $currentcount zu erhalten. Dafür müssen wir aber zuerst noch unsere $alphabet-Variable holen, welche den Wert einer checkbox enthält, mit der wir die Ausgabe der Datenbank nach der ID sortieren können. Ohne Sortierung werden die Einträge in der Reihenfolge ausgegeben wie sie in die Datenbank geschrieben wurden. Mit der alphabet-if-Abfrage werden die Abfragen einmal nach alphabetischer Sortierung generiert und einmal ohne. Dafür fragen wir die Variable für $alphabet erneut ab und erstellen die Abfrage entweder mit ORDER BY spalte oder ohne. Die Limit-Anweisung fordert nur angegebene Einträge aus der Datenbank an, dabei setzt sich die Anweisung wie folgt zusammen:
LIMIT startpunkt,Anzahl Einträge. Damit sind unsere Variablen-Deklarationen und Berechnungen fertig und es folgt der HTML-Code.

Der HTML-Code auf unserer Seite ist recht unspektakulär. Wir spannen lediglich eine komplette Tabelle mit einer einzigen Zelle um unsere ganzen Elemente. Der Inhalt der Datenbank wird in eine eigene Tabelle innerhalb dieser umschließenden Tabelle geschrieben. Alle weiteren HTML-Elemente werden gleich mit echo-Anweisungen im folgenden php-Code generiert. Man hätte zwar auch den php-Code ständig unterbrechen und neubeginnen können, ob dadurch der Code allerdings übersichtlicher wird ist dem jeweils eigenem Geschmack vorbehalten. Der Freiheit in der Gestaltung sind hier keine Grenzen gesetzt.

Im nun folgenden php-Code können wir zu informativen Zwecken die im Kopf berechneten Variablen ausgeben lassen. Wir beginnen gleich mal mit der Gesamtanzahl der Einträge in unserer Datenbank. Danach folgt das Drop-Down-Menü mit dem wir unsere Einträge pro Seite selbst einstellen können. Dieses Element steckt in einem eigenem Formular, welches unabhängig von den Formularen für die Checkbox oder die Seitenweiterschaltung ist. Da jedes Formular nur die Variablen seiner eigenen Elemente abschickt, kann man die sonstigen benötigten Variablen mittels sogenannter Hidden-Elemente dem Seitenaufruf des Formulars mitgeben. Damit beim Wechsel der Einträge pro Seite die aktuelle Seite und die Sortierung beibehalten wird, müssen wir die Variablen $seite und $alphabet mitschicken. Da unser Drop-Down-Menü nach einer Auswahl und neuladen der Seite immer auf den allerersten Eintrag springt, geben wir einen Hinweis aus für die gewählte Anzahl. Auch ist das der Grund dafür, daß der allererste Eintrag keine Zahl, sondern das Wort wählen ist. Das Wort "wählen" kann zwar ausgewählt werden, wegen der onchange-Anweisung hat es aber keinerlei Auswirkung, da besagte Form eben nur bei einer Änderung ausgeführt wird ("wählen" erneut auszuwählen ist keine Änderung). Ebenfalls ist das der Grund, warum wir das Drop-Down-Menü in ein eigenes Formular packen müssen. Würde es im Formular der Checkbox stehen, würde bei einer Änderung der Checkbox die momentan gewählte Einstellung als Variable übergeben, was dann das Wort "wählen" wäre und damit ein invalider Wert für die Anzahl der Einträge pro Seite. Dies würde zu einem massivem Fehler in der Webseite führen. Interessant ist, daß unser Drop-Down-Menü von Haus aus kein Ausführen des Formulars und damit Neuladen der Seite bei der Änderung eines Wertes initiiert. Dafür müssen wir die Action onchange und einen Javascript Befehl namens this.form.submit() bemühen.
Nach der Zeilenauswahl folgt die Checkbox für die Sortierung. Damit bei der Umschaltung der Sortierung die momentan gewählte Seite mit der momentan gewählten Zeilenzahl erhalten bleibt, müssen wir wieder sämtliche dafür notwendigen Variablen ($zeilenzahl und $seite) beim Reload der Page mittels
input type=hidden übergeben. Nach den Hidden-Elementen erfolgt die if-Abfrage, ob die Checkbox gewählt wurde, denn ein Reload der Page führt grundsätzlich zum abwählen der Checkbox. Sie soll aber den letzten Zustand erhalten, bzw. wieder herstellen. Da der letzte Zustand als Variable (on falls ausgewählt, kein Wert falls abgewählt) übergeben wurde, fragen wir diesen ab und fügen falls erforderlich ein checked="checked" ein, was einen Haken in die Box setzt. Nach einer weiteren kleinen Informationszeile für die momentan angezeigten Einträge, geht es zur Seitenweiterschaltung die wir mittels Buttons realisieren. Hier müssen alle 3 Variablen $zeilenzahl, $alphabet und $seite dem Formular mitgegeben werden, damit die Seitenweiterschaltung korrekt funktioniert. Dabei werden $zeilenzahl und $alphabet mittels der Hidden-Elemente übergeben, während die Seitenvariable direkt durch die Submit-Buttons übergeben wird. Dummerweise werden dadurch die Submit-Buttons mit der nächst höheren oder niedrigeren Seitenzahl beschriftet. Möchte man dies vermeiden, kann man eine eigene Variable definieren und im Kopf eine Abfrage einfügen, welche die Seitenzahl erhöht oder erniedrigt. Eine andere Lösung wäre ein einfacher Link ganz ohne Formular. In dem Fall müßten die benötigten Variablen an den Link angehängt werden, da bei fehlendem Formular natürlich kein Hidden-Element verwendet werden kann. Die Link-Adresse würde dann in der Adresszeile so aussehen:
<a href="index.php?zeilenzahl=25&alphabet=on&seite=3">
und als echo-Anweisung in unserer Datei:
echo "<a href=\"index.php?zeilenzahl=",$zeilenzahl,"&alphabet=",$alphabet,"&seite=",$seite+1\">";
Es folgen die Abfragen für die Generierung der Buttons. Ist die Seitenanzahl weniger als 2, also folglich nur eine einzige Seite, benötigt man ja keine Seitenweiterschaltung. In dem Fall wird lediglich ein Leerzeichen anstelle der Buttons generiert. Hat man doch mehr Seiten, kommt es darauf an, wo man sich befindet. Auf Seite 1 benötigt man natürlich nur einen Button nach rechts um die Seitenzahl zu erhöhen und auf der letzten Seite logischerweise nur einen nach Links. Für alle anderen Seiten werden beide Buttons generiert. Zwischen den Buttons wird die momentan gerade aktuelle Seite ausgegeben damit man weiß, wo man sich befindet.

Mittels der while-Schleife werden die Einträge Zeile für Zeile ausgelesen. Falls nicht in allen Zellen der Datenbank Werte stehen, wird durch die if-Abfrage stattdessen ein &nbsp; (nonbreakablespace=Leerzeichen) eingefügt um die Optik der Tabelle nicht zu gefährden. Ein Rahmen wird nur gezogen, wenn die Zelle in der Tabelle auch einen Inhalt aufweist. Damit ist unsere Seitenweise Ausgabe einer Datenbank fertig.

Zur Ergänzung für die Datenbankausgabe noch ein paar weitere Abfrage-Beispiele:

$sql = "SELECT COUNT(*) AS anzahl FROM liste";
$ergebnis = mysql_query($sql);
$array = mysql_fetch_array($ergebnis);
$anzahl = $array["anzahl"];
echo "Anzahl der Einträge: ", $anzahl;
Mit Hilfe von COUNT kann man die Gesamtanzahl der Einträge in einer Tabelle ausgeben. Möchte man die Gesamtanzahl einzelner Einträge hilft
$sql = "SELECT hersteller, COUNT(*) AS anzahl FROM liste GROUP BY hersteller ORDER BY anzahl DESC";
$ergebnis = mysql_query($sql);
while($array = mysql_fetch_array($ergebnis))
{
$anzahl = $array["anzahl"];
$hersteller = $array["hersteller"];
echo $hersteller, " ", $anzahl;
}
Wie man sieht, erweitert sich der Abfrage-Befehl um die Komponenten GROUP BY und ORDER BY, wobei Ersteres die Spalte auswählt, die zusammengefaßt werden soll. In dem Fall unsere Spalte "hersteller", also werden sämtliche gleichen Hersteller zusammengezählt. Die Komponente ORDER BY gibt an, nach welcher Ausgabe sortiert werden soll. In unserem Fall nach der Anzahl in absteigender (DESC) Reihenfolge, also tauchen die am häufigsten vorkommenden Hersteller in der Liste ganz oben auf, gefolgt von den weniger häufigeren. Mittels der while-Schleife gibt man die zusammengezählten Einträge aus.
Und noch mehr mögliche Abfragen:
// Nur einzelne Spalten einer Tabelle auswählen
$sql = "SELECT hersteller, typ FROM liste";

// Mit LIMIT die Ausgabe beschränken
$sql = "SELECT hersteller, typ FROM liste LIMIT 0,10";

// Nur Datensätze ausgeben, die einer bestimmten Bedingung entsprechen
$sql = "SELECT hersteller, typ FROM liste WHERE hersteller='ford'";

// Mit einem Text-Eingabe-Feld (name="suchwort")hat man eine Suche
$begriff = $_GET["suchwort"];
$sql = "SELECT hersteller, typ FROM liste WHERE hersteller='$begriff' OR typ='$begriff'";

Standardmäßig verwendet mysql die LIMIT-Anweisung 0,30, d.h. es werden nur die ersten 30 Zeilen ausgegeben.

Damit haben wir die Grundfunktionen: Daten in die Datenbank eintragen und wieder auslesen. Am Anfang des Beitrags haben wir die Datenbank mit phpmyadmin erstellt. Der Vollständigkeit halber kommen jetzt noch die entsprechenden php-Befehle zum Erstellen oder Löschen der Datenbank oder einer Tabelle und zum Ändern von Datensätzen.

Datenbank oder Tabelle anlegen

<?php
include("zugriff.inc.php");

$sql = "CREATE TABLE liste (id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, hersteller VARCHAR(30) NOT NULL, typ VARCHAR(30) NOT NULL) ENGINE = MYISAM";
mysql_query($sql);
echo mysql_error();
mysql_close();
?>
Der Befehl zum Anlegen einer Tabelle lautet
CREATE TABLE tabellenname (Spaltename1 Datentyp Sonstiges, Spaltenname2 Datentyp Sonstiges, ...) ENGINE=verwendete Engine;
Eine bereits existierende Tabelle wird dabei nicht überschrieben, sondern führt zu einer Fehlermeldung, welche man sich mit echo mysql_error(); ausgeben lassen kann. Möchte man die Fehlermeldung unterdrücken läßt man entweder die echo Anweisung weg oder fügt einen Zusatz an den Befehl an: CREATE TABLE IF NOT EXISTS.
<?php
include("zugriff.inc.php");

$sql = "CREATE DATABASE autos";
mysql_query($sql);
echo mysql_error();
mysql_close();
?>

Der Befehl zum Anlegen einer Datenbank ist simpel: CREATE DATABASE Datenbankname. Genau wie bei CREATE TABLE wird eine existierende Datenbank nicht angerührt und führt zu einer Fehlermeldung.

Datenbank oder Tabelle löschen

Um eine komplette Datenbank oder eine einzelne Tabelle zu löschen gibt es folgende Befehle:

<?php
include("zugriff.inc.php");

$sql = "DROP DATABASE autos"; // löscht die gesamte Datenbank
$sql = "DROP TABLE liste"; // löscht eine einzelne Tabelle samt Inhalt
$sql = "DELETE FROM liste WHERE hersteller='ford'"; // löscht aus der Tabelle "liste" alle Einträge bei denen in der Spalte "hersteller" der Begriff "ford" vorkommt

mysql_query($sql);
mysql_close();
?>

Die Befehle zum löschen werden ohne Rückfrage ausgeführt! Möchte man eine Sicherheitsabfrage, so ist diese mittels php selbst zu definieren!

Einträge in der Datenbank überschreiben/ändern

<?php
include("zugriff.inc.php");

$sql = "UPDATE liste SET hersteller='ford', typ='mustang' WHERE id='4'";

mysql_query($sql);
mysql_close();
?>

Mittels UPDATE werden bestehende Datensätze überschrieben. Dabei kann man die einzelnen Spalten mit dem Wert durch Komma getrennt hintereinander angeben. Die WHERE-Anweisung sagt, welcher Datensatz geändert werden soll. Läßt man WHERE weg, würden sämtliche Datensätze in der Tabelle mit den neuen Werten überschrieben werden. Noch ein Beispiel:
UPDATE liste SET hersteller='golf', typ='III' WHERE hersteller='golf'
würde jedem Datensatz der in der Spalte "hersteller" den Wert "golf" besitzt, in der Spalte "typ" den Wert "III" eintragen.