Native Pagination in TYPO3 10

Mit der neuen Version bekommt TYPO3 auch eine native Möglichkeit für die Paginierung von Datensätzen. So könnte Ihr sie nutzen!

Habt ihr nicht auch schon immer mit diesem Widget für eine Paginierung von Ergebnislisten einer TYPO3 Extension gehadert? Also ich war froh, als ich das letztens in den Changelogs gesehen hatte.

The TYPO3 core provides an interface to implement the native pagination of lists like arrays or query results of Extbase.

Da ich in meiner Extension sowieso ein Problem mit der Weitergabe von Suchparametern auf nachfolgende Seiten hatte (addQueryStringMethod POST war nicht mehr möglich), fiel die Entscheidung für einen Umbau nicht schwer. Da sich die Doku für eine Umstellung in Grenzen hält, will ich euch die Schritte im einzelnen etwas näher bringen. Wie immer ist das hier nur einer von vielen Wegen so etwas umzusetzen. Verbesserungsvorschläge sind daher natürlich immer willkomen. Gern als Kommentar oder als Anregung im Github Projekt der Extension welches ich nachfolgend auch verlinke.

Im Groben habe ich mich bei meiner Umsetzung an diesem Beispiel (Steckt im neuen Extension Manager) orientiert:
https://review.typo3.org/c/Packages/TYPO3.CMS/+/64524

Wie versprochen hier der Link zu meinem Github Repo, wo ihr euch die komplette Umsetzung anschauen könnt.
https://github.com/kanow/operations

Die Extension ist für die Darstellung von Feuerwehreinsätzen gedacht und bietet vielfältige Möglichkeiten diese mit zusätzlichen Information auszugeben. Eine Liste und ein Filter zur Einschränkung der Ergebnisliste nach verschiedenen Kriterien ist ein wichtiges Feature und natürlich braucht man dafür auch eine funktionierende Paginierung.

In meiner Extension habe ich nun die listAction und die searchAction im Controller erweitert und dabei die Klasse QueryResultPaginator benutzt. Um die hier aufgeführten Code Snippets zu benutzen, solltet ihr am Anfang eures Controllers folgendes einfügen:

use TYPO3\CMS\Extbase\Pagination\QueryResultPaginator; use TYPO3\CMS\Core\Pagination\SimplePagination;

Nun können wir ein erstes ein QueryResultPaginator Objekt erzeugen

$paginator = new QueryResultPaginator($operations, $currentPage, $this->settings['itemsPerPage']);

Dabei sind die zu durchlaufenden Items anzugeben, die gerade aktuelle Seite und wieviele Einträge pro Seite angezeigt werden sollen. Die $currentPage hole ich mir vorher entweder aus den Argumenten (wenn vorhanden) oder lege sie auf 1 fest. Dann ist es eben die erste Seite.

$currentPage = $this->request->hasArgument('currentPage') ? $this->request->getArgument('currentPage') : $currentPage;

Dann die eigentliche Paginierung erzeugen

$simplePagination = newSimplePagination($paginator);

Nun kann ich mit der Methode buildSimplePagination für die jeweilige Action einfach die Pagination bauen.

/** 
  * build simple pagination
  *
  * @param SimplePagination $simplePagination
  * @param QueryResultPaginator $paginator
  * @return array
  */ 
protected function buildSimplePagination(SimplePagination $simplePagination, QueryResultPaginator $paginator) {
 $firstPage = $simplePagination->getFirstPageNumber();
 $lastPage = $simplePagination->getLastPageNumber();
 return [ 
   'lastPageNumber' => $lastPage,
   'firstPageNumber' => $firstPage,
    'nextPageNumber' => $simplePagination->getNextPageNumber(),
    'previousPageNumber' => $simplePagination->getPreviousPageNumber(),
    'startRecordNumber' => $simplePagination->getStartRecordNumber(),
    'endRecordNumber' => $simplePagination->getEndRecordNumber(),
    'currentPageNumber' => $paginator->getCurrentPageNumber(),
    'pages' => range($firstPage, $lastPage) 
  ];
} 

