New Podcast

Posted Tuesday, July 27 at 2:29 pm

Ryan Price and Mike Anello recently talked with Jacob Redding (jredding), author of Beginning Drupal as well Treasurer and Interim General Manager of the Drupal Association.

Download Podcast 41
DrupalEasy_ep41_20100727.mp3
Syndicate content

NEWSLETTER

Stay informed on our latest news!

Syndicate content

Testimonial

Thanks for a well-organized, straightforward, and information-packed workshop. Thank you for covering the basics so concisely and clearly. It was a good experience for me. I'm looking forward to taking more workshops from DrupalEasy.

Who are we?

DrupalEasy is the collective expertise of Ryan Price and Michael Anello, who joined forces to provide training and consulting services worldwide. Read all about them and what they can do.

What is Drupal?

Drupal is a free, super-powerful content management system for sites that require information posting and collection, including blogs, forums, videos, photos, and databases of information. We think it is the best platform available. Here's why...

Why Drupal?

More and more savvy organizations are going with Drupal for content management, and its no mystery why. It’s free, flexible, and easy to maintain for small or large volume sites. Learn more...

Using Views 2 and Drupal 6 to Create a Related Pages Block

Average: 4.4 (118 votes)

Today's question comes from Dale at NFi Studios in Orlando, FL - my home town:

Essentially:, what i'm trying to do is
1. Determine the current nodes taxonomy terms
2. Determine all other pages that share taxonomy terms
3. Display the title (and link) to those pages in a block

Using Drupal 6.2 and Views - Looked at a few modules, but nothing quite
exact - Reviewing some module snippets right now to see if I can
potentially use an argument to do it.

Dale asks a good question: before the release of Panels for Drupal 6, how can one associate a block with the node it's being displayed next to without writing a custom module? It turned out to be simpler than I expected. I actually started going down the path of custom modules, but in the process I noticed that Views still have the ability to load Arguments with PHP Code, and my solution wrote itself.

Dale, you're already pretty far along: you know you need a view inside of a block, displayed based on taxonomy terms to relate the view to the pages. Instead of giving you a full-fledged tutorial on Views and the Black Arts, you'll be getting a recipe that outlines how to create the block in question.

First, you'll want to download and install Views 2 for Drupal 6, currently in Beta 4, then enable the module under admin/build/modules - remember that Views also requires you to activate Views UI, as the views.module is more of an API for creating views.

The first step in your new Views journey is to Add a new view at admin/build/views. Just click on the tab near the top of the screen:
add a view

Now you'll be asked to name your view something computer-friendly - in this case you'll name it related_by_term:
Name your view

Once you click through, you'll be presented with the granddaddy of all administration screens, but don't be afraid, things move pretty quickly in here if you know what you're doing. Notice the Orange text in the top right: New view. Until you push the Save button at the bottom of the screen, all you hard work could be lost, and especially don't forget to save once you've finished configuring your view.
Main views screen

I want you to skip all those fancy options and dive right in: you've got to eat your vegetables, so let's get the hard part over with and set up the arguments:
Add an argument

Arguments were the most powerful (and hardest to understand) feature of the old Views - think of this as the WHERE clause of your SQL statement. Your first and only argument will be keyed off of a Taxonomy Term ID:
taxonomy argument type

Since you don't have Panels at your disposal, you'll need to specify a Default Argument. There are several (powerful) ways to accomplish this, but in your case, resort to tried-and-true PHP Code. The code displayed here loads the object for the current $node (if any) and concatenates a list of all the Term IDs on that node, then returns the string to Views in the format 1+2+3, just like the arguments on taxonomy/term pages:
use PHP to specify the default argument

In order to activate this muitliple-term-driven argument scheme, you need to check a few boxes below the PHP code. The first sets up the fact that you can use the 1+2+3 format, and the second removes duplicate entries that have more than one term. Make sure you read the warnings about performance; if you don't use multiple taxonomy terms, leave this box unchecked. You can proceed by clicking the Update button:
Allow multiple terms, reduce duplicates

