Jun 17, 2011

Creating pagers in D7

I've been working with Drupal for 3 years now (or something like that), and today I learned something I had never done before, but had used a lot: pagers. And all because we are training two new guys in the company (Seed Software), and one of them, not knowing about views yet, decided he wanted to create one. I did two things, first I told him views existed, and second, well, I decided I needed to know how to do it (who knows, one day I might need it, and I don't like not knowing).

I googled this and that and came up with a nice article which pretty much told me what to do, except for one thing, it didin't work for me, the pager was outputting nothing, and here is the trick.

theme_pager uses two global variables ($pager_page_array, $pager_total) to keep track of which pager to print, but, it doesn't keep track of which pager has been printed already, which means that if there are two or more pagers on a page, and you invoke theme('pager') without explicitly telling it which pager you want, it will always give you the first one.

The solution is simpler than it looks, (I assume you read the linked article). All you have to do is take note of how many pagers exist before you create yours, and capture that info to later on give that number to theme('pager') in order to get what you expect. Want to see the code?

  1. Keep track of the number of pagers

    <?php
      ...
      // Just before the query creation
      global $pager_total;
      $my_pager = count($pager_total);
      ...
      // Create your query
      $query = db_select('table', 'alias')
      ...
      ->extend('PagerDefault')
      ->limit(10)
      ...
      $results = $query->execute();
    
  2. Print your table, list, whatever
    Here I made one small change. I love render arrays, so I changed the code to make use of them.

    <?php
      $output['content'] = array(
        '#markup' => $your_content,
      );
    
  3. Print your pager
    To use render arrays the same way you use theme(), each of the parameters you would normally pass in the $variables array, you pass it as a property of the render array, in our case $variables['element'] will be "#element".

    <?php
      ...
      $output['pager'] = array(
        '#theme' => 'pager',
        '#element' => $my_pager,
      );
      return $output;
    

    And voilà.

A little explanation: $pager_page_array is always an array, can be empty, or can be, hum, not empty. Either way the count() function works. It wil return 0, if the array is empty, or 1 or more if it is not, and what a nice coincidence: our counter identifier (#element) will be exactly that number.

Also note that pagers will take the page number form the url, and you don't want all the pagers changing at the same time, this solves the issue.

Comments