Paginierung in Symfony 4 mit dem KnpPaginatorBundle

Dieser Artikel ist zuerst bei ourcodeworld.com erschienen. Mir hat der Artikel gut gefallen, weshalb ich ihn übersetzt und ggf. um eigene Erfahrungen und Tipps erweitert habe. Hier gehts zum Original Artikel
1 ... 4 5 6 ... 12

Performanz ist das A und O einer Web Anwendung. Vor allem bei großen Datenmengen ist die Implementierung einer Paginierung unabdingbar. So kann der Benutzer durch mehrere Datensätze navigieren, ohne dabei tausende Einträge auf einmal laden zu müssen.

In Symfony 3 ist das KnpPaginatorBundle die beste Lösung, wenn du mit Doctrine arbeitet. Die Dokumentation in Zusammenarbeit mit Symfony 4 lässt allerdings zu wünschen übrig, weshalb viele Entwickler aus Frustration zu anderen Paketen greifen.

Aber keine Sorge, die Installation dieses Bundles ist eigentlich kinderleicht, wenn du diesem Artikel folgst. Also los gehts.

Das KnpPaginatorBundle kann folgendes paginieren:

  • array
  • Doctrine\ORM\Query
  • Doctrine\ORM\QueryBuilder
  • Doctrine\ODM\MongoDB\Query\Query
  • Doctrine\ODM\MongoDB\Query\Builder
  • Doctrine\ODM\PHPCR\Query\Query
  • Doctrine\ODM\PHPCR\Query\Builder\QueryBuilder
  • Doctrine\Common\Collection\ArrayCollection
  • ModelCriteria
  • array mit Solarium_Client und Solarium_Query_Select

In diesem Artikel zeige ich dir wie du das bekannte KnpPaginatorBundle in deinem Symfony 4 Projekt installierst.

1. Installation und Konfiguration vom KnpPaginatorBundle

Das KnpPaginatorBundle ist ein SEO freundlicher Symfony-Paginator, der euch alles paginieren lässt. Dieses Werkzeug:

  • benötigt keine großartige Initialisierung
  • kann auf jegliche Art und Weise angepasst werden: View, Event Subscriber etc.
  • bietet die Möglichkeit eine benutzerdefinierte Filterung hinzuzufügen, die Sortierung beruht auf Request Parametern
  • ist lediglich verantwortlich für den Paginierungs View

Um das Paket in eurem Symfony Projekt zu installieren, kannst du die aktuellste Version mit dem folgenden composer Befehl herunterladen:
composer require knplabs/knp-paginator-bundle

Damit installierst du das Bundle und registrierst es in der app/config/bundles.php. Für weitere Informationen schau dir das offizielle Repository auf GitHub an.

Nach der Installation musst du nur noch die Datei app/config/packages/knp_paginator.yml anlegen. Diese enthält die gesamte Konfiguration des Pakets. Du kannst dich beim Konfigurieren an der Dokumentation orientieren:

# config/packages/paginator.yaml
knp_paginator:
    page_range: 5 # number of links showed in the pagination menu (e.g: you have 10 pages, a page_range of 3, on the 5th page you'll see links to page 4, 5, 6)
    default_options:
        page_name: page # page query parameter name
        sort_field_name: sort # sort field query parameter name
        sort_direction_name: direction # sort direction query parameter name
        distinct: true # ensure distinct results, useful when ORM queries are using GROUP BY statements
        filter_field_name: filterField # filter field query parameter name
        filter_value_name: filterValue # filter value query paameter name
    template:
        pagination: '@KnpPaginator/Pagination/sliding.html.twig' # sliding pagination controls template
        sortable: '@KnpPaginator/Pagination/sortable_link.html.twig' # sort link template
        filtration: '@KnpPaginator/Pagination/filtration.html.twig' # filters template

Speicher die Datei ab und lösche falls nötig den Cache.

2. Paginator im Controller konfigurieren