At this point, you'll see an error message inviting you to extract some fields in your view, which is set up to display fields by default. If you wanted to view full nodes or teasers, you could change that option and be safe, but the block you want to build needs titles that link to the node:egads, an error message

Now you want to tackle adding fields to your view. This is the building block of any view, analogous to the SELECT part of a SQL statement:
Add a field

You should recognize this next picture, because it's very similar to the way you chose your argument type, and how you'll choose your filter in the future. Use the Add button to move to the next screen:
you want to see the node title

If you don't delete the word "Title" in the Label text box, it will appear next to all your links. There are some situations where this is wanted; yours is not one of them. You also said you wanted the titles to be links, so check that box:remove the Label and enable links

At this stage, you should be able to get a working preview of your view. Just type a number or a 1+2 in the arguments area and push the button to trigger the AJAX. That blue text is your view, and there's also some geeky information below. Notice that currently "This display has no path"; that's OK, you want a block:
use some arguments to get a live preview

At this point, you still haven't told Views that you want your view to be a block, so make sure you choose block from the drop-down in the main interface. If you're working strictly with Page nodes, you may also want to throw a filter on your view to limit the results. You also should never forget the all-important Save button:filter and save your view

The last thing you need to view is activate your block on admin/build/block (you may need to use block visibility rules, but that's another tutorial), and finally visit one of your Taxonomy-tagged pages to see if your other taxonomy-tagged pages shows up. If you've followed all the steps here, everything should be a snap. Maybe the best feature about your new block is the handy links that pop up when you mouse over your new block (if you have administer views access, at least):
your finished block with edit links

Well Dale, I think that should just about answer your question. Since this is my first Drupal 6 tutorial, I'll have to say, this was a lot more fun for me than I'm sure the last few days have been for you. Wave hello to Corey and Sterling and Derek and Daniel and the other NFi folks, and I hope I was able to save you some precious time with this post.

Trackback URL for this post:

http://drupaleasy.com/trackback/6

149 comments

user picture
ryanprice wrote 2 days 5 hours ago

Martijn, There is probably an

Martijn,

There is probably an easier way to do this with a contributed module, or possibly Panels context.

A quick Google search returned:
http://drupal.org/project/related_terms
http://groups.drupal.org/node/10829
http://davidherron.com/content/improving-navigability-drupal-taxonomy-hi...

user picture
ryanprice wrote 2 days 5 hours ago

Leonardo, When setting up an

Leonardo,

When setting up an Argument, there is an area called "Title". Type your text, but instead of "X", put the characters "%1". This is a placeholder for whatever the argument returns. In this case it would be "Other nodes in category Sheep", where you entered %1 in the place of Sheep.

Enter it on this screen, in the Title box.
use PHP to specify the default argument

Leonardo Giordani wrote 3 days 10 hours ago

Thank you very much. Just a

5

Thank you very much. Just a question: how can I set the title of the block to something related to the view argument? I would like to set it as "Other nodes in category X". I tried to preprocess the block through template.php but I lost myself in the API. Thanks

Martijn wrote 4 weeks 4 days ago

Hi Great tutorial! How could

Hi Great tutorial!
How could I build a sort of related terms block using this method on taxonomy/term/x page (not on nodes pages) of "foreign" vocabulary?

Logic something like this:
1.Get the x out of the url (url= taxonomy/term/x)
2. Get the terms out of all the nodes shown on taxonomy/term/x page
3. Show the terms from a specific other vocabulary (not the one from the url).

Would this be doable using above method. What would be the phpcode please?

Thanks a lot in advance for your reply!
Greetings,
Martijn

Brad wrote 5 weeks 5 days ago

I had a problem using gost_

I had a problem using gost_ "What if you want to show only" comment below for my site. The code worked great expect that the block I was using it for was isolated to a single Content Type. Here is his original code:
$node = node_load(arg(1));
if ($node) {
$terms = taxonomy_node_get_terms_by_vocabulary($node, 6);
  foreach ($terms as $tid => $term) {
    $tids[] = $tid;
  }
  return implode ("+", $tids);
}
return false;
Now if I needed this on every page then I wouldn't have had any problem. But I needed it on only a single Content Type page. Now I already had the region isolated to that Content Type, but still it was producing an error. The problem I was having was it was producing this error on every other page that did not have a term. "warning: implode() [function.implode]: Invalid arguments passed in /home/hpelive/public_html/sites/all/modules/views/plugins/views_plugin_argument_default_php.inc(48) : eval()'d code on line 6." Now it was discussed below about fixing that by adding a term to each node but that is not really logical if you have many node as some describe. So my fix was to isolate that in the Views Argument based on Content Type. So I replaced Line 2: if ($node) { with this: if ($node->type == 'episode') where "episode" is my Content Type. So my entire code looked as follows:
$node = node_load(arg(1));
if ($node->type == 'episode') {
$terms = taxonomy_node_get_terms_by_vocabulary($node, 3);
  foreach ($terms as $tid => $term) {
    $tids[] = $tid;
  }
  return implode ("+", $tids);
}
return false;
Not the most complicated of fixes but hopefully it will be able to help someone else.
Ann wrote 5 weeks 6 days ago

Fantastic tutorial and

5

Fantastic tutorial and comments...what a lifesaver

phobia flying wrote 6 weeks 3 hours ago

One nice thing to call out

One nice thing to call out might be the 'Theme: Information' link which tells you which templates the styles will be using, and gives you a full list of names that you can choose from for your own template; and also will show you the default template so you don't even have to go and seek out the original .tpl.php file if you want to look at it.

negative wrote 7 weeks 6 days ago

Hi! The big problem is when

3

Hi! The big problem is when you have to negate the term ID argument... how could that be possible??????????

Paul wrote 9 weeks 4 days ago

I have to echo my thanks.

I have to echo my thanks. The post is almost two years old and yet so valuable!

Ronan Keating wrote 9 weeks 6 days ago

This is fantastic thanks,

5

This is fantastic thanks, works a dream.

user picture
ryanprice wrote 11 weeks 1 day ago

@sukant The reason why this

@sukant

The reason why this happens is because the paths that get reserved by views allow for arguments to be passed.

A workaround for this is to add an argument to the view in question, and then add some validation. One of the options in validating an argument is to return a 404 / Not Found error.

Hope that helps

Guest wrote 11 weeks 1 day ago

you shouldn't run a mile when

2

you shouldn't run a mile when only ten yards is needed
just one field "title" does it

Alfred wrote 11 weeks 1 day ago

Thanks!

5

Thanks!

sukant wrote 11 weeks 3 days ago

hi in my site which is

hi
in my site which is created with drupal 6 if i write the url as
www.hellotravel.com/members
it works fine but when i write
www.hellotravel.com/members/dkfjdjfkdjkfjdjfkdjfkdjkfd
it should display page not found error but it reloads the same members page
this bug is happen only with those pages which are created with views so please help someone asap

thanks in advance

James wrote 13 weeks 1 day ago

Thanks a lot for this step by

5

Thanks a lot for this step by step guide! How can I change to code to limit this to a specific vocabulary and multiple terms?

Othe steps are clear! Thanks a lot for this guide

James

GreenReaper wrote 13 weeks 5 days ago

Great tutorial! If you do

5

Great tutorial!

If you do this, consider adding a sort criteria for Taxonomy: Term ID descending and put it at the top of your criteria list. That way, newer tags - which are more likely to be *specific* tags - take precedence over more general ones.

For example, I might have an article tagged "Anthrocon" and "conventions". As the "Anthrocon" tag was created later, I get all the stories related to Anthrocon before the ones about other conventions, which is what I want.

user picture
ryanprice wrote 20 weeks 2 days ago

@Hilko, You should look at

@Hilko,

You should look at using a special field called a user reference. While this article mostly refers to the node reference field, the concept is the same:
http://drupaleasy.com/blogs/ultimike/2009/07/using-views-relationships-a...

and another:
http://drupaleasy.com/blogs/ultimike/2009/02/displaying-hierarchical-con...

Peace,
Ryan

Hilko wrote 21 weeks 1 day ago

Great tutorial! I've put it

Great tutorial! I've put it to good use already.

However, I tried to do something similar and failed miserably. Perhaps someone here could help.

I have two content types: 'person' and 'publication'. I want to create a view that shows up on an individual 'person' page, and shows all publications by this person. Both content types contain a field for the first name, one called field_firstname, the other field_pub_firstname. The view should show all the publications where field_pub_firstname == field_firstname (of the current visible single node).

If I add custom php argument code like so:

return 'John';

it correctly shows only the publications by John. However, using what I thought I learned from this page, I tried the following:

return $node->field_firstname[0]['view']

where, in case of John's 'person' page being open, should do the exact same thing.

This doesn't seem to work though. Can anyone tell me why, and what I should do to fix this?

Kevin wrote 21 weeks 5 days ago

Thank you - I learned

5

Thank you - I learned something important from this post!

Kristen wrote 22 weeks 1 hour ago

Wish I would have seen this

5

Wish I would have seen this yesterday ;)

