WE Drupal

If you need new Drupal Talent, or just a little extra bandwidth, consider hosting an intern through our Work Experience (WE) Drupal program. You get a line in on the most highly trained newbies out there, while supporting talent development for the community.

New Podcast

Posted Tuesday, April 1 at 6:40 am
Théodore Biadala (nod_), technical consultant with Acquia, and one of the Drupal 8 JavaScript maintainers, joins Andrew, Ted, and Mike to talk about the current (and future) state of JavaScript in Drupal core. Also discussed is Acquia’s new certification program, DrupalCon Latin America, and picks of the week that you’re not going to want to miss!
Download Podcast 126
DrupalEasy_ep126_20140401.mp3
Syndicate content

Everywhere

Connect with DrupalEasy:

Survey

Interested in learning more about Drupal, but can't find the training you're looking for? Help us help you by letting us know what workshops interest you. Take this short survey to let us know!

Newsletter

Stay up-to-date on DrupalEasy workshops and other events. On average, we send about one newsletter per month.

Who are we?

DrupalEasy is a training and consulting company that specializes in public and private Drupal training as well as site building and consulting with a focus on best practices and building sustainable web sites. More...

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 (159 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

169 comments

enxox wrote 2 years 39 weeks ago

this is the code for D7 $node

this is the code for D7

$node = node_load(arg(1));
if($node){
foreach (field_get_items('node', $node, 'field_tags') as $term ) {
$terms[] = $term['tid'];
}
return implode('+', $terms);
} else { return; }

Pingback

[...] Using Views 2 and Drupal 6 to Create a Related Pages Block from drupaleasy.com [...]

ryanprice wrote 2 years 45 weeks ago

This tutorial was written

This tutorial was written some time ago, when Drupal 6 was still very young - please read some of the comments below for more modern (module based) solutions to this problem.

Ryan Price
@liberatr

Guest wrote 2 years 45 weeks ago

Hi, thanks for the

Hi, thanks for the tutorial,
but when I try to implement this tutorial, at the end i got this error:

warning: implode() [function.implode]: Invalid arguments passed in \sites\all\modules\views\plugins\views_plugin_argument_default_php.inc(48) : eval()'d code on line 4.

can you help me?

Bryan Casler wrote 3 years 2 weeks ago

I was was able to create a

5

I was was able to create a working solution for D7, could use some help optimizing/reviewing it.

http://drupal.org/node/1099004#comment-4234808

Bryan Casler wrote 3 years 3 weeks ago

Hey Ryan, thanks for the

5

Hey Ryan, thanks for the great walk through. Your instructions works great on D6. However, like in #5, I took am upgrading to D7. I've tried switching $node->taxonomy to $node->field_tags, but that didn't work.

Any advice on how to make this happen in D7 would be greatly appreciated.

ryanprice wrote 3 years 6 weeks ago

Matt, I'm not sure if you do

Matt,

I'm not sure if you do need PHP to accomplish this, but if you follow the instructions exactly, and then add a "Filter" to only display nodes of a particular taxonomy term "movie-reviews" that is one way to solve the problem.

That's not how I would do it, though.

There is a great module called Context out there. You can set conditions for displaying blocks on pages, among many other things.

Basically, you build a view that shows your term with filters, don't worry about arguments unless you really want/need to.

Next you use context to set a condition that when a node is tagged with the meovie-reviews term, to have a reaction that is to show a block, and then choose the Views block you created. Make sense?

Ryan Price
@liberatr

Matt wrote 3 years 7 weeks ago

Hi there. Kinda lost,

Hi there. Kinda lost, lol.

What I want to do is show a block only on node with a specific taxonomy term.

For example the term "movie-reviews."

Do I need an php argument for that?

ryanprice wrote 3 years 9 weeks ago

Thijs, Thanks for the

Thijs,

Thanks for the comment.

I know our podcast co-host Andrew Riley has developed a similar solution with the UserPoints module - from what I understand, every time a user reads, comments on, or votes for a node, he adds points to a field that relates the user to the taxonomy terms associated with that node, which he then uses as a weighted score.

I'll see if I can get him to help me put up a tutorial for the site.

Ryan Price
@liberatr

Thijs wrote 3 years 9 weeks ago

Hi, I realy liked your

Hi,

I realy liked your tutorial... I'm trying to do something slightly different, but maybe you already know the solution....?

I have a table named "rank_user" with uid's en taxonomy id's (uid, tid) now i want to make view, where the logged in user can only see the node's where he or she has the taxonomy id for, you could derive the taxonomy id linked to the user from the "rank_user" table... but how to make a view...?

Thank you very much in advance!!
Regards,
Thijs

ryanprice wrote 3 years 10 weeks ago

@segmentation - the more apt

@segmentation - the more apt question would be "what has changed in Views 3.x?"

I don't think using Views 3 in Drupal 6 and 7 is very different. Using CCK vs using fields is not very different either. In this example, we are using Taxonomy, which must now be added as a field to any content type as a "Term reference" field.

This would mean that instead of looking for node->taxonomy it's probably more like node->field_tags (where tags is the name of your taxonomy field).

I haven't played with Views Relationships enough to know if this is now possible without writing PHP code in the default for the argument. This is something I always hope will get added. I feel like one of the goals of Drupal is taking coding tasks away from site builders.

Ryan Price
@liberatr

segmentation wrote 3 years 11 weeks ago

Hi, I was wondering what

Hi,

I was wondering what needs to be changed to make this work in Drupal 7.

Greetings

salim wrote 3 years 13 weeks ago

What if the node belongs to

What if the node belongs to multiple terms?

Hi
This view works greatly when a node has only one term
But if the node has multiple terms the view doesn't work. In my case it shows nothing at all.
i'm running drupal 6.20 and views 6.x-2.12
Is there a way to run this in a multiple terms selection environment?

Again thanks for the good job

Hendrik wrote 3 years 14 weeks ago

Hello, anyone tried this with

Hello,
anyone tried this with Views 6.x.3-dev? Can´t get it working there.
The SQL for a node with nid = 17 looks like this:

SELECT node.title AS node_title,
node.nid AS nid,
node.language AS node_language
FROM node node
INNER JOIN term_node term_node_value_0 ON node.vid = term_node_value_0.vid AND term_node_value_0.tid = 17
WHERE (node.status = 1) AND (node.type in ('product')) AND (term_node_value_0.tid = 17)

It searches for nodes associated with the term id = 17 while the term associated with the actual node is 253 (17 is the nid as stated above).

Thanks!

fourmi4x wrote 3 years 23 weeks ago

Hi, Thank you for this

5

Hi,
Thank you for this tutorial !

Is it possible to display the view not in a block of the current page, but on a separate page, on demand (by clicking a button "see related content" for instance) ?

In other words : will the arguments from the current node be automatically transfered when I generate the view on another page ?
Or by extension, how to generate a block with content related to a page on another page ?
That would be awesome !
Many thanks,
Xavier

Carlos wrote 3 years 25 weeks ago

Hello, I have successfully

5

Hello,

I have successfully followed your instructions in the past, but now I have another problem which is similar but not exactly the same you are talking about:

I want to show related nodes according to user interests (which are content taxonomy fields in a content profile).

That's what I want to achieve:
1. Determine the current user's taxonomy terms
2. Determine all other nodes that share taxonomy terms
3. Display the title (and link) to those pages in a block

That's what I did:
1. Install and configure Content Profile.
2. Create a vocabulary called "interests/targets"
3. Create a taxonomy field called "interests" (linked to vocabulary created before) in a content type using content profile that would be displayed in sign-up process.
4. Create custom content types with a taxonomy field called "target" which would share the same vocabulary ("interests/targets").
5. Create a block using views that would display current's user's content of interests, according to the taxonomy fields.
6. Provided that both content types and users share a content taxonomy field, I wanted to use it as an argument (it's the field called "Interessos" in the attached view) and as default value I chose "logged in user".
7. Since technically users don't have any taxonomy field (I had to use content Profile) I also used that field as a relationship and I made sure that the argument uses the relationship.

Unfortunately it didn't work.

Can you help me, please? Thank you very much

More details are provided in views' issue queue, but unfortunately I didn't get any reply: http://drupal.org/node/923834

groomer wrote 3 years 26 weeks ago

Excellent tutorial, Ryan. You

Excellent tutorial, Ryan. You sure helped a lot of people (like me) out with this single post. We owe you countless beers.

ryanprice wrote 3 years 31 weeks ago

Sam, There is actually a

Sam,

There is actually a setting in the attachment (at the bottom of the left column while editing the attachment) that allows you to inherit arguments from the main view. This might be off by default, but it's easy to change.

Ryan Price
@liberatr

Sam wrote 3 years 31 weeks ago

Hello, I have created

Hello, I have created something similar as you, but I currently have:
A page (which gets the taxonomy-id from an argument, the taxonomy id represents the category of a product). I've created a relationship to get the seller of the product. But I want next to the product something like:
The seller is ..., they also sell ____ , ____ and ____. So what I'm trying to do here is making an attachment for this (I've managed to get the related products when you put the seller-id as an argument, but I want to get the argument directly from the above-lying page).

I really hope this makes some sense to you.
In a nutshell: How can I pass arguments from the page to an attachment, staying on the same page?

damiandab wrote 3 years 34 weeks ago

Sorting problem and already

3

Sorting problem and already viewed node is displayed again in related content block :(

I'm comming back with the question from few earlier posts:

There is no way to dictate that the nodes with highest number of matches should come first?

I know module like 'similar terms' that make it perfect, but only displays the linked titles to the related node. Is any way to acomplish the same with the views, so I could dislpay other custom fields (ex. image) in the block of related nodes?

Thanks in advance for any helpfull answer.

ryanprice wrote 3 years 37 weeks 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...

Ryan Price
@liberatr

ryanprice wrote 3 years 37 weeks 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

Ryan Price
@liberatr

Leonardo Giordani wrote 3 years 37 weeks 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 3 years 41 weeks 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 3 years 42 weeks 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 3 years 42 weeks ago

Fantastic tutorial and

5

Fantastic tutorial and comments...what a lifesaver

phobia flying wrote 3 years 42 weeks 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 3 years 44 weeks 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 3 years 46 weeks 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 3 years 46 weeks ago

This is fantastic thanks,

5

This is fantastic thanks, works a dream.

ryanprice wrote 3 years 48 weeks 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

Ryan Price
@liberatr

Guest wrote 3 years 48 weeks 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 3 years 48 weeks ago

Thanks!

5

Thanks!

sukant wrote 3 years 48 weeks 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 3 years 50 weeks 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 3 years 50 weeks 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.

ryanprice wrote 4 years 5 weeks 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

Ryan Price
@liberatr

Hilko wrote 4 years 5 weeks 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 4 years 6 weeks ago

Thank you - I learned

5

Thank you - I learned something important from this post!

Kristen wrote 4 years 6 weeks 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

ryanprice wrote 4 years 7 weeks 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.

Ryan Price
@liberatr

Pingback

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

TR_Master wrote 4 years 7 weeks 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 4 years 8 weeks 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 4 years 9 weeks ago

Great stuff, i just got

5

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

Guest wrote 4 years 10 weeks 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 4 years 11 weeks 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 4 years 11 weeks 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 4 years 13 weeks 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 4 years 13 weeks 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.

Syndicate content