guenni
Goto Top

Tabellen sortieren mit PHP

Sortierung von Tabellen mit PHP

Teil I - Sortierung von Spalten innerhalb einer Tabelle

1. Ausgabe von Datensätzen in Tabellenform
2. Die sortierte Ausgabe von Spalten innerhalb der Tabelle
3. Die Richtung der Sortierung der einzelnen Spalte(aufwärts, abwärts)
4. Übergabe von Sortierkriterien per Link

Im Anhang I nochmal die PHP-Seite im Zusammenhang

Teil II - Sortierung von Spalten innerhalb einer Tabelle, verteilt auf
mehrere Seiten

Hier gibt's keine Unterpunkte, es werden lediglich die Erweiterungen zur ersten Seite
erläutert.

Im Anhang II auch diese PHP-Seite im Zusammenhang

Der Zugriff auf die Datenbank erfolgt mit HTML/PHP. Als Datenbank-Server läuft
MySQL. Verzichtet wird auf Fehlerabfragen.

Software:
Linux Debian Sarge
Apache
MySQL 4
PHP4

Teil I - Sortierung von Spalten innerhalb einer Tabelle

1. Ausgabe von Datensätzen in Tabellenform

Die einfachste Form, Daten aus einer Datenbank auszugeben:

<?>
$query="select vorname, nachname, telefon from tabelle";  
$result=mysql_query($query, $conn);
echo "<table>";  
while($row=mysql_fetch_array($result, MYSQL_ASSOC)){
 echo "<tr><td>";  
 echo implode("<td>", $row);  
echo "</tr>";  
}
echo "</table>";  
</?>

In der Variablen $query wird die Select-Anweisung gespeichert, diese Variable
wird der Funktion mysql_query übergeben.

Einfache Abfragen können auch folgenderweise realisiert werden:

<?>
$result=mysql_query("select .....", $conn);  
</?>

Hier wird die Select-Anweisung der Funktion direkt als "String" übergeben, im Laufe des
Tutorials wird die Select-Anweisung jedoch um einige Parameter erweitert.

Da die Parameter von Variablen abhängig sind, ist es einfacher, die Select-Anweisung
außerhalb der Funktion zu definieren, und sie dann der Funktion als Variable zu übergeben.

In der while-Schleife werden der Variablen $row die einzelnen Datenfelder der
Datensätze als Array übergeben.

Die Funktion implode fügt ein <td> als Trennzeichen der Datenfelder ein.
Ein </td> ist nicht erforderlich.

2. Die sortierte Ausgabe von Spalten innerhalb der Tabelle

Wenn die oben beschriebene Anweisung 10 oder 20 Datensätze zutage fördert,
so bleibt es einigermaßen übersichtlich. Bei hundert oder mehr Datensätzen kann
das Finden eines Eintrags schon zu einem lästigen Rauf- und Runterscrollen der
Ergebnisseite führen.

Lassen wir uns deshalb mal die einzelnen Spalten sortieren. Dazu wird der Spaltenname
der Tabelle separat ermittelt und als Link dargestellt.
Dieser Link bekommt als Parameter den Spaltennamen "mit auf den Weg" um die
Select-Anweisung zu steuern.

Die Spaltennamen der Tabelle werden mit folg. Anweisung ermittelt und dargestellt:

<?>
$row=mysql_fetch_array($result, MYSQL_ASSOC));
while($field=key($row)){
  echo "<th>$field</th>";  
  next($row);
 }
</?>

Der Variablen $field werden in der while-Schleife die einzelnen Spaltennamen durch
die Funktion key übergeben. Als Trennzeichen verwenden wir diesmal #th>,
th bedeutet table header.

Der Unterschied zwischen th und td ist lediglich der, dass bei th der Eintrag mittig
und fett dargestellt wird, td zu verwenden wäre also kein Fehler.

Um nun einzelne Spalten sortiert dazustellen, muß die Seite erneut aufgerufen werden.
Dazu wird der Spaltenname als Link auf die Seite selber definiert, das Sortierkriterium wird
dem Link als Parameter angehangen:

<?>
while($field=key($row)){
  echo "<th><a href=\" sort.php?sort=$field\">$field</a></th>";  
  next($row);
 }
</?>

Beim Klick auf einen Spaltenkopf wird die Seite sort.php erneut aufgerufen, Inhalt des Parameters sort ist der Name des Spaltenkopfs, über dem sich der Mauszeiger jeweils beim Klick befindet.
Unsere Eingangsabfrage, s.o., gestaltet sich nun folgendermaßen:

<?>
if($sort){
 $query="select vorname, nachname, telefon from tabelle order by $sort";  
}else{
          $query="select vorname, nachname, telefon from tabelle";  
         }
</?>

