Skip to content

Commit

Permalink
Paginierungs-Beispiel
Browse files Browse the repository at this point in the history
Beispiel-Klasse zur Erstellung einer Paginierung, zur weiteren
Verwendung in Blog-Modulen, Suchergebnissen, etc.

FriendsOfREDAXO/friendsofredaxo.github.io#10
https://github.com/tyrant88/search_it/issues/44
  • Loading branch information
alxndr-w committed Oct 4, 2016
1 parent a5c02e2 commit 92de0ff
Showing 1 changed file with 266 additions and 0 deletions.
266 changes: 266 additions & 0 deletions class_pagination.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
# Pagination

Eine simple Paginationsklasse, zum Blättern von Seiten (bspw. bei einem Blog, bei Suchergebnissen in `search_it` o.ä.)

## Anwendung

Die Klasse benötigt zunächst nur 3 Parameter:

* `$total`: Anzahl der gesamten Ergebnisse
* `$page`: Aktuelle Seitenzahl (default: 1)
* `$limit`: Anzahl der Ergebnisse innerhalb einer Seite (default: 10)


## Beispiel-Code

```
// Pagination initialisieren
$pagination = new Pagination($total, $page, $limit);
// Zusätzliche Optionen und Parameter
# $pagination->addParams("search", rex_request("search", "string", "")); // zusätzliche URL-Parameter, bspw für `search_it`
# $pagination->setHash("results"); // ID der Sprungmarke, zu der der Browser beim Auswahl einer Seite springen soll
# $pagination->setOption("show_max", 5); // Anzahl der Links, die um die aktuelle Seite angezeigt werden.
# $pagination->setOption("show_skip", false); // Zeige Erster/Letzer Link
# $pagination->setOption("show_neighbours", false); // Zeige Zurück/Vor Link
# $pagination->setId("1"); // Ziel-Artikel-ID
// Optional: Syntax überschreiben
# $pagination->setHtml('ul', '<ul class="###class###">###items###</ul>');
# $pagination->setHtml('li', '<li class="###class###">###anchor###</li>');
# $pagination->setHtml('a', '<a href="###href###" class="###class###">###text###</a>');
// Text der Navigations-Links überschreiben
# $pagination->text['first'] = '«';

This comment has been minimized.

Copy link
@staabm

staabm Oct 7, 2016

Member

warum verwendest du für diese api ein public array und oben überall setter?

This comment has been minimized.

Copy link
@alxndr-w

alxndr-w Oct 7, 2016

Author Member

(wie gesagt, weil ich es nicht besser weiß)

# $pagination->text['last'] = '»';
# $pagination->text['prev'] = '‹';
# $pagination->text['next'] = '›';
// Pagination ausgeben
echo $pagination->show();
```

## PHP-Code

Diesen Code bspw. in Redaxo unter `/redaxo/src/addons/project/lib/` abspeichern, die Klasse wird dann über den redaxo-internen Autoloader geladen und in jedem Modul / Template zur Verfügung gestellt.

