Tuesday, September 8, 2009

Taxonomy menus and submenus

Here is a request for help that I posted on the Drupal Forums.



Currently, on Primary Links I have a menu item
which appears on my page.

I have defined a Taxonomy with Tags called My Tags

In my Views I have specified a table which has nodes with update date, title and teaser.

I have specified the validator as 'My Tags' and specified the Menu as Primary Links and in my Primary Links I have a menu item which has all the Tags (which are specified by the Author of the article and dynamically added) listed below it.

However, when I click the Menu Item it just takes me to a page which has the Tags across the top and then all articles listed below in a table.

When the user clicks one of the tags, then only those articles which have that tag are displayed.

What I want is for there to be a submenu from the Primary menu which will just display the relevant pages.

I'm not sure what I'm missing.





I solved this in two parts. Instead of setting up the Primary LInks in Drupal to use views I wrote a custom block within Drupal which directly accessed the Taxonomy Terms from the Drupal Database.

I have a series of articles in my website which are categorised by sport: football and cricket are categorised as 'Team Sports' and tennis and squash are categorised as 'Raquet Sports'.

Team Sports and Raquet Sports are defined in the Taxonomy menu under 'Content Management' in the Drupal admin using 'add vocabulary' and specifying the terms 'Team Sports' and 'Raquet Sports' by using 'add terms'.

These are saved to the Database table {term_data} with a category vid (presumably standing for 'vocabulary identity'), which, on my system is 6.

So to get a listing of all the terms in my sports category vocabulary I interrogate the database with the following query:

"SELECT tid,vid,name FROM {term_data} WHERE vid=6"
+-----+-----+----------------+
| tid | vid | name |
+-----+-----+----------------+
| 8 | 6 | Racquet Sports |
| 9 | 6 | Team Sports |
+-----+-----+----------------+


This will give my list of main menu items.

The actual sport which will appear as the submenu is also defined under the Taxonomy Administration section and is also checked as 'Required' when the Author creates his article, but in this case, the Author can enter any sport he likes, and, if the article concerns multiple sport, he may have a comma-separated list. These items will occur in the same database table under a different vid, in my case '3'.

"SELECT tid,vid,name FROM {term_data} WHERE vid=3"
+-----+-----+----------------+
| tid | vid | name |
+-----+-----+----------------+
| 2 | 3 | football |
| 3 | 3 | tennis |
| 4 | 3 | rugby |
+-----+-----+----------------+

These are linked to the articles in the {term_node} table.

SELECT * FROM {term_node} WHERE tid=9;
+-----+-----+-----+
| nid | vid | tid |
+-----+-----+-----+
| 9 | 9 | 9 |
| 44 | 44 | 9 |
| 45 | 45 | 9 |
+-----+-----+-----+

The nids are all the node identities associated with Team Sports (tid=9) and we can use them to find the submenu items.
SELECT * FROM {term_node} WHERE nid=44;
+-----+-----+-----+
| nid | vid | tid |
+-----+-----+-----+
| 44 | 44 | 2 |
| 44 | 44 | 9 |
+-----+-----+-----+

So, by using the tid from this (2) and looking at the term_data table, we can add 'Football' to the submenus below the menu item 'Team Sports'. Using PHP we can get a series of arrays holding the menu items and the submenus.

$categories=array();
$query=db_query('SELECT tid,name FROM {term_data} WHERE vid=6');
while($row=db_fetch_array($query)){//term id and name of the Main Menu Item
$node_query=db_query('SELECT nid FROM {term_node} WHERE tid=%d',$row['tid']);
$submenus=array();
while($nodes=db_fetch_array($node_query)){//node id of articles categorised as under Main Menu Item
$submenu_query=db_query('SELECT tid FROM {term_node} WHERE nid=%d',$nodes['nid']);
while($tids=db_fetch_array($submenu_query)){//term id of all categories referrenced by the article
$name_query=db_query('SELECT name FROM {term_data} WHERE tid=%d AND vid=3',$tids['tid']);
while($names=db_fetch_array($name_query)){//submenus which referrence the article and which belong to vocabulary '3'
$submenus[]=array('submenu'->$names['name'],'tid'->$tids['tid']);
}
}
}
$categories[]=array('menu'->$row['name'],'submenus'->$submenus);
}

In the second part, we need to use CSS to implement the drop down menus.

print '<style>';
for($i=0;$i<count($categories);$i++){
print '#expandamat'.$i.'{position: relative;}#expandamat'.$i.' ul li:hover ul{display: block;}#expandamat'.$i.' ul ul{display: none;}';
}
print '</style>';
$i=0;
foreach($categories as $row){
print '<div id="expandamat'.$i.'"><ul><li><a href="#" style="color: black !important;">'.$row['menu'].'</a>';
if(!empty($row['submenus'])){
print '<ul>';
$subs=$row['submenus'];
foreach($subs as $element){
print '<li><a href="http://sportsinterhost.com/content/news?sport='.$element['name'].'&tid='.$element['tid'].'">'.$element['name'].'</a></li>';
}
print '</ul>';
}
print '</li></ul></div>';
$i++;
}

The menu item requests a page and passes the name of the sport and it's term id which is then used in a query to select the relevant articles.

you can see this in action on sportsinterhosts.com

Please be aware that I am not an expert, and I would very much welcome comment.

I also acknowledge that my original question was badly couched, possibly because I did not understand the interaction between Primary menus and views.

No comments:

Post a Comment