if($sort) überprüft, ob die Variable $sort mit einem Wert gefüllt ist.
Wenn ja, wird der ja-Zweig der if-Abfrage ausgeführt. Die Tabelle wird so ausgegeben, dass die
Spalte, deren Tabellenkopf angeklickt wurde, sortiert ausgegeben wird.

Wenn die Seite das erste Mal aufgerufen wird, so kann $sort auch nicht gefüllt sein. Folglich wird
dann der Alternativ-Zweig der if-Abfrage ausgeführt.

Vor dem Hintergrund kann man die Ausgabe der Tabelle natürlich auch standardmäßig nach einem bestimmten Kriterium sortieren. Dann sähe die Anweisung so aus:

<?>
if($sort){
 $query="select vorname, nachname, telefon from tabelle order by $sort";  
}else{
          $query="select vorname, nachname, telefon from tabelle order by nachname";  
         }
</?>

3. Die Richtung der Sortierung der einzelnen Spalte(aufwärts, abwärts)

Auch die Richtung der Sortierung der einzelnen Spalte(aufwärts, abwärts) läßt sich steuern, nämlich mit den Konstanten asc und desc.

$query="select vorname, nachname, telefon from tabelle order by nachname asc";
sortiert die Tabelle innerhalb der Spalte nachname aufwärts. Da asc die Standardeinstellung ist,
kann diese optionale Konstante auch entfallen.

$query="select vorname, nachname, telefon from tabelle order by nachname desc";
dagegen sortiert die Tabelle innerhalb der Spalte nachname abwärts.

Um dieses Verhalten zu steuern, definieren wir eine Funktion:

<?>
function direction($dir){
 if($dir= ="asc"){  
  return "desc";  
 }else{
           return "asc";  
         }
}
</?>

Somit können wir die Abfrage um einen weiteren Parameter erweitern:

<?>
if($sort){
 $dir=direction($dir);
 $query="select vorname, nachname, telefon from tabelle order by $sort $dir";  
}else{
          $query="select vorname, nachname, telefon from tabelle";  
         }
</?>

Der Code zur Ermittlung der Spaltennamen wird ebenfalls um einen Parameter erweitert:

<?>
while($field=key($row)){
  echo "<th><a href=\" sort.php?sort=$field&dir=$dir\">$field</a></th>";  
  next($row);
 }
</?>

Analysieren wir den Ablauf:

Die Seite wird zum ersten Mal aufgerufen, die Variable $sort ist leer, folglich wird der Alternativ-Zweig,
oder auch Nein-Zweig, der if-Abfrage ausgeführt.

Ausgabe der Tabelle: Reihenfolge der Datensätze, wie sie eingegeben wurden.

Klicken wir nun einen der Spaltenköpfe an, wird die Seite erneut aufgerufen, diesmal ist die Variable $sort nicht leer, sondern in ihr ist der Name des Spaltenkopfs enthalten, somit wird der ja-Zweig der if-Abfrage ausgeführt.

Innerhalb des ja-Zweigs bekommt die Variable $dir den Rückgabewert der Funktion direction
zugewiesen.

Die Variable $dir wird der Funktion als Parameter übergeben. Da die Variable $dir zu dem Zeitpunkt ebenfalls "leer" ist, wird ihr gemäß der Funktionsbeschreibung erstmal der Wert "asc" übergeben.

Beispiel:

Der Spaltenkopf vorname wird angeklickt.
Die Seite wird erneut aufgerufen.
In der Variablen $sort steckt nun vorname, in der Variablen $dir asc.

Ausgabe der Tabelle: Reihenfolge der Datensätze sind innerhalb der Spalte vorname aufsteigend sortiert.

Teil II - Sortierung von Spalten innerhalb einer Tabelle, verteilt auf
mehrere Seiten

Damit die Ausgabe großer Tabellen noch etwas komfortabler wird, werden wir
nun die Ausgabe auf mehrere Seiten verteilen, natürlich auch sortiert.

Zugrunde liegt die erste PHP-Seite, die um einige Anweisungen erweitert wird:

Anzahl der Datensätze pro Seite:

<?>
$sets=4;
</?>

Wieviele Seiten brauchen wir? Dazu müssen wir wissen, wieviele Datensätze überhaupt
da sind, das erledigt die Funktion count:

<?>
$query="select count(id) as Count from tabelle";  
</?>

Das Ergebnis wird in der Variablen $pages gespeichert:

<?>
$result=mysql_query($query,$conn);
$pages=mysql_fetch_array($result,MYSQL_ASSOC);
</?>

Wenn wir 10 Datensätze haben, ergibt 10(Sätze) geteilt durch 4(die wir anzeigen wollen) 2,5
Seiten, halbe Seite gibt's nicht, die Funktion ceil rundet auf die nächst höhere Ganzzahl auf,
also 3 Seiten:

