Creating a grid of images for an album in Drupal 6 with pagination

Following on from the original tutorial on creating a grid of images for an album in Drupal 6, a few people asked how to add pagination on to this for large albums.

Unfortunately from what I can tell Drupal's pagination function only works with SQL queries so we are unable to use the existing data available in the node object. But due to Drupal's nice database schema, it is very simple to write some simple SQL to give us the pager.

Below is the full code and below the code I will explain what each part does.

<?php
$count 
count($node->field_images);
if (
$count 0):
  
$images_per_page 9;
  
$sql "SELECT f.fid, i.field_images_data, f.filepath FROM content_field_images i JOIN files f ON f.fid = i.field_images_fid WHERE nid = "$node->nid;
  
$count "SELECT COUNT(f.fid) FROM content_field_images i JOIN files f ON f.fid = i.field_images_fid WHERE nid = "$node->nid;
  
$query pager_query($sql$images_per_page0$count);
  while (
$data db_fetch_object($query)) {
    
$images[$data->fid] = array(
      
'filepath' => $data->filepath,
      
'data' => unserialize($data->field_images_data),
    );
  }
  
$rows = array();
  
$images_per_row 3;
  
$i 0;
  
$row 0;
  foreach (
$images as $image) {
    
$rows[$row][$i] = '<a class="gallery-thumbs" title="'htmlspecialchars($image['data']['description']) .'" rel="lightbox[photo_gallery-'$node->nid .']" href="'imagecache_create_url('lightbox'$image['filepath']) .'">'theme('imagecache''thumbnail'$image['filepath'], $image['data']['title'], $image['data']['title']) .(trim($image['data']['description']) != '' '<br /><small>'$image['data']['description'] .'</small></a>' '');
    
$i++;
    if (
$i == $images_per_row) {
      
$row++;
      
$i 0;
    }
  }
?>
  <table class="views-view-grid">
    <tbody>
      <?php foreach ($rows as $row_number => $columns): ?>
        <?php
          $row_class 
'row-' . ($row_number 1);
          if (
$row_number == 0) {
            
$row_class .= ' row-first';
          }
          elseif (
count($rows) == ($row_number 1)) {
            
$row_class .= ' row-last';
          }
        
?>
        <tr class="<?php print $row_class?>">
          <?php foreach ($columns as $column_number => $item): ?>
            <td class="<?php print 'col-'. ($column_number 1); ?>">
              <?php print $item?>
            </td>
          <?php endforeach; ?>
        </tr>
      <?php endforeach; ?>
    </tbody>
  </table>
  <?php print theme('pager', array(), $images_per_page0); ?>
<?php 
else: ?>
  <p>No images in album</p>
<?php endif; ?>

First thing we do is check to see if there are any images. Rather than doing a SQL query to get the result, I have chosen to use the already existing array of images in the node object.

<?php$count count($node->field_images);?>

Then as before we check to make sure we have images, then create our query to generate the pager.

<?php$images_per_page 9;
$sql "SELECT f.fid, i.field_images_data, f.filepath FROM content_field_images i JOIN files f ON f.fid = i.field_images_fid WHERE nid = "$node->nid;
$count "SELECT COUNT(f.fid) FROM content_field_images i JOIN files f ON f.fid = i.field_images_fid WHERE nid = "$node->nid;
$query pager_query($sql$images_per_page0$count);
while (
$data db_fetch_object($query)) {
  
$images[$data->fid] = array(
    
'filepath' => $data->filepath,
    
'data' => unserialize($data->field_images_data),
  );
}
?>

In the query, we are gathering the file id (fid) of each individual image, the field_images_data which is a serializd array of the title, description and alt text of the image from when it was uploaded and the filepath of the image. The count isn't necessarily needed, but I have found the pager can act oddly when the $count part of pager_query() is missing.

pager_query() also requires 2 other elements. The first after $sql, is the amount of rows to be taken out the database. The next number is the element number. This is needed for pages with multiple pagers on them. If you have got multiple pagers and experience trouble then you will need to change this.

Then from this we recreate the $images array that we had before, although it is missing some information which is provided through the $node object, it provides everything that we need to display the image on the page.

The whole table HTML section remains untouched, but it is followed by an extra line:

<?php print theme('pager', array(), $images_per_page0); ?>

This prints out the Drupal pager below out table of images. This can be used multiple times on a page, so you can have some pagination below and above the table of images.

If the page you are displaying the albums on already has pagers, you may need to change the 0 in both the theme_pager() and pager_query().

You should now have a fully working grid with pagination.

Edit: As pointed out by dukat in the comments, you can change the original SQL query to the following to keep the images in the order defined in the node.

<?php$sql "SELECT f.fid, i.field_images_data, f.filepath FROM content_field_images i JOIN files f ON f.fid = i.field_images_fid WHERE nid = "$node->nid ." ORDER BY i.delta ASC";?>

Obviously you can change the order between ASC or DESC.