Before I found this, I created a similar one using the views group by module where it shows the number of terms in common. The views export is here:

http://kristen.org/content/use-drupal-views-group-module-show-closest-ma...

Also, some less views-savvy folks may want to check out the featured content module for easily creating lots of different kinds of featured and related content blocks including sorting by closest match by terms.

http://drupal.org/project/featured_content

Cheers,
Kristen

user picture
ryanprice wrote 22 weeks 3 days ago

@TR_Master thanks for your

@TR_Master thanks for your comment. However, this tutorial is simply meant as an example. There are some great modules out there to handle similar situations. Read some of the earlier comments, which refer to numerous solutions.

Pingback

[...] Using Views 2 and Drupal 6 to Create a Related Pages Block | DrupalEasy nice args code [...]

TR_Master wrote 23 weeks 1 day ago

Great tutorial, it worked

4

Great tutorial, it worked perfectly.

Any chance of getting the sort by count(common tags) working ..?

The sort order should be:

1 - Drupal, CSS, HTML
2 - CSS, HTML
3 - Drupal

Thanks.

akalata wrote 23 weeks 6 days ago

Thank you Ryan! And, thanks

5

Thank you Ryan! And, thanks to all the commenters who posted with fixes/updates/adjustments/additional use cases to consider. Stuff like this is why I love Drupal. :)