Sobald das Plugin installiert und konfiguriert ist, ist die Nutzung ganz einfach. Du musst nur sicherstellen, dass dein Controller die Symfony\Bundle\FrameworkBundle\Controller\Controller Klasse erweitert. Diese Klasse ermöglicht dir sämtliche Services (bspw. den Entity Manager) via get Methode abzurufen. Initiiere den Paginator und speichere ihn in einer Variable. Dann musst du ein Doctrine Query (Vorsicht: kein Ergebnis wie bspw. mit getResult()) erstellen und die paginate Methode vom Paginator mit den folgenden drei Parametern aufrufen:

  1. Dein Doctrine Query
  2. Die aktuelle Seite, die durch den GET Parameter „page“ definiert wird. Setze die erste Seite als Fallback Wert, wenn der Parameter nicht gesetzt ist.
  3. Die Anzahl an Elementen pro Seite.

In der View musst du dann nur noch über den Rückgabe-Wert der paginate Methode iterieren. Dieses Objekt enthält die Ergebnisse deines Queries mit dem angegebenen Limit und ein paar anderen nützlichen Methoden.

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use App\Entity\Appointments; // Include paginator interface
use Knp\Component\Pager\PaginatorInterface;

class DefaultController extends AbstractController {
    // Include the paginator through dependency injection, the autowire needs to be enabled in the project
    public function index(Request $request, PaginatorInterface $paginator) {
        // Als erstes holen wir uns den Entity Manager
        $em = $this->getDoctrine()->getManager();
        
        // Damit holen wir uns ein Repository, in unserem Fall eine Termin Entität namens Appointments
        $appointmentsRepository = $em->getRepository(Appointments::class);
                
        // Finde alle Einträge aus der Termin Tabelle und filtere das Query nach deinen Wünschen
        $allAppointmentsQuery = $appointmentsRepository->createQueryBuilder('p')
            ->where('p.status != :status')
            ->setParameter('status', 'canceled')
            ->getQuery();
        
        // Jetzt paginieren wir die Ergebnisse des Queries
        $appointments = $paginator->paginate(
            $allAppointmentsQuery, // Doctrine Query, nicht Ergebnisse
            $request->query->getInt('page', 1), // Page GET Parameter
            5 // Elemente pro Seite
        );
        
        // Rendert die Twig View
        return $this->render('default/index.html.twig', [
            'appointments' => $appointments
        ]);
    }
}

Die Termine werden mit dem Namen appointments an die Twig View weiter gegeben und können dort, wie gewohnt, referenziert werden.

3. Paginator in der Twig View erstellen

Wir haben nun also das Paginierungs-Objekt an die Twig View weitergegeben. Diese rendert unsere Paginierung und die dazugehörigen Einträge. In unserem Beispiel sieht die Twig View folgendermaßen aus:

{# ./templates/default/index.html.twig #}
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>My Application</title>
    </head>
    <body>
        <ul>
        {% for appointment in appointments %}
            <li>
                {{ appointment.title }}
            </li>
        {% endfor %}
        </ul>
        
        <div class="navigation">
            {{ knp_pagination_render(appointments) }}
        </div>
    </body>
</html>

Dieser Code generiert eine Liste mit fünf Einträgen pro Seite, wie im Controller angegeben. Die knp_pagination_render Funktion rendert die Paginierung mit allen verfügbaren Seiten. Beim Klick auf einen Seitenlink wird die aktuelle URL (auch deren Query Parameter) um die Paginator-Parameter (größtenteils „page“) erweitert. Damit weiß der Controller welche Elemente er als nächstes ausgeben muss.

Wenn du dein Symfony-Projekt mit git versionierst und immer wieder die selben Befehle fürs Deployment ausführen musst, dann ist mein Artikel über Deploy Skripte vielleicht auch etwas für dich.

1 Kommentar zu “Paginierung in Symfony 4 mit dem KnpPaginatorBundle

  1. Pingback: How can I use a http Client in Symfony while working with KnpPaginator Bundle? – Ask your php questions

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert