Wer mal eben ein Paging für aufwendige Views einbauen möchte findet im Internet meistens ein und das selbe Herrangehen an das Problem.
Es wird erst eine limitierte Query abgesetzt und die Datensätze gezählt und anschliessend wird die Datenbank nochmal abgefragt um das result zu erstellen.
Das ist im Prinzip unperformant, weil man komplexe Tabellen eben 2 mal abfragen muss.
Dazu sehen die Zugriffe und die Codes meist sehr chaotisch aus.
Ein weiterer Nachteil ist die unschöne Darstellung der Seitenlinks, wenn viele Seiten existieren.
Ich habe mir im Zuge eines Kundenprojektes die Arbeit machen müssen eine “saubere” OOP Implemantation vorzunehmen.
Was rauskam ist eine OOP-PHP 5 Portierung der Pagings von ExtJS. Es gibt keine Seitenlinks mehr sondern ein Eingabefeld, welches die momentane Seite anzeigt. Der Vorteil ist, dass man die gewünschte Seite auch einfach eingeben kann.
Ein weiterer Vorteil ist, dass man der Klasse einfach ein Array mit einen Resultset übergeben kann, den Rest mach die Klasse. Keine Weiteren Datenbakabfragen also. Man braucht auch nicht unbeding mysql sondernd die Klasse ist unabhängig vom Datenbanksystem, welches PHP verwendet.
Die Klasse benötigt also keine eigene Datenbankabstraktion sondern nutzt die der Anwendung. Zudem ist der Code gekapselt und man hat keinen Aerger mit ungewollten Namenskonflikten.
Fullscreendemo
Download
Die Einrichtung ist simple. Nun folgt ein Beispiel mit dem Code des Samples hier.
In der Praxis habe ich natürlich statt des einfachen Arrays ein Array mit Objekten verwendet. Und als HTML Engine kam Smarty zum Einsatz.
Wer die Smartyimplementierung sehen will kann sich bei mir melden.
Das Sample ist reduziert. für die Erstellung des Tableheaders sollte man die methode addHeader() verwenden. Und das Form ausserhalb definieren.
Features:
- OOP
- Datenbankunabhängig
- externe Stylesheets
- keine Linklisten
- einstellbare Einträge / Seite (auch über den Request)
<?php
/*
* thats the sample how to use the pagingclass
*/
require_once 'C_PAGING.php';
require_once 'populatedata.php';
//define vars wich must be trasported in the request (UserIDs, Sessions etc)
$arr_params=array("neededParam"=>$_REQUEST['neededParam']);
//instantiiate the pagingclass with 4 parameter
$controller="sample.php";
//the name of the pageparameter (page=1)
$paginVarName="page";
$_paging= new C_PAGING($controller, $arr_params, $result,$paginVarName);
//how many entries per page
$_paging->entriesPerPage=4;
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<link rel='stylesheet' type='text/css' href='css/style.css' />
<link rel='stylesheet' type='text/css' href='css/table.css' />
</head>
<body >
<table id="sortable_table" class="datagrid">
<thead>
<tr>
<th width="200">Firstname</th>
<th width="200">Lastname</th>
<th width="300">Street</th>
<th>Location</th>
<th>Zip</th>
</tr>
</thead>
<?php
//iterate the resultset
foreach($result as $key=>$arr_value) {
$html[$key].="<tbody>";
$html[$key].="<tr>";
$html[$key].="<td>".$arr_value['firstname']."</td>";
$html[$key].="<td>".$arr_value['lastname']."</td>";
$html[$key].="<td>".$arr_value['street']."</td>";
$html[$key].="<td>".$arr_value['location']."</td>";
$html[$key].="<td>".$arr_value['Zip']."</td>";
$html[$key].="</tr>";
$html[$key].="</tbody>";
//add current row to the object
$_paging->addRow($html[$key]);
}
//add navigation
echo $_paging->addNavigation();
//diplay tablefooter
?>
</table>
<body>
</html>
Daten populieren
Die Daten kommen aus einem einfachen array. Ihr könnt auch ein Database result nehmen.
Wichtig ist nur das die Struktur : array(’1′=>value,2=>value2) ist
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
//populate from an array, sample of using a resultset coming soon
$result = array();
$result[1]['firstname'] ="Peter";
$result[1]['lastname'] ="Böthig";
$result[1]['street'] ="Bodenacher Strasse 65";
$result[1]['location'] ="Benglen";
$result[1]['Zip'] ="Benglen";
$result[2]['firstname'] ="Stephen";
$result[2]['lastname'] ="King";
$result[2]['street'] ="Mainstreet";
$result[2]['location'] ="Manchaster Str.22";
$result[2]['Zip'] ="Birmingham";
?>
Die Klasse C_PAGING.php dazu ist auch überschaubar.
<?php
/*
* @desc generates a pagein for database views
* no database is needed.
* the paging will be generated from an databaseresult. in the simplest was it is an array
* @author peter boethig
* @date : 26.11.09
* @copyright by Peter Böthig
* @ feel free to use ist for free
* @version 1.0
*/
class C_PAGING {
//selftalking
var $entriesPerPage = 20;
//simly an iterator
var $iterator = 0;
//current page
var $page = 1;
//count the elements in the db-results
var $countElements = 0;
//the HTML Row
var $row = array(0=>'<tr>eine row</tr><tr>eine row</tr><tr>eine row</tr>');
//the tableheader
var $headerHTML = "<table><tr><td>header1</td><td>header2</td><td>header3</td></tr>";
//the closing table
var $footerHTML = "</table>";
//the linktaget
var $target = "_self";
//the page wich the link routes
var $controller = "yourPageHier.php";
//contains the needed requestparameters
var $params = array();
//the style of the link
var $buttonCSS = "buttonCSS";
//the buttons
var $pagesCSS = "pagesCSS";
//the style for the linkcontainer
var $pagingDIVCSS = "pageingDiv";
//default next, back, next, last arrows you can use images here
var $arr_images = array("first"=>"<<","back"=>"<","next"=>">","last"=>">>");
//the displayed HTML
var $html = array();
var $pages = 0;
//requestpagameter
var $currentPage = 1;
//hiddenfields needed for request
var $hiddenfields = "";
//default requestvar
var $requestvariable ="page";
/**
* @desc builts the maindatas
* @param <string> $controller
* @param <array> $params
* @param <array> $result
*/
function __construct($controller,$params,$result,$requestvariable) {
//if requestparam > pages or 0
if($requestvariable=="") {
$this->requestvariable=$requestvariable;
echo"Warning: no requestvariable defined: using \$requestvariable";
}
if($_REQUEST[$requestvariable] > 0) {
$this->currentPage = $_REQUEST[$requestvariable];
}
else {
$this->currentPage=1;
}
//databaseresult ist needed
if(count($result)<1) {
die(get_class()."__construct() keine Daten zu pagen");
}
if(isset($controller)) {
$this->controller=$controller;
}
if(isset($params)) {
$this->params=$params;
}
$this->countElements = count($result);
}
/**
* @desc generates needed hiddenfields from needed parameters
* @return <string>
*/
function setHiddenFields() {
if(is_array($this->params)) {
foreach($this->params as $key=>$param) {
$this->hiddenfields .="<input type='hidden' name='".$key."' id='".$key."' value='".$param."' />";
}
$this->hiddenfields .="<input type='hidden' name='entriesPerPage' value='".$this->entriesPerPage."' />";
}
return $this->hiddenfields;
}
/**
* @desc checks the request if var is given
*/
function setEntriesPerPage() {
if($_REQUEST['entriesPerPage']!= $this->entriesPerPage && $_REQUEST['entriesPerPage'] > 0 ) {
$this->entriesPerPage=$_REQUEST['entriesPerPage'];
}
}
/**
* @desc simply resets the iterator if entriesperpage is reached
*/
function work() {
$this->setEntriesPerPage();
//calc pages
$this->pages = ceil($this->countElements / $this->entriesPerPage);
//reset if max is reached
if($this->currentPage > $this->pages) {
$this->currentPage=1;
}
if($this->iterator == $this->entriesPerPage) {
$this->iterator=0;
$this->page++;
}
}
/**
* @desc adds a HTML ROW to an array
*/
function addRow($row) {
$this->work();
$this->row[$this->page] .= $row;
$this->next();
}
/**
* @desc increeses iterator
*/
function next() {
$this->iterator ++;
}
/**
* @desc returns the list with entries
* @param <int> $page
* @return <array>
*/
function addCurrentPage($page) {
return $this->row[$page];
}
/**
* @desc contains the HEaderHTML
* @param <type> $headerHTML
* @return <type>
*/
function addTableHeader($headerHTML) {
return $this->headerHTML = $headerHTML;
}
/**
* @desc returns the tablefooter
* @param <string> $footerHTML
* @return <HTML>
*/
function addTableFooter($footerHTML) {
return $this->footerHTML = $headerHTML;
}
/**
* @desc adds navigation
*/
function addNavigation() {
$this->html ="<form class='f_form' name='form_paging' action='".$this->controller."' target=".$this->target.">";
$this->html.= $this->setHiddenFields();
$this->html.="<div id='".$this->pagingDIVCSS."'>";
//sets the first,next, back, etc
$this->setFirstLinks();
//sets the pagelinks
$this->setPageField();
//sets the next, lastlinks
$this->setNextLinks();
$this->html.="</div>";
$this->html.="</form>";
//display page
$this->html.= $this->addCurrentPage($this->currentPage);
return $this->html;
}
/**
* @desc sets the next and lastlinks
*/
function setNextLinks() {
if($this->arr_images['next']!=">"&& $this->arr_images['last']!="&lgt;<") {
$this->html.= "<img src='".$this->arr_images['first']."'/> <img src='".$this->arr_images['back']."'/> ";
}else {
$this->html.= "<a href='".$this->controller."?page=".$this->setNext().$this->getParams()."'
target=".$this->target." class=".$this->buttonCSS.">".$this->arr_images['next']."</a>
<a href='".$this->controller."?page=".$this->setLast().$this->getParams()."'
target=".$this->target." class=".$this->buttonCSS.">".$this->arr_images['last']."</a>";
}
}
/**
* @desc sets the next and lastlinks
*/
function setFirstLinks() {
if($this->arr_images['first']!="<<" && $this->arr_images['back']!="<") {
$this->html.= "<img src='".$this->arr_images['first']."'/><img src='".$this->arr_images['back']."'/>";
}else {
$this->html.= "
<a href='".$this->controller."?page=".$this->setFirst().$this->getParams()." ' target=".$this->target."
class=".$this->buttonCSS.">".$this->arr_images['first']."</a>
<a href='".$this->controller."?page=".$this->setPrievious().$this->getParams()."' target=".$this->target."
class=".$this->buttonCSS.">".$this->arr_images['back']."</a>";
}
}
/**
* @desc sets the privious page
* @return <int>
*/
function setFirst() {
return 1;
}
/**
* @desc sets the privious page
* @return <int>
*/
function setPrievious() {
if($this->currentPage > 1) {
return $this->currentPage-1;
}
return 1;
}
/**
* @desc sets the next page
* @return <int>
*/
function setNext() {
if($this->currentPage < $this->pages) {
return $this->currentPage + 1;
}
return $this->pages;
}
/**
* @desc sets the last page
* @return <int>
*/
function setLast() {
return $this->pages;
}
/**
* @desc sets the pagelinks
*/
function setPageField() {
$this->html.="
<p class='ofPages'>Seite</p>
<input type='text' id='f_page' name='page' class='f_page' value='".$this->currentPage."'/>
<p class='ofPages'> von ".$this->pages."</p>";
}
/**
* builts the URL
*/
function setURL() {
return $this->controller."?page=".$this->page.$this->getParams();
}
/**
* sets the paramstring
*/
function getParams() {
if(is_array($this->params)) {
foreach($this->params as $key=>$param) {
$paramString .="&".$key."=".$param;
}
$paramString.="&entriesPerPage=".$this->entriesPerPage;
}
return $paramString;
}
}
?>
abschliesend noch die Styles (style.php) dazu:
/*
Document : style.css
Created on : 27.11.2009, 11:34:13
Author : Peter Boethig
Description:
Styles for the paginengin
*/
/*
TODO customize this sample style
Syntax recommendation http://www.w3.org/TR/REC-CSS2/
*/
#pageingDiv
{
border:0px solid black;
width:250px;
color:#000;
height:30px;
background-image:url('../images/pagingBackground.gif');
padding:8px 0 0 40px;
margin:0 0 0 0;
font-weight:bold;
text-align:center;
font-family:verdana, sans-serif;
font-size:12px;
}
#pageingDiv a.buttonCSS:link,
#pageingDiv a.buttonCSS:link,
#pageingDiv a.buttonCSS:hover,
#pageingDiv a.buttonCSS:active,
#pageingDiv a.buttonCSS:visited
{
padding:2px 3px 0 0;
margin:0 2px 0 0 ;
color:#487efa;
font-weight:bold;
display:block;
width:22px;
height:20px;
float:left;
text-align:center;
border:1px solid #ffffff;
text-decoration:none;
background-color:#fff;
background-image:url('../images/pagingBackground.gif');
}
#pageingDiv a.buttonCSS:hover
{
color:#cecece;
background-color:#487efa;
background-image:none;
}
#pageingDiv a.pagesCSS:link,
#pageingDiv a.pagesCSS:link,
#pageingDiv a.pagesCSS:hover,
#pageingDiv a.pagesCSS:active,
#pageingDiv a.pagesCSS:visited
{
border:0;
padding:0 3px 0 0;
color:#000;
display:block;
width:20px;
float:left;
text-align:center;
}
#pageingDiv a.pagesCSS:hover
{
color:#cecece;
}
#f_page{
width:40px;
height:22px;
padding:0;
margin:0;
float:left;
color:#487efa;
font-size:14px;
background-image:url(../images/inputBG.gif);
}
p.ofPages
{
float:left;
padding:4px 3px 0 3px;
font-size:11px;
font-weight:normal;
color:#487efa;
}
.f_form
{
margin:0;
padding:0;
}