Bødlen wrote 25 weeks 5 hours ago

Great stuff, i just got

5

Great stuff, i just got related pages working by follow your great guide.
Thanks :-)

Guest wrote 25 weeks 3 days ago

Or you could use the Related

Or you could use the Related Links Module and be done with it. Using Views is a very advanced concept for geeks not everyday users.

Guest wrote 27 weeks 12 hours ago

Great Post. I have

Great Post. I have implemented a view that displays a picture in a block based on the taxonomy of the page with this. However I have a page that is generated by a view. How can I give the page from a view a taxonomy so that my block view can pick it up to display a page?

chandrabhan wrote 27 weeks 12 hours ago

Good article but still lacks

3

Good article but still lacks the sorting mechanism. There is no way to dictate that the nodes with highest number of matches should come first.

copyhold wrote 28 weeks 2 days ago

Use of PHP inside views is

2
Use of PHP inside views is not a good approach because in this case the view is not cached first. And also this piece of php executed by `eval` function which is not good for performance (afaik). And even if so, you should not use `node_load`,-who knows which type will it be. Or which hooks will run on node_load. This might be ve-e-ery heavy. My suggestion is - if you are already write PHP . Why use views? Use almost the same php in block.
<?php
$nid
= str_replace('node/','',$_GET['q']);
if (!
is_numeric($nid)) return; // i only work for nodes
$ns = db_query('select distinct nid,title from {node} n inner join {term_node} tn using (nid) where nid<> %d and tid in (select tid from {term_node} where nid=%d))',$nid,$nid);
$out = array();
while (
$n=db_fetch_object($ns)) {
 
$out[] = l($n->title,'node/'.$n->nid);
}
echo
theme('item_list',$out);
?>
something like this.
Ian wrote 28 weeks 4 days ago

