Eigener Pagebrowser für die Listenausgabe mit Fluid

Hinweis: Ab TYPO3 7.5 besteht die Möglichkeit dem Paginator Widget Argumente zu übergeben. Damit sollte sich in vielen Fällen die Notwendigkeit eines eigenen Pagebrowsers erübrigen.

Für einen Pagebrowser in einer Listenausgabe kann man das Fluid Paginator Widget verwenden. Dieses kann auch einem eigenem Template zugeordnet werden um die Ausgabe zu individualisieren.

verlorene Paramter
Bis TYPO3 7.5 war es aber nicht möglich, der Pagination irgendwelche Parameter mitzugeben. Wenn ihr also ein Queryergebnis wie z.B. $this->myRepository->findByColor($color) paginiert, ist nach dem ersten Seitenblättern über den Paginator die Variable $color verloren.

In dem Fall muss man das Paginator Widget ergänzen, oder man schreibt direkt einen eigenen Paginator.
So kompliziert ist das auch nicht ....


Die Controller Logik

Parameter übernehmen
Zunächst müssen wir innerhalb der List Funktion erst einmal auf alle möglichen Parameter prüfen, inklusive einer Seitenzahl.

Daten zählen
Danach zählen wir im Repository die Datensätze die den Paramtern entsprechen - je nach Ergbeniss brauchen wir gar keinen Paginator.

Benötigte Daten abfragen
Anhand der Seitenvariabel und der Konstanten wieviele Ergebnisse pro Seite gezeigt werden sollen, können wir uns eine Abfrage mit Offset und Limit zusammen bauen. Damit holen wir nur die Daten die wir anzeigen und die Funktion bleibt performant.

Paginator aufbauen
Zum Schluss bauen wir uns noch ein Paginator Array. Mit den Angaben Anzahl aller Datensätze, Ergebnisse je Seite und aktueller Seite ist das schnell kalkuliert.

Nehmen wir als Beispiel die Adresstabelle aus dem Artikel "flexible Queries":

public function listAction() {
    $page = 1;
    $itemsPerPage = 20;
    $name = null;
    $firstName = null;

    //Parameter abfragen
    if($this->request->hasArgument('page'){
        $page = intval($this->request->getArgument('page'));
    }
    if($this->request->hasArgument('filter'){
        $filter = $this->request->getArgument('filter'));
    }
    
    if ($filter[''name]) {
        $name = $filter['name'];
    else {
        $name = null;
    }

    if ($filter[''firstName]) {
        $firstName = $filter['firstName'];
    else {
        $firstName = null;
    }

    // Count results
    $countResults = $this->myRepository->countByFilter($name, $firstName);

    //fetch Data
    $offset = ($page -1) * $itemsPerPage;
    $limit = $itemsPerPage;
    $results = $this->myRepository->findByFilter($name, $firstName, $offset, $limit);

    if ($countResults > $itemsPerPage) {
        $toatalPages = ceil($countResults / $itemsPerPage);
        $paginator = $this->buildPagination($page, $totalPages);
    }

    $this->view->assign('results', $results);
    $this->view->assign('paginator', $paginator);
    $this->view->assign('filter', $filter);
}


In der privaten Funktion buildPagination bauen wir jetzt das Array für den Paginator auf:

private function buildPagination($page, $totalPages) {
    //Anzahl der Seiten die im Paginator angezeigt werden sollen:
    $pageLinks = 7;
    $i = 1;

    // case 1 
    // Es können alle Seiten dierekt in der Paginierung angezeigt werden
    // Paginierung: 1 | 2 | 3 | 4 | 5 | 6 | 7
    if($totalPages <= $pageLinks) {
        while ($i <= $totalPages) {
            $pagination[$i]['value'] = $i;
            if ($i == $actualPage) {
                $pagination[$i]['class'] = 'active';
            }
            $i++;
        }
        return $pagination;
    }

    // case 2
    // Die aktuelle Seite ist kleiner 4, die Paginierung beginnt mit 1
    // Paginierung: 1 | 2 | 3 | 4 | 5 | 6 | 7 | >>
    if($actualPage < 4) {
        while ($i <= 7) {
            $pagination[$i]['value'] = $i;
            if ($i == $actualPage) {
                $pagination[$i]['class'] = 'active';
            }
            $i++;
        }
        // link to last page
        $pagination[$i]['value'] = $totalPages;
        $pagination[$i]['class'] = 'last';

        return $pagination;
    }

    // case 3
    // Die aktuelle Seite liegt irgendwo in der Mitte
    // Paginierung: << | 5 | 6 | 7 | 8 | 9 | 10 | 11 | >>
    if($actualPage >= 4 && $actualPage < $totalPages - 3) {
        // link to first page
        $pagination[0]['value'] = 1;
        $pagination[0]['class'] = 'first';

        //beginn der Paginierung berechnen:
        $i = $actualPage - 3;
        while ($i <= $i + 7) {
            $pagination[$i]['value'] = $i;
            if ($i == $actualPage) {
                $pagination[$i]['class'] = 'active';
            }
            $i++;
        }

        // link to last page
        $pagination[$i]['value'] = $totalPages;
        $pagination[$i]['class'] = 'last';

        return $pagination;
    }

    // case 4
    // Die aktuelle Seite liegt unter den letzten 3
    // Paginierung: << | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
    if($actualPage >= $totalPages - 3) {
        // link to first page
        $pagination[0]['value'] = 1;
        $pagination[0]['class'] = 'first';

        //beginn der Paginierung berechnen:
        $i = $totalPages - 7;
        while ($i <= $totalPages) {
            $pagination[$i]['value'] = $i;
            if ($i == $actualPage) {
                $pagination[$i]['class'] = 'active';
            }
            $i++;
       }
       return $pagination;
    }
}

Das Fluid Template für den Paginator

<f:for each={results} as="result">
    <!-- Ausgabe der Liste -->
</f:for>

<div class="paginator">
    <f:for each={pagination} as="paginator">

        <f:if condition='{paginator.class}'>
            <f:then>
                <f:if condition='{paginator.class} == "active"'>
                     <span class='pagination-page'>{paginator.value}</span>
                </f:if>
                <f:if condition='{paginator.class} == "first"'>
                     <f:link.action action='list' arguments='{filter: filter, page: paginator.value}'>
                         <span class='pagination-page'><<</span>
                     </f:link.action>
                </f:if>
                <f:if condition='{paginator.class} == "last"'>
                     <f:link.action action='list' arguments='{filter: filter, page: paginator.value}'>
                         <span class='pagination-page'>>></span>
                     </f:link.action>
                </f:if>
            </f:then>

            <f:else>
                <f:link.action action='list' arguments='{filter: filter, page: paginator.value}'>
                   <span class='pagination-page'>{paginator.value}</span>
                </f:link.action>
            </f:else>

        </f:if>
    </f:for>
</div>

Weitere Artikel zu diesem Thema:

Empfehlenswerte Lektüre:

Linux-Kommandoreferenz

Jeder der TYPO3 auf einem Server einrichtet sollte auch die grundlegenden Linux Befehle fü die Shell kennen. Das Bucht führt übersichtlich durch den Dschungel der Befehle und erleichtert die Arbeit auf dem Server auch für Einsteiger.

Kommentare

keine Kommentare vorhanden


Kommentar verfassen

Die Email Adresse wird nicht veröffentlicht.