```
<?php
/*
*
* Pagination
* Gibt eine Liste mit Paginierungs-Links aus.
*
* @author: @alexplus_de Alexander Walther
* @version: 0.2
*
*/
class Pagination {
public $limit;
public $offset;
public $total;
public $page;
public $page_max;
public $html = array();

This comment has been minimized.

Copy link
@staabm

staabm Oct 7, 2016

Member

Warum alles public wenn es setter gibt? Entweder setter oder public field.

This comment has been minimized.

Copy link
@alxndr-w

alxndr-w Oct 7, 2016

Author Member

kannst du mir eins der beiden für diesen Fall empfehlen? (zur Erinnerung - ich bin noch nicht sehr OOP-fest)

This comment has been minimized.

Copy link
@staabm

staabm Oct 7, 2016

Member

für "anfänger" sind setter besser.

This comment has been minimized.

Copy link
@alxndr-w

alxndr-w Oct 7, 2016

Author Member

ok, dann setze ich die auf private.

public $text = array();
public $option = array();
public $url = array();
public $params = array();
private $elements = array();
private $return = "";
public function __construct($total = 50, $page = 1, $limit = 10) {
$this->total = $total; // Letzter Eintrag
$this->page = $page; // Aktuelle Seite
$this->limit = $limit; // Einträge pro Seite
$this->offset = $page * $limit; // Aktueller Eintrag
$this->page_max = (int) ($total / $limit); // Letzte Seite
$this->html['ul'] = '<ul class="###class###">###items###</ul>';
$this->html['li'] = '<li class="###class###">###anchor###</li>';
$this->html['a'] = '<a href="###href###" class="###class###">###text###</a>';
$this->html['span'] = '<span class="###class###">###text###</span>';
$this->text['first'] = '«';
$this->text['last'] = '»';
$this->text['prev'] = '‹';
$this->text['next'] = '›';
$this->option['show_max'] = 5; // Anzahl der Seiten-Links um die aktuelle Seite herum
$this->option['show_skip'] = true; // Zeige Erste / Letzte
$this->option['show_neighbours'] = true; // Zeige Vor / Zurück
$this->url['id'] = "REX_ARTICLE_ID"; // Ziel-Artikel-ID
$this->url['hash'] = ""; // Ziel-ID (ohne "#")
return true;
}
public function setHtml($key, $value) {
$this->html[$key] = $value;
return true;

This comment has been minimized.

Copy link
@staabm

staabm Oct 7, 2016

Member

warum return true in allen settern?

This comment has been minimized.

Copy link
@alxndr-w

alxndr-w Oct 7, 2016

Author Member

muss ich falsch rauskopiert haben aus einem Beispiel

}
public function setText($key, $value) {
$this->text[$key] = $value;
return true;
}
public function setOption($key, $value) {
$this->option[$key] = $value;
return true;
}
public function setHash($hash) {
$this->url['hash'] = $hash;
return true;
}
public function setId($id) {
$this->url['id'] = $hash;
return true;
}
public function addParams($key, $value) {
$this->params[$key] = $value;
return true;
}
public function getFirst() {
// Erste Seite
if($this->option['show_skip']) {
$anchor = $this->buildAnchor(1, $this->text['first']);
$li = str_replace("###anchor###",$anchor,$this->html['li']);
if($this->offset > $this->limit) {
$li = str_replace("###class###","first",$li);
} else {
$li = str_replace("###class###","first disabled",$li);
}
return $li;
}
}
public function getPrev() {
// Zurück
if($this->option['show_neighbours']) {
$page = $this->page-1;
if($page < 1) {

This comment has been minimized.

Copy link
@staabm

staabm Oct 4, 2016

Member

anstatt dieser ganzen berechnungen in dieser klasse zu machen, könntest du dafür auch den rex_pager verwenden https://github.com/redaxo/redaxo/blob/master/redaxo/src/core/lib/util/pager.php

damit würde sich diese klasse hier auf die markup aspekte reduzieren

This comment has been minimized.

Copy link
@alxndr-w

alxndr-w Oct 4, 2016

Author Member

Tja, wenn ich den denn gekannt hätte :D

Ich werde das Beispiel nicht nochmal umbauen, bin aber für PRs offen :)

(Was meine Klasse ja macht, ist auch, zu definieren, wie viele Links um den Cursor anzeigt, z.B. bei 5 3-4-5-6-7 - das gibt's ja so nicht in rex_pager)

This comment has been minimized.

Copy link
@staabm

staabm Oct 4, 2016

Member

Tja, wenn ich den denn gekannt hätte :D

again what learned ;-).

(Was meine Klasse ja macht, ist auch, zu definieren, wie viele Links um den Cursor anzeigt, z.B. bei 5 3-4-5-6-7 - das gibt's ja so nicht in rex_pager)

das ist im prinzip keine pager-logic daher kann die in deiner klasse bleiben.

$page = 1;
}
$anchor = $this->buildAnchor($page, $this->text['prev']);
$li = str_replace("###anchor###",$anchor,$this->html['li']);
if($this->offset > $this->limit) {
$li = str_replace("###class###","prev",$li);
} else {
$li = str_replace("###class###","prev disabled",$li);
}
return $li;
}
}
public function getNext() {
// Nächste
if($this->option['show_neighbours']) {
$page = $this->page + 1;
if(($page * $this->limit) >= $this->total) {
$page = (int) ($this->total / $this->limit);
}
$anchor = $this->buildAnchor($page, $this->text['next']);
$li = str_replace("###anchor###",$anchor,$this->html['li']);
if((($this->page+1) * $this->limit) <= $this->total) {
$li = str_replace("###class###","next",$li);
} else {
$li = str_replace("###class###","next disabled",$li);
}
return $li;
}
}
public function getLast() {
// Letzte Seite
if($this->option['show_skip']) {
$anchor = $this->buildAnchor((int) ($this->total / $this->limit), $this->text['last']);
$li = str_replace("###anchor###",$anchor,$this->html['li']);
if((($this->page+1) * $this->limit) <= $this->total) {
$li = str_replace("###class###","last",$li);
} else {
$li = str_replace("###class###","last disabled",$li);
}
return $li;
}
}
private function buildAnchor($page, $text = '') {
$this->addParams("page", $page);
$href = rex_getUrl($this->url['id'], null, $this->params);
if($this->url['hash']) {
$href .= "#".$this->url['hash'];
}
$span = str_replace("###text###",$text,$this->html['span']);
$anchor = str_replace("###text###",$span,$this->html['a']);
$anchor = str_replace("###href###",$href,$anchor);
$anchor = str_replace("###key###",$key,$anchor);
return $anchor;
}
public function show() {
$elements[] = $this->getFirst();
$elements[] = $this->getPrev();
if($this->page_max > $this->option['show_max']) {
$first = $this->page - (int)($this->option['show_max']/2);
$last = $this->page + (int)($this->option['show_max']/2);
while($first < 1) {
$first++;
$last++;
}
while($last > $this->page_max) {
$first--;
$last--;
}
} else {
$first = 1;
$last = $this->page_max;
}
// Zahlen
for($i = $first; ($i <= $last); $i++)
{
$anchor = $this->buildAnchor($i, $i);
$list = str_replace("###anchor###",$anchor,$this->html['li']);
if($i == $this->page) {
$list = str_replace("###class###","current",$list);
} else {
$list = str_replace("###class###","",$list);
}
$elements[] = $list;
}
$elements[] = $this->getNext();
$elements[] = $this->getLast();
foreach ($elements as $element) {
$return .= $element;
}
$return = str_replace("###items###",$return,$this->html['ul']);
$return = str_replace("###class###","pagination",$return);
return $return;
}
}
```

1 comment on commit 92de0ff

@staabm
Copy link
Member

@staabm staabm commented on 92de0ff Oct 4, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generell ein schöner einfacher weg um rel. frei das markup einer paginierung zu erstellen... 👏

Please sign in to comment.