Great tutorial! I'd also like

Great tutorial!

I'd also like to add that this will display the current node in the list... in order to exclude it you would need to add a second Node: Nid argument with the following PHP code:

$node = node_load(arg(1));
if($node){
return $node->nid;
} else {
return null;
}

And select the "Exclude the Argument" box.

Tim browne wrote 28 weeks 5 days ago

Excellent post, as someone

Excellent post, as someone who has next to no PHP knowledge, this post just saved me a lot of time. Thank You.

Guest wrote 31 weeks 6 days ago

Thanks for such a good

Thanks for such a good article. I need some help here.
I have two content types.
1. Staff Profile.
2. Staff Video.

Now when one user create staff video content, he also select a staff profile in the Node reference field in Staff Video Content Type.

Now I want to make a view and embed it's link in the Staff Profile content type. SO that whenever any user views any Staff Profile content and click on the Views Link, he should be able to view only that Staff Video where the same name of the Staff profile node was selected. I hope that the picture is clear.
Kindly help me in this regard how am I going to make such a view.

Thanks and regards

Qasim Virjee wrote 32 weeks 4 days ago

I dig this method for making

I dig this method for making a related content block via Views - it works, except I've found that when I have the term in related nodes actually displayed as a field in my view powering this block only 1 term will display - the term field renders empty for any nodes tagged with different terms which the live node shares.

Odd.

q./

Rida wrote 33 weeks 1 day ago

Any way to sort by the number

Any way to sort by the number of commun terms ? showing the nodes that have more commun terms first ?

psychoman wrote 34 weeks 1 day ago

found that if use multiple

found that if use multiple vocabs to node, this trick pulls all of term.
to restrict turned this
foreach($node->taxonomy as $term){$terms[]=$term->tid;}

into this
foreach($node->taxonomy as $term){if ($term->vid=="4"){$terms[]=$term->tid;}}
-----------------------------------------------------------

ps
here we put number of our vocabulary, in my case 4
if ($term->vid=="4")

Shaun Wolf Wortis wrote 34 weeks 5 days ago

For anyone wanting to do a

For anyone wanting to do a similar thing but with node reference rather than taxonomy, you'd create the argument using content: the node reference field (rather than term id), and then use this code:

$node = node_load(arg(1));
if($node) {
$refnid = $node->node_ref_fieldname[0]['nid'];
return $refnid;
}
return false;

maria_zk wrote 35 weeks 1 day ago

First, thank you so much for

First, thank you so much for this. It is of great help :D

Hoping that this is still alive, I would like to ask the following:
Having 4 vocabularies assigned to the node, how can i display relevant nodes that much terms for all 4 vocabularies?

In other words:
Right now, this works like an OR statement. Even if it finds a match for one of the four vocabularies, it will display a node as relevant.
Would it be possible to display relevant nodes with an AND? So that relevant nodes should have one common term from all four vocabularies?

Thanks :D

Szymon Nitka wrote 35 weeks 2 days ago

Hi, There is one more thing

3

Hi,

There is one more thing to do with your 'related' view, please:

sorting by numer of common terms. This will make this view more useful in hardly tagged sites.

Thx,
Szy.

Guest wrote 35 weeks 4 days ago

Almost the PHP code I was