Der übergebe ich einfach meine zuvor erzeugten Objekte. Dadurch muss ich diesen Code nicht in jeder Action wiederholen.

$pagination = $this->buildSimplePagination($simplePagination, $paginator);

Damit bekomme ich nun die notwendigen Daten und kann dann mit die Pagination in meiner Action bauen lassen. Jetzt müssen wir das Ergebnis noch an das Template übergeben

$this->view->assignMultiple([ 'pagination' => $pagination, 'paginator' => $paginator ]);

Und das Templating in den Fluid Templates selbst anpassen. Am besten ihr schaut euch mit einem <f:debug>{pagination}</f:debug> und <f:debug>{paginator}</f:debug> die gelieferten Angaben an. Dann könnt ihr eure eigene Pagination recht easy templaten. Da dies etwas umfangreicher ist und je nach Anforderung sicherlich unterschiedlich aussehen wird, verzichte ich hier auf größere Ausschnitte aus dem FluidTemplate. Ihr könnt euch aber jederzeit mein verwendetes Template im Github anschauen. Ich habe mir ein Partial angelegt welches ich nun oberhalb oder unterhalb meiner Liste nutzen kann. Die Datensätze stecken übrigens in {paginator} und werden dabei als mit {items:paginator.paginatedItems} an das Partial übergeben.

Ihr findet das Partial in: Resources/Private/Partials/List/Pagination.html Ein extra ViewHelper wird nun nicht mehr benötigt, es gibt keine Probleme mehr mit irgendwelchen Argumenten die das Widget irgendwie verarbeiten muss, der Controller kümmert sich nun auch selbst um die Pagination. Die leichtgewichtige SimplePagination bringt alles mit was man braucht um sich eine eigene Pagination zu bauen. Nicht in 3 Zeilen Code erledigt, dafür aber eben alle Freiheiten.

Mein Beispiel ist nur eine Variante und zeigt eine einfache Möglichkeit eine Paginierung in eurer Extension zu benutzen. Ich hoffe es hilft dem einen oder anderen und/oder inspiriert euch diese Paginierung zu erweitern.

Nachtrag:

Mittlerweile gibt es von Georg Ringer auch eine nette Extension dafür: numbered_pagination, welche ich nun auch in operations verwende. Da ist das ganze noch ein wenig hübscher gestaltet. Die Seitenlinks werden da auch nicht unendlich viel sondern es wird immer nur eine bestimmte Anzahl angezeigt. Natürlich könnte man diesen Code auch in seine eigene Extension integrieren aber so mus sman sich nicht um die Sicherstellung der Funktionalität bei zukünftigen Updates kümmern. Und der Georg ist da eigentlich ja auch ganz gut hinterher.


Kommentare

Recht hast du ;-). Werd ich mal in Angriff nehmen.

If you find the documentation insufficient, perhaps you can write what you are missing in the documentation as issue or submit a PR? Thanks.

issues: https://github.com/TYPO3-Documentation/TYPO3CMS-Reference-CoreApi/issues

docs page: https://docs.typo3.org/m/typo3/reference-coreapi/master/en-us/ApiOverview/Pagination/Index.html

Jep, gute Idee. Werde das dahingehend sicher auch mal noch umbauen und flexibler gestalten. Der Georg hat dafür sogar eine eigene kleine Extension für gebaut. Die kann man dann einfach in seiner eigenen Extension verwenden wenn man möchte. https://extensions.typo3.org/extension/numbered_pagination

Ist auch ein Ansatz, allerdings hat man dann eben eine Dependency auf diese Extensioon.

Danke für das Beispiel. Ich benötige die Paginierung in mehreren Listen-Ansichten. Dafür habe ich das vorgegebene Beispiel in eine zusätzliche Service Klasse ausgelagert, die ich in den List-Actions der jeweiligen Controller nutzen kann.

https://gist.github.com/jokumer/c0034a0005685d92bf95453ac1434bef


Kommentar schreiben

* Diese Felder sind erforderlich