<?>
$pages=ceil($pages[Count]/$sets);
</?>

Bei einer seitenweisen Ausgabe sucht man sich ein Hauptkriterium heraus, nach welchem
die Seiten vorab sortiert werden, in diesem Beispiel, ein Minitelefonbuch, ist es der Nachname.
Die folgende Anweisung
- erstellt eine temporäre Tabelle, diese wird bei Sitzungsende automatisch gelöscht
- sortiert die Daten der Quelltabelle nach Nachname
- fügt den Teil, den wir sehen wollen, in die temporäre Tabelle ein, angefangen bei
$start, dazu mehr weiter unten, begrenzt auf $sets(s.o. $sets=4)

Den Ausschnitt, den wir sehen wollen, liefert uns der Parameter limit Startwert, Anzahl:

<?>
if($start){
 $query="create temporary table tmp select * from tabelle order by nachname limit start,$sets";  
}else{
          $query="create temporary table tmp select * from tabelle order by nachname limit 0,$sets";  
         }
</?>

Die Daten der einzelnen Seite holen wir nun aus der temporären Tabelle:

<?>
if($sort){
 $dir=direction($dir);
 $query="select vorname, nachname, telefon from tmp order by $sort $dir";  
}else{
       $query="select vorname, nachname, telefon from tmp";  
      }
</?>

Eine Standardsortierung im Nein-Zweig der if-Abfrage kann entfallen, da die Daten
bereits sortiert in der Tabelle tmp vorliegen.

Der Code zur Darstellung des Spaltenkopfs wird um den Parameter start=$start erweitert:

<?>
while($field=key($row)){
  echo "<th><a href=\"sort2.php?start=$start&sort=$field&dir=$dir\">$field</a></th>";  
  next($row);
 }
</?>

Am Ende der Seite
- werden die Links auf die Seiten generiert
- werden die Startwerte errechnet, ab welchem Datensatz die Daten pro Seite
- angezeigt werden

Die Variable $page ist einfach die Seitenzahl, da die Zählung bei Null beginnt, wird eine 1
aufaddiert:

<?>
$start=0;
for($i=0;$i<$pages;$i++){
 $page=$i+1;
 echo "<a href=\"sort2.php?start=$start\">Seite $page</a> ";  
 $start+=$sets;
}
</?>

Anhang I - Anzeige der Tabelle auf einer Seite

<?
function direction($dir){
 if($dir= ="asc"){  
  return "desc";  
 }else{
           return "asc";  
         }
}

$conn=mysql_connect("localhost","user","passwort");  
$db=mysql_select_db("Datenbankname");  
if($sort){
 $dir=direction($dir);
 $query="select vorname, nachname, telefon order by $sort $dir";  
}else{
          $query="select vorname, nachname, telefon from tabelle";  
          //oder  $query="select vorname, nachname, telefon from tabelle order by nachname"; 
          //z.B. als Standardsortierung
         }
$result=mysql_query($query, $conn);
?>
<html>
<head>
<title>Untitled</title>
</head>
<body>
<?
$row=mysql_fetch_array($result, MYSQL_ASSOC));
echo "<table border=\"1\">";  
//Begin des Tabellenkopfes
echo "<tr>";  
while($field=key($row)){
  echo "<th><a href=\" sort.php?sort=$field&dir=$dir\">$field</a></th>";  
  next($row);
 }
echo "</tr>";  
//Ende Tabellenkopf
//Da durch die Anweisung $row=mysql_fetch_array($result, MYSQL_ASSOC)); bereits der
//erste Datensatz "geholt" wurde, muß er separat ausgegeben werden 
echo "<tr>";  
echo implode("<td>", $row);  
echo "</tr>";  
//Dann erfolgen die restlichen Datensätze mit der while-Schleife
while($row=mysql_fetch_array($result, MYSQL_ASSOC)){
 echo "<tr><td>";  
 echo implode("<td>", $row);  
echo "</tr>";  
}
echo "</table>";  
?>
</body>
</html>

Anhang II - Anzeige der Tabelle auf mehreren Seiten

<?
function direction($dir){
 if($dir=="asc"){  
  return "desc";  
 }else{
           return "asc";  
         }
}
$sets=4;
$conn=mysql_connect("localhost","user","passwort");  
$db=mysql_select_db("Datenbankname");  
$query="select count(id)as Count from tabelle";  
$result=mysql_query($query,$conn);
$pages=mysql_fetch_array($result,MYSQL_ASSOC);
$pages=ceil($pages[Count]/$sets);
if($start){
 $query="create temporary table tmp select * from tabelle order by nachname limit $start,$sets";  
}else{
       $query="create temporary table tmp select * from tabelle order by nachname limit 0,$sets";  
			}
