globe: Umfassendes Paging mit PHP und MySQL

Beitrag lesen

n'abend,

Wie richtet man ein umfassendes Paging via PHP und MySQL ein? (Sprich: xy Einträge in einer Tabelle, davon sollen pro Seite immer nur z ausgegeben werden.)

Um eine sinnvolle Seitennavigation (von mir aus können wir es auch Paging nennen, wenn denn so sehr auf komische Anglizismen steht) zu schaffen, musst du die Rahmenbedingungen kennen:

  1. Wie viele Datensätze habe ich überhaupt?
  2. Wie viele und welche Datensätze möchte ich pro Seite anzeigen?
  3. Wie viele Seiten links möchte ich denn anzeigen? Bei hunderten Seiten ist es nicht sonderlich praktisch alle Links zu jeder einzelnen Seite anzuzeigen.
  4. Nach welchem Schema möchte ich denn mein Subset an Links (was dem Gedanken 3 nach unumgänglich ist) anzeigen? Möchte ich ich »1, 2, 3, ..., 5, [6], 7, ..., 10, 11, 12« haben? oder vielleicht lieber »3, 4, 5, [6], 7, 8, 9 , 10, 11«?

Grundsätzlich gibt es die Funktion COUNT(), um an die Gesamtzahl an Datensätzen zu gelangen. Aber zwei sehr ähnliche Abfragen auf die Datenbank zu feuern erscheint einem bei näherem Betrachten nicht ganz so optimal, zumindest dann, wenn mal SQL_CALC_FOUND_ROWS und FOUND_ROWS() kennt. Wichtig für unser Vorhaben ist auch eine Möglichkeit die Menge der zurückgelieferten Datensätze einzugränzen, was wir mit LIMIT recht einfach machen können.

/* hole Daten für Seite $p */  
SELECT SQL_CALC_FOUND_ROWS colum1, colum2, colum3  
FROM table  
WHERE colum4 = 42  
ORDER BY column1  
LIMIT 0, 10;  
  
/* hole die Gesamtzahl der Datensätze */  
SELECT FOUND_ROWS();

Das könnte in PHP verpackt ungefähr so ausschauen:

// Die Seite auf der wir uns gerade befinden (beginnend bei 1)  
$currentPage = 2;  
  
// Anzahl Datensätz pro Seite  
$itemsPerPage = 15;  
  
/*  
 * Die Datensatzlaufnummer, bei der wir anfangen wollen.  
 * Der erste Datensatz hat die Laufnummer 0, unsere Seiten  
 * fangen aber bei 1 an, weshalb wir die Seitenzahl um eins  
 * reduzieren müssen, bevor wir mittels der Multiplikation  
 * mit der Anzahl von Datensätzen pro Seite eine Sprungmarke  
 * bekommen  
 */  
$itemOffset = ($currentPage - 1) * $itemsPerPage;  
  
// Datensätze der aktuellen Seite ermitteln  
$res = mysql_query( 'SELECT SQL_CALC_FOUND_ROWS colum1, colum2, colum3  
FROM table  
WHERE colum4 = 42  
ORDER BY column1  
LIMIT '. $itemOffset .','. $itemsPerPage );  
  
// Gesamtzahl der Datensätze abfragen  
$totalItems = mysql_fetch_row( mysql_query( 'SELECT FOUND_ROWS()' ) );  
$totalItems = $totalItems[0];  
  
// Gesamtzahl der Seiten ermitteln  
$totalPages = ceil( $totalItems / $itemsPerPage );  
  
/*  
 * Wir wissen an dieser Stelle, dass die erste mögliche Seite, die Seite 1 ist.  
 * Wir wissen, dass wir momentan Seite $currentPage geöffnet haben  
 * und unsere Datensätze auf gesamthaft $totalPages Seiten aufgeteilt haben.  
 * Wir haben an dieser Stelle also alle Grenzwerte, die wir brauchen, um eine Sinnvolle Seitennavigation zu generieren.  
 */  
  
/*  
 * - Sind wir auf der ersten Seite?  
 * - Sind wir auf der letzten Seite?  
 * - Wo stecken wir mit $currentPage genau?  
 *     Sind wir nahe am Anfang?  
 *     Sind wir nahe am Ende?  
 * - Wie viele Links können wir in die beiden Richtungen anzeigen,  
 *   ohne den Grenzwert zu überschreiten, oder mehr Seiten-Links zu  
 *   generieren, als wir maximal anzeigen wollen?  
 *  
 * Die Beantwortung der gestelleten Fragen wird als Übungsaufgabe hinterlassen.  
 */  
  
// Daten ausgeben  
while( $row = mysql_fetch_assoc($res) )  
  print_r( $row );  

Ich bin zwar kein absoluter PHP-Anfänger mehr, aber das vollständig selbst zu programmieren, übersteigt doch noch meinen Horizont, deshalb wäre es einfach praktisch und toll, wenn es dafür ein Script gäbe. Auch für einen Buchtipp wäre ich dankbar. ;-)

Meiner Meinung nach hat das nichts mit der verwendeten Programmiersprache zu tun, diese ist immerhin nur Mittel zum Zweck. Die Fähigkeit Abläufe zu erfassen und abstrahieren zu können ist die Kunst.

weiterhin schönen abend...

--
#selfhtml hat ein Forum?
sh:( fo:# ch:# rl:| br:> n4:& ie:{ mo:} va:) de:] zu:} fl:( ss:? ls:[ js:|