Almost the PHP code I was looking for, would it be possible to wish for a similar snipet for "Taxonomy: Term" instead of "Taxonomy: Term ID" ? :-P

Erik wrote 40 weeks 3 days ago

Thank you, Ryan! The solution

5

Thank you, Ryan!

The solution to this scenario was puzzling me the last couple of days, building a relatively simple Drupal based site. Couldn't figure out how to do it myself, but now got it working perfectly with your solution. It was the last pending piece of functionality, so I'm really glad someone at drupal.org forums pointed me to this post!

Thanks a great deal for contributing this!

Guest wrote 45 weeks 2 days ago

Views has now moved on

Views has now moved on 6.x-2.6, and unfortunately is quite a bit different to the screen dumps in this article - in particular the arguments screen - any chance of an update?

Johnn wrote 45 weeks 4 days ago

Thanks for posting this

4

Thanks for posting this tutorial. I suffered the same errors as a few others (incorrect entry of the code) but after a quick browse through the comments and your replies amendments were fast, easy and effective.

The resulting functionality is excellent! kudos to you.

Guest wrote 46 weeks 4 hours ago

one of the few decent drupal

one of the few decent drupal tutorials that's both easy to follow and does what it says on the box. THANKS

Nate Kharrl wrote 46 weeks 2 days ago

This is a crucial piece of

5

This is a crucial piece of functionality, it's amazing that this isn't rolled into stock Views. Thanks for taking the time to publish the snippet!

C Richey wrote 47 weeks 1 day ago

Pretty good tutorial, I

5

Pretty good tutorial, I actually understood it (still being a drupal noob). Still have a lot to learn about Drupal...the platform just rocks.

user picture
ryanprice wrote 48 weeks 5 days ago

Wexy, You may need to include

Wexy,

You may need to include the Comments as a Views Relationship, but I don't think so.

First, try creating a new View with just node title and comment count and see what happens.

wexy wrote 48 weeks 5 days ago

For some reason when I add

5

For some reason when I add "Node: Comment count" as a field I get no results at all, when I remove it I get the normal results. Node: Teaser and Node Statistics: View count work normaly it just bugs when I wanna print out number of comments for the node.

Any ideas? Pretty much tried everything :/

David wrote 49 weeks 3 days ago

* the problem turned out to

* the problem turned out to be a typo... I though I had checked - my apologies

* On your suggestion I tried similar_terms which also lead me to relevant_content. Both of these are much easier to configure, but don't give the layout options that your views solution does. For instance, I have a lot of node titles that are going to relate (perhaps over a hundred) and I can use views to lay them out in a grid within the block.

* Is there a reason to avoid using this as a permanent solution, having regard to the layout issue? I'm obviously fairly new to Drupal.

user picture
ryanprice wrote 49 weeks 4 days ago

David, Please double-check

David,

Please double-check the code you have entered in the default arguments box. This could make or break the block.

Also, this article is simply meant as a tutorial -> in the real world, you may want to use a module like http://drupal.org/project/similarterms

David wrote 49 weeks 4 days ago

I must have missed something

I must have missed something important. I can get the view to work up to the point that if i click the preview I get the expected result.

I can't see how I am supposed to trigger that view to display?

If i activate the block at admin/blocks/ I get this php errors:

warning: implode() [function.implode]: Bad arguments. in /var/www/html/drupal/sites/all/modules/views/plugins/views_plugin_argument_default_php.inc(48) : eval()'d code on line 4.

I've tried the patch suggested above but it didn't help.

IfI cliick on any node that contains a taxonomy term I get:

Fatal error: Cannot use object of type stdClass as array in /var/www/html/drupal/sites/all/modules/views/plugins/views_plugin_argument_default_php.inc(48) : eval()'d code on line 3

This is on a test site, but it's exactly the sort of thing that I need to do in production.

Any help appreciated.

Add your comment

The content of this field is kept private and will not be shown publicly.
 
Syndicate content