Query Loops

Pagination

Add paginate to a query when a list should be split across multiple WordPress pages instead of showing every matching post at once.

Basic Shape#

phpresources/views/index.php
{{ query:posts limit="12" paginate }}  <article>    <h2>{{ title }}</h2>  </article>{{ /query:posts }}{{ pagination }}  <a href="{{ prev_url }}">Previous</a>  <span>Page {{ current_page }} of {{ total_pages }}</span>  <a href="{{ next_url }}">Next</a>{{ /pagination }}

What Each Part Does#

The opening query controls what gets listed and how many items appear on each page:

php
{{ query:posts limit="12" paginate }}

query:posts asks WordPress for normal blog posts.

limit="12" means 12 posts per page when paginate is present. Page 1 shows the first 12 matching posts, page 2 shows the next 12, and so on.

paginate tells TemplateX to use the current WordPress page number and prepare pagination values for the {{ pagination }} block that follows.

For paginated lists, always use limit. Without limit, TemplateX asks WordPress for all matching posts, so there is usually only one page to paginate.

The pagination block reads the most recent query that used paginate:

php
{{ pagination }}  <a href="{{ next_url }}">Next</a>{{ /pagination }}

{{ pagination }} gives you values. It does not create buttons, wrappers, classes, disabled states, or page numbers for you. That keeps the HTML under your control.

On the first page, {{ prev_url }} is empty. On the last page, {{ next_url }} is empty.

Use {{ if }} when you only want to print a link when its URL exists:

php
{{ pagination }}  {{ if prev_url }}    <a href="{{ prev_url }}">Previous</a>  {{ /if }}  <span>{{ current_page }} / {{ total_pages }}</span>  {{ if next_url }}    <a href="{{ next_url }}">Next</a>  {{ /if }}{{ /pagination }}

The pagination block does not create page-number links by itself. That keeps the HTML theme-owned and makes the first version easier to control.

Count Example#

If 37 posts match this query:

php
{{ query:posts limit="12" paginate }}

Then the pagination values work like this:

ValueOn page 1
{{ current_page }}1
{{ total_pages }}4
{{ total_items }}37
{{ prev_url }}empty
{{ next_url }}URL for page 2

{{ total_items }} is the total number of posts that matched the query before WordPress split them into pages. It is not the number of posts printed on the current page. In this example, page 1 prints 12 posts, but {{ total_items }} is still 37.

Filters still count. If the query is filtered to one category, {{ total_items }} is the total number of matching posts in that category before pagination.

Available Values#

These are value tags. They are not paired tags.

ValueMeaning
{{ prev_url }}URL for the previous page, or empty on the first page.
{{ next_url }}URL for the next page, or empty on the last page.
{{ current_page }}Current page number, starting at 1.
{{ total_pages }}Number of pages WordPress found for this query after applying limit.
{{ total_items }}Number of matching posts before the current page slice is applied.

Page-number loops and ellipses are not part of the minimal pagination syntax yet.