Paginating Database Results
When developing web applications, you often encounter the requirement to limit the number of listed items per page, a technique known as pagination.
Let's start from a state where we list all data without pagination. For selecting data from the database, we have an
ArticleRepository
class. Besides the constructor, it contains a findPublishedArticles
method that
returns all published articles sorted descending by publication date.
In the presenter, we then inject this model class. In the render method, we retrieve the published articles and pass them to the template:
The default.latte
template will then take care of listing the articles:
This way, we can list all articles, but this becomes problematic as the number of articles increases. At that point, implementing a pagination mechanism becomes useful.
This mechanism divides all articles into several pages, and we only display the articles belonging to the currently selected page. The total number of pages and the division of articles are calculated by the Paginator utility based on the total number of articles and the desired number of articles per page.
In the first step, we'll modify the article retrieval method in the repository class so it can return articles for just one page. We'll also add a method to get the total count of articles in the database, which is needed to configure the Paginator:
Next, let's modify the presenter. We'll pass the current page number to the renderDefault
method. If this number
isn't part of the URL, we'll set a default value of 1 (the first page).
We'll also extend the render method to create and configure a Paginator instance and select the appropriate articles for
display in the template. The modified HomePresenter
will look like this:
The template now iterates only over the articles for the current page. We just need to add the pagination links:
This completes the pagination implementation using the Paginator. If you use Nette Database Explorer instead of Nette Database Core as your database layer, you can implement pagination even
without using the Paginator utility directly. The Nette\Database\Table\Selection
class includes a page() method that incorporates the
pagination logic.
With this approach, the repository will look like this:
In the presenter, we don't need to create a Paginator instance. Instead, we'll use the page()
method provided by
the Selection
object returned from the repository:
Since we are no longer passing the Paginator object to the template, we need to adjust the part that displays the pagination links:
This way, we've implemented the pagination mechanism without explicitly using the Paginator utility.