Jump to content

[SOLVED] Pagination links render but do not work.

Recommended Posts

Hey everyone,

I'm pretty experienced with pagination and haven't seen this before. I have my pages pulled using $pages->find, which is working fine however using renderPager() generates pagination where the links do not work. Here are some details.

  • All templates needing pagination have pagination enabled in the admin.
  • URL Segments are not enabled.
  • Clicking on the "Next" or numbered links merely reloads the current page.
  • The link href values are properly being output with the urls being /page2, /page3, /page4, etc.
  • Manually entering the paginated urls has the same effect of reloading the current page with no new content.
  • Pages are being returned from the ->find function properly and with the proper limit.

A few other details:

  • ProcessWire v3.0.98
  • Multi-language is enabled, 2 languages implemented.
  • Pagination does not work on either language
  • Have very few modules installed (few enough to list), none of which I could see interfering:
    • ProFields, ProDrafts, ListerPro, DB Backups, Cronjob DB Backup, Upgrades, Upgrade Checker, Force Password Change, Markup Sitemap XML

I'm stumped. For the sake of being overly-thorough, here's the code:

  $articleTemplates = [

  $searchParams = [
    'template=' . implode('|', $articleTemplates),
    'limit=' . $pages->get('template=template_news')->list_count

  $articles = $pages->find(implode(',', $searchParams));
  echo $articles->renderPager();


Share this post

Link to post
Share on other sites

So I figured out the source of the issue. I wrote some code that detects a user's preferred language either from their browser language setting, or from a cookie that is created when they have visited and chose a language last time.

If a preferred language detected and the current page URL does not match it, it will redirect to the same page but in the proper language.

My problem is finding a way to get the URL that includes the pagination to compare. Right now my idea is to use $input->pageNum to build the URL myself... is there a way to get the URL including the page number?

Lesson learned...

Share this post

Link to post
Share on other sites
1 hour ago, usualCommission said:

is there a way to get the URL including the page number?

I'm not 100% I understand your question. Maybe you can try combination of $input->pageNum and $pager->getURL()? E.g.:


Note the caveat in the $pager->getURL() method at the above link.

Could this topic be of interest?



Edited by kongondo

Share this post

Link to post
Share on other sites

Yeah, I'm not explaining my situation well enough and it's becoming a little more complex.

I'm working on abstracting localization to a class where one of the methods is used to redirect the user to their preferred language. That preferred language is either the language preference they have set in their browser, or a language cookie that was set last time they visited and selected a language via a select dropdown in the nav. That said, since the method is run on page load it will not have any access to specific pagination instances because they don't exist yet.

I read the link above and didn't see a solution that covers all of the bases and the module reference in a link to another post is no longer maintained, so I am going to write a custom implementation.

Here's my solution:

  • Language detection will be tied to a unique session variable.
  • On page load, the script checks for that session variable, if it exists- it exits because the language has been checked/redirected if necessary on ingress already.
  • If no language session variable exists, then compare the destination URL against the URL of that page for their preferred language.
  • If the URLs do not match then build a new URL
  • The destination URL is checked for page numbering using $input->pageNum(), if  > 1 then create a URL string for that. Any GET variables are extracted and rebuilt into a string- this preserves any possible incoming variables like UTM trackers.
  • Get localized URL for user's preferred language, re-add page number, re-add any GET variables that existed.
  • Set unique language session variable, then properly redirect to the localized page using the build URL.

I kind of wish that there was a built in method that could wrap most of this up and preserve URL details while redirecting to a given translated page, but this should work and also only redirect once.

I may be over-complicating this but it's what I've got. I really appreciate your help!

Share this post

Link to post
Share on other sites

Something like this would be the easiest way, I can think of, to do what you are doing. Redirect to a another language, including urlSegments, Pagenumber and optional QueryStrings;

if($user->language->isDefault) {
	$user->language = $languages->get("de");
	$session->redirect($input->url($withQueryString = true));


  • Like 2

Share this post

Link to post
Share on other sites

That sets the user language properly but getting the $input->url(true) still gets the non-localized version of the URL so it doesn't redirect to the translated page. It loops and fails the redirect.

Also the language move has been a little rough because using the code below seems to lead to a possible solution but is where I was hitting the paging/GET issues.

$languages->setLanguage(-lang str here-); // Also sets the language as a $user->language assignment does
$page->localHttpUrl($user->language); // Returns the proper localized URL, but does not include pagination or GET vars

I've seen many posts in the forums about redirection to a language and all of them use $page->localUrl($user->langauge) and none consider GET vars. Multi-language documentation says that the $page->localUrl() will automatically adjust to pagination but I haven't seen it. Would still have to manually build GET vars.


Share this post

Link to post
Share on other sites

How about getting the url-segments/page-num/get-vars suffix and then appending that to $page->localUrl?

$url_suffix = str_replace($page->url, '', $input->url(true));
$redirect_url = $page->localUrl() . $url_suffix;


  • Thanks 1

Share this post

Link to post
Share on other sites

Added that to a comparison and that did the trick! Here's the method after adding your trick:

private function doInitLocalization() {
  $page = wire('page');
  $user = wire('user');
  $input = wire('input');

  // Get/set user language from either browser or cookie
  $user->language = $this->getLangFromCookie() ?: $this->getValidBrowserPrefLang();

  $urlSuffix = str_replace($page->url, '', $input->url(true));
  $userUrl = $page->localUrl($user->language) . $urlSuffix;

  if ($_SERVER['REQUEST_URI'] !== $userUrl) {
    header("Location: {$userUrl}");

getLangFromCookie() checks if the user has visited previously and selected a language from a dropdown.
getValidBrowserPrefLang() gets the language pref sent by the browser, if it exists as a language in the CMS, returns the value.

By setting the language for the user this checks against what the browser request asked for/server is delivering vs. what the CMS knows it should be delivering. If they differ, then redirect.

This is executed in _init.php so any point of ingress is checked for url vs. preference.

Thanks @kongondo for introducing me to $input->url and the good idea for direction.
Thanks @Soma for concluding my head->desk marathon. Your solution is the simple one I couldn't see.


Share this post

Link to post
Share on other sites

When you change the $user->language, all following API returns stuff in that language also, the $page->url or $input->url. No need to do str_eplace on something already the same.

So if $this.>getLangFromCookie does return the language object then you can change it to this.

private function doInitLocalization() {
  $user = wire('user');
  $input = wire('input');

  // Get/set user language from either browser or cookie
  $language = $this->getLangFromCookie() ?: $this->getValidBrowserPrefLang();
  if($language !== $user->language) {
    $user->language = $language;


  • Like 1

Share this post

Link to post
Share on other sites

Good to know.

$this->getLangFromCookie() returns a string and is shared by other methods in the same/other classes. I could probably refactor it to work directly with the language object, but I'll have to come back to that sometime. Appreciate that info.

Share this post

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By MateThemes
      Hello everyone!
      I have a problem with pagination. I have following code:
      <div class="uk-section"> <?php $results = $pages->find("template=gallery, limit=10, sort=title"); $pagination = $results->renderPager(); echo $pagination; echo "<ul class='uk-pagination uk-flex-center'>"; foreach($results as $result) { echo "<li><a href='{$result->url}'>{$result->title}</a></li>"; } echo "</ul>"; echo $pagination; ?> </div> Which works fine. And this markup results in following html code:
      <div class="uk-section"> <ul class='uk-pagination uk-flex-center'> <li> <a href='/galerie-bisheriger-projekte/'>Galerie bisheriger Projekte</a> </li> <li> <a href='/galerie-bisheriger-projekte/galerie-1/'>galerie-1</a> </li> </ul> </div> But instead of "Galerie bisheriger Projekte" and "galerie-1" I want to have a number.
      And as last question, how can I add a previous and next button?
      Thanks for your help!
    • By Liam88
      Hi all,
      Quick question as I haven't found anything from my Googling. 
      I have a blog on the site which utilises pagination. On the standard blog page I have a custom header which has featured posts.
      Below that I then have recent posts like mosts blogs.
      Now if i click to page two or three I want the header to disappear and just show a continuation of the standard posts.
      I'm not sure how to go about this so any direction would be helpful.
    • By stanoliver
      Good morning everyone!
      I have a growing number of posts about cars, bikes, airplanes, etc. 
      The following code (below) just works fine and returns only the posts of the category=cars as I desired together with pagination.
      In my url I have for example /categories/cars/car1 or /categories/bikes/bike1
      I do want to filter my posts not only with ... category=cars ... but also with category=bikes or category=airplanes and at best:
      If my url is /categories/bikes/ then ... category=cars ... should be overwritten or replaced by ... category=bikes ... 
      If my url is /categories/airplanes/ ... then the filter should be ... category=airplanes ... (I know a work around by creating almost identical templates where I could just change the "category=cars" part of my code but that's comes of a prize by repeating a lot of identical code and is not a good habit). In the documentation I read something about the "has_parent" selector but I could not get to work it related to the urls mentioned above.
      <?php foreach ( $results = $pages->find('id>1, template=templateblogpost, category=cars, limit=5, sort=-postdate') as $post 😞?> <!-- Blog entry --> <div class="g8-card-4 g8-margin g8-white"> <!--<img src="/g8images/bridge.jpg" alt="Norway" style="width:100%">--> <div class="g8-container"> <h3><b><?= $post->title; ?></b></h3> <h5>Datum: <span class="g8-opacity"><?= $post->postdate; ?></span></h5> </div>   <div class="g8-container"> <p><?= $post->posteditor; ?></p> <div class="g8-row"> <div class="g8-col m8 s12"> <p> <a href="<?= $post->url; ?>"><button class="g8-button g8-padding-large g8-white g8-border"><b>Details lesen &raquo;</b></button></a> </p> </div> <div class="g8-col m4 g8-hide-small"> <!--<p><span class="g8-padding-large g8-right"><b>Comments &nbsp;</b> <span class="g8-badge">2</span></span></p>--> </div> </div> </div> </div> <!-- END BLOG ENTRIES --> <?php endforeach; ?>   <? echo $results->renderPager(array( 'nextItemLabel' => "rückwärts", 'previousItemLabel' => "vorwärts")); ?>
    • By happywire
      Using devilbox to develop locally.
      Installing the Beginner, Intermediate and Blank sites from the setup menu works perfect.
      The sites load, all pages load, can access the admin panel, all fine.

      However when installing the Multi-language site, the one I can pick during the setup procedure, things do not work.
      The English Home page works.
      The English About page,
      https://wiremultilang.loc/en/about/ tells me
      Same for the English Sitemap,
      https://wiremultilang.loc/en/site-map/ .
      I have allowed all cookies and can see them when checking in the browser cookies and site data, using Firefox 65.0.1 64-bit on Ubuntu 18.04.2 LTS.
      Clicking "German" on the Home page,
      https://wiremultilang.loc/de/ , shows me the German version of the 404 page.
      Clicking "Finish" on the Home page,
      https://wiremultilang.loc/fi/ , shows me the Finish version of the 404 page.
      What could be the issue here?
      Thank you for your guidance or any help you could supply.
    • By swampmusic
      Trying to figure out work flow for translators on a new website and have hit a brick wall.
      Site was launched in Spanish, now the translators want to add in other languages.
      I presumed that when you tick the "active" language checkbox on settings for the home page, then the new language would not appear on the public facing website, but translators would be able to work with the pages in the admin and view their work.
      Finally, once all translation had been completed, we could activate the language from the home page.
      I have searched thru the forums and found older articles from 2015 here.
      https://processwire.com/talk/topic/11100-disable-a-language-on-a-multilanguage-site/ https://processwire.com/talk/topic/10467-allow-translators-to-work-on-hidden-language/ This seems a really messy hack, or did i miss something ?
      Does anyone know if there has been an update within Processwire since 2015  to make this better/easier, or other articles explaining how to achieve it ?
      We were looking for a solution that the client can use from within Admin. Not via .htaccess or similar that would require tech skills.
      Many thanks for reading 🙂
  • Create New...