A frequent need is to have an image or other chunk of content that can appear beside a node. That could be done many ways on the node itself, but what if you want the image to come from a shared pool? For that, we have fun with Views.

Required modules

  • Views
  • CCK
  • Nodereference (included with CCK)
  • Imagefield (if you're using images, as in this example)

Setup

What we're going to do is set up a node type to hold each sidebar chunk of content, then allow a node to pick which one should be used on it. For this example we're going to use a basic image, but any number of sidebar types are possible.

First, go to admin/content/types and create a new content type with Name "Sidebar image" and Type "sidebarimage". Set it to not promote to the front page, and to have no body. Save it. Then go to the Add fields tab and add a new Image field, named "Block image". Set the field to required. Any other configuration you want to do here is up to you.

The Sidebar image content type will be our holder for the "stuff on the side". Go ahead and create a node or two of that type, uploading an image for each one.

Now, edit the Page content type. Add a new Node Reference field to it called "Side block". Set the Widget to "Select list". Restrict the field to just "Sidebar image" content types, and save it. You can make the field required or not. Now, go to the "Display fields" tab on the Page content tyep and set the Block image field to hidden on both teaser and full view.

Now add or create a few Page nodes. You'll see a select box that lists all of the Sidebar image nodes in the system. Simply select one as desired. When you save the node you won't see anything different, but you should see that information saved if you edit the Page again.

The view

Now that we have al of our data setup, it's time to build the blocks that will pull it in. The view is actually quite simple.

Create a new View, called sidebar_image. Don't provide a Page for it. Instead, just provide a Block. Set the View type to List View, and the Nodes per Block to 1. Under Fields, add a single field: "Image: Block image", and set its handler to Not group multiple values.

In Arguments is where we put the magic. Create a single argument for Node: ID, and set the Default value to Use Empty Text. Now expand the Argument Handling Code fieldset, and insert the following code (not including the PHP tags):

$args = array();
if (arg(0) == 'node' && is_numeric(arg(1))) {
  $node = node_load(arg(1));
  $field = array_rand($node->field_side_block);
  $args[0] = $field['nid'];
}
return $args;

(Note that normally node_load() is an expensive operation, but we're loading the node being shown on the the current page. That means it's alread been loaded and cached, so it's very cheap to grab it.)

If you named the field something other than side_block, you will need to reference that field accordingly. Note that we're randomizing the field in order to easily handle the case where you set the node node reference field to be multi-value, in which case you can specify multiple side images to be selected at random. Sweet!

What this does is tell the View to pull all nodes that have a specific nid, that is, the nid specified by the node reference field on the current page. If there isn't one specified, we simply show the empty text for the block instead (which by default is nothing, so the block does not apear).

As an extra bonus, set the Sort order on the View to Random. Combined with not grouping multiple values, it means each individual Sidebar image node can have multiple images on it (multi-value field), and one will be chosen at random there, too.

Now, go to admin/build/block and enable the Block you just created. It should now show up next to the Pages you edited before, showing the image. Spiffy! if you don't like the way the block is laid out, simply use the Views Theme Wizard to create the necessary template file for that View and style it to your tastes.

Going further

If you want to show more than just the image field in the block, simply add additional fields to the Sidebar image content type and then pull them as well in the View. Add theming to taste.

For even more fun, you can group Sidebar image nodes into taxonomy categories and create selective pools using a View. Then, have the node reference field use that View as a source instead of all Sidebar image nodes, and add multiple node reference fields, one for each category/pool.

Comments

psheridan’s picture

I've followed your instructions above and set m block to show 3 nodes and am getting the following sql error:

user warning: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'LIMIT 0, 3' at line 1 query: LIMIT 0, 3 in C:\ps_projects\ps_drupal\includes\database.mysql.inc on line 172.

After some investigation, it seems the 'empty text' setting is at least contributing to the error...

586’s picture

On implementing the above almost exactly (my field names are obviously different), I found that the block did not show up on pages with attached images, and on those without it generated an error.

I can just about follow PHP syntax (a combination of half-remembered C operators and working with drupal for five months :) ) so on a hunch, and because the error mentioned the array_rand() function I changed the offending line to:

$field = $node->field_side_block[0];

This seems to have done the trick. The article above sort of explains why picking a single NID at random is necessary, but as my node reference field can't have multiple values I think I'm O.K. (?)

Just out of interest, If one did require more than one image from a node reference field with multiple values, does anyone have any ideas as to how that could be accomplished? Some kind of loop perhaps?

askibinski’s picture

Indeed, if you need multiple images, the code above needs some tweaking as it didn't work for me with multiple referenced images from a node.

I just spend a couple of hours after I finally realized that you need to return all the referenced id's in one $arg[0]. At first i returned an array with $arg[0] being the first referenced image, $arg[1] the second, and so on. That doesn't work - it will only show you the first image.

This is the code that does work:

$args = array();
if (arg(0) == 'node' && is_numeric(arg(1))) {
  $node = node_load(arg(1));
  foreach($node->field_side_block as $field) {
  	// ids is the array with the referenced image id's
  	$ids[] = $field['nid'];
  }
 $ids= implode('+', $ids);
}

return array($ids);

The key to succes is having the values combined with '+'.

Albert Skibinski - Homepage

Leahcim’s picture

Has anyone done this in DP7?

/mike

Ars’s picture

Would love to see this for D7, too... any luck?

Gaperville’s picture

Me too, on D7 as this is a little over my head w/ 7 changed.

Gaperville’s picture

YES!

The image block Mod is working for me