mysql_query($query,$conn);
if($sort){
 $dir=direction($dir);
 $query="select vorname, nachname, telefon from tmp order by $sort $dir";  
}else{
       $query="select vorname, nachname, telefon from tmp";  
      }
$result=mysql_query($query, $conn);
?>
<html>
<head>
<title>Untitled</title>
</head>
<body>
<?
$row=mysql_fetch_array($result, MYSQL_ASSOC);
echo "<table border=\"1\">";  
//Begin des Tabellenkopfes
echo "<tr>";  
while($field=key($row)){
  echo "<th>#a href=\"sort2.php?start=$start&sort=$field&dir=$dir\">$field#/a>#/th>";  
  next($row);
 }
echo "</tr>";  
//Ende Tabellenkopf
//Da durch die Anweisung $row=mysql_fetch_array($result, MYSQL_ASSOC)); bereits der
//erste Datensatz "geholt" wurde, muß er separat ausgegeben werden  
echo "<tr><td>";  
echo implode("<td>", $row);  
echo "</tr>";  
//Dann erfolgen die restlichen Datensätze mit der while-Schleife
while($row=mysql_fetch_array($result, MYSQL_ASSOC)){
 echo "<tr><td>";  
 echo implode("<td>", $row);  
echo "</tr>";  
}
echo "</table>#br>";  
$start=0;
for($i=0;$i<$pages;$i++){
 $page=$i+1;
 echo "<a href=\"sort2.php?start=$start\">Seite $page</a> ";  
 $start+=$sets;
}
?>
</body>
</html>

Die Sortierung ist noch nicht ganz perfekt, da die Konstanten asc und desc abwechslend
von der Funktion zurückgegeben werden. Heißt, wenn z.B. eine Spalte bereits aufwärts sortiert
ist, und die Funktion jetzt zufällig den Wert asc zurückgibt, passiert natürlich nichts, obwohl
man(vielleicht) erwarten würde, dass die Spalte nun abwärts sortiert wird.

Dazu müßte man noch Variablen einführen, die sich den sortierten Zustand jeder Spalte
"merken", eine Abfrage definieren, die den Zustand abruft und die erwartete Sortierung
steuert.

Tja, ich glaube, das war's soweit.

Grüße
Günni

Auf Anfrage eines Mitglieds ein Nachtrag:

In der Datei php.ini kann eine Variable namens register_globals gesetzt werden. Diese Variable kann die Einstellung On|Off enthalten.

Wirkung bei register_globals=On:

Variablen, die via GET (zielscript?name=ich&freund=du) oder POST (über Formular: z.B. Textfeldname) gesendet werden, können im Zielscript

einfach verwendet werden, indem man dem Variablennamen einfach das Dollarzeichen ($) voranstellt.

Bei einem Link, "zielscript?name=ich&freund=du", z.B. reicht es, im Zielscript zu fragen: if($name=="ich" . . . ect..

Das Gleiche gilt auch für z.B. Textfelder im Formular "<input . . . . name="ich" . . .": if($_POST['ich']=="Günni" . . . ect..

Und da register_globals standardmäßig in meiner damaligen PHP-Version 4.x mit On belegt war, lief das Script natürlich erwartungsgemäß.


Seit PHP-Version 5.x wird diese Variable standardmäßig mit Off belegt, was zur Folge hat, dass die Variablen je nach Übermittlungsart (POST oder GET)

auch so abgefragt werden müssen, also bei einem Link z.B.:

if($_GET['name'] == "ich" . . . etc..

Oder via Formular:

if($_POST['ich'] == "Günni" . . . ect..

Die Variable wurde seit PHP-Version 5.x aus Sicherheitsgründen auf Off gestellt und soll auch, lt. Info einiger Websites, demnächst in neueren Versionen

ganz aus der Konfig-Datei verschwinden.

Content-Key: 23446

Url: https://administrator.de/contentid/23446

Printed on: April 18, 2024 at 12:04 o'clock

Member: Enclave
Enclave Mar 18, 2006 at 18:10:20 (UTC)
Goto Top
PS: Das Tutorial ist super!

Mfg Enclave
Mitglied: 36213
36213 Oct 03, 2006 at 21:58:20 (UTC)
Goto Top
Du bekommst eine glatte "6" im Umgang mit Datenbanken.
Leider erlaubt mir das Script nur eine einmalige Bewertung (hoffe ich für Dich!), sonst würde ich hier minütlich auflaufen, bis die 4 Sterne verschwunden sind.

Wieso?

Frag nach!
Member: Guenni
Guenni Oct 04, 2006 at 18:27:38 (UTC)
Goto Top
Bin gespannt.
Member: Ash-rak
Ash-rak Aug 01, 2007 at 11:24:05 (UTC)
Goto Top
Und wo hat sich das Tutorial nun versteckt ?

Ich hatte das schonmal gelesen hier aber nun ist es verschwunden.

Ash-rak