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_page, 0, $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.

Comments

Awesome - works perfectly, thanks for the additional tutorial, couldn't have come at a better time!

Excellent tutorial! Very well explained and easy to implement.

Thanks a lot!

Thanks for this great tutorial.

Perhaps it's a good idea to add the order criterion "ORDER BY i.delta" to $sql.

Than the gallery grid will use the list order.

dukat, good idea, I hadn't thought about any ordering issues.

Hey James, sent you an email about Drupal image gallery stuff 15.4.2010 but did not hear from you back?

Just trying to make sure you got my email :)

To which email address? I haven't got any emails about Drupal on 15.04.2010

Hey James, where can i send you email to?

I tried to send it to James Tombs Google-profile cos dont have your email addy.

Ah right, it wasn't forwarded on, I use my gmail account to forward email to another account but this one didn't come through.

I am a newbie for Drupal but I love these tutorials.
I created a few albums (5) but I dont want the album covers to show if you open the album. At the moment the album cover is also the first thumb shown in the opened album.
Thanks for your help!!

One more question, for the albums I want number of colums 3 but for the album details I want more colums, 5 for example. How can I do this?

Never mind my last question, I found the solution.
Still looking for the album cover problem...

If you always used the first image as the album cover, in the code you could use unset() to remove the first image from the array.

Where in the code should I use this and how?

Line before $count, write unset($node->field_images[0]);

If I write unset($node->field_images[0]); before $count, the album cover is shown as last pic in the album details

Change the view to use the first image of the gallery. You would also need to change the SQL queries to ignore the album cover.

Fantastic tutorial James! This has helped me get my first gallery live!

Just wondering - is it possible to create sub gallery's using this method, also maybe even dedicated user 'areas' to upload their own photographs?

It would be nice if you had the option of selecting a gallery for the photo(s) to go into when you upload them.

Thanks!

Great tutorial!

Ian,

I have not tried it but handling these galleries through taxonomy temrs from this point would be easiers. We can now assign terms to these galleries and can create hirarchy...just a thought..

Navnish

Fantastic tutorial. Worked like a charm, was wondering if the hyperlink to "download image" was possible to add in the lightbox 800x600 display? I thought it appeared at one point, but no longer.

Good one James, you are the king of tutorial for drupal views galleries!

I'm getting this error using your code:

user warning: Table 'cupramontana1.content_field_images' doesn't exist query: SELECT COUNT(f.fid) FROM content_field_images i JOIN files f ON f.fid = i.field_images_fid WHERE nid = 2 in C:\virtual G\Cupramontana 1\drupal\sites\all\themes\garlanddpm\node.tpl.php on line 24.
user warning: Table 'cupramontana1.content_field_images' doesn't exist query: 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 = 2 LIMIT 0, 9 in C:\virtual G\Cupramontana 1\drupal\sites\all\themes\garlanddpm\node.tpl.php on line 24.
warning: Invalid argument supplied for foreach() in C:\virtual G\Cupramontana 1\drupal\sites\all\themes\garlanddpm\node.tpl.php on line 35.

The only difference in my album is that i added a date field. Can it be the couse of the error?
I double checked that field name (field_images) is correct.

PS: of course it is not working!

On your image field have you selected it to be more than 1 image?