I've got a hierarchical taxonomy vocabulary with 24 terms currently, but eventually this will grow to include many more. Currently I'm using the Term Display module to list my terms on each node. The terms which are musical instruments grouped in families (woodwinds, brass, strings, etc.) must be listed in a specific standard order. When viewing my term list page (Administer › Content management › Categories) for this vocab, I have all the terms listed as I want them by giving each parent term (instrument family) and then each child term (individual instruments) a specific weight. It looks something the tree recreated below. I've added the assigned weights in brackets after each term.
Woodwinds [weight 0]
-- Flute [weight 0]
-- Piccolo [weight 1]
-- Alto Flute [weight 2]
Brass [weight 1]
Percussion [weight 2]
-- Pitched Percussion [weight 0]
---- Xylophone [weight 0]
---- Glockenspiel [weight 1]
---- Chimes [weight 2]
-- Unpitched Percussion [weight 1]
---- Temple Blocks [weight 0]
-- Gamelan [weight 2]
Harp & Keyboards [weight 3]
-- Harp [weight 0]
-- Piano [weight 1]
-- Organ [weight 2]
Strings [weight 4]
-- Violin [weight 0]
---- Violin 1 [weight 0]
---- Violin 2 [weight 1]
-- Viola [weight 1]
-- Cello [weight 2]
-- Bass [weight 3]
Electronic Tape [weight 5]
Now it seems to me that intuitively, the ordering of the terms as listed in this tree-like arrangement should be preserved in any listing on a node, but is not case. Instead drupal seems to sort by the individual term weights and then alphabetically. For example on the node that has the most instruments listed they appear in this order:
Flute, Harp, Temple Blocks, Violin 1, Xylophone, [all weight 0]
Glockenspiel, Piccolo, Viola, Violin 2, [all weight 1]
Alto Flute, Cello, Chimes, [all weight 2]
Bass [weight 3]
This is all perfectly logical, but is there a way around it. Obviously I could theoretically assign the appropriate individual term weights to each instrument term, but eventually I will have more than the 21 levels of weights provided by the taxonomy module. Any ideas on how to get the terms in the tree order?
Comments
You are right that hierarchy
You are right that hierarchy is not reflected in the order of display.
It might help a bit, if you use a different vocabulary for each family. This will also mean that and etc. are not listed as instruments.
BTW. Shouldn’t Piano be in Pitched Percussion?
___________________
It’s in the detaιls…
I agree that breaking each
I agree that breaking each family down into it's own vocabulary might make organizing things easier in some respects, but then I would have different fields listed as you suggest: i.e. woodwinds, strings, percussion, etc. when I really want everything listed in just one field in each node under the heading of "Instruments:". Even if there were a way to combine the separate vocabularies under an added field label, I would still like to find a way to override the built-in sort behavior. I can imagine that there might be a lot of applications for it.
Thanks for the reply.
(Piano has been traditionally classified as a percussion instrument, but in orchestral scores, it is grouped with other keyboard instruments as well as with the harp. It is the orchestral score order I am trying to reflect in my listing.)
possible approach
I haven't had time to investigate this fully, and my php knowledge is at a very basic stage, but here is what I've found. The taxonomy_get_tree function returns my vocabulary listed above with all the terms in the order I want them. The problem is that it returns all of the terms in the vocab, not just the the terms associated with a particular node. Does anyone have a clue about how to combine the sorting behavior of taxonomy_get_tree with the node-relevance filtering of taxonomy_node_get_terms?
Anthony
--
anthonymosakowski.com
intersection
As both these functions return arrays, you can use;
$result = array_intersect(taxonomy_get_tree(...), taxonomy_node_get_terms(...));This will preserve the order of the first array.
I don’t think this is the most efficient solution :-(
___________________
It’s in the detaιls…
demonstration portfolio
tried, but no luck
Hey Zeta,
if you're still around, thanks for the tip: letting me know about the array_intersect function. It seems like it might be the way to go, but so far I haven't had success. Here's what I've got:
I know that each array does contain a list of terms, because if I change the $links definition to just output each array separately rather than the intersection of both, I get a list of terms. However, the definition above results in a long list of identical error messages:
recoverable fatal error: Object of class stdClass could not be converted to string in ...includes/common.inc(1352) : eval()'d code on line 12.This isn't entirely clear to me. Is it saying the two arrays are somehow incompatible for intersection?
Anthony
--
anthonymosakowski.com
Comparisons
What version of Drupal are you using?
Is that the full error message?
If so, then I think this is caused by lack of keys. Try using array_intersect_assoc($treeterms, $taxterms). I’m not optimistic about this option, but no harm in trying.
More likely, I think, is the comparison performed by array_intersect, needs strings: So instead use array_uintersect($treeterms, $taxterms, 'tax_term_cmp'). This will compare terms using a function;
which you will need to include.
___________________
It’s in the detaιls…
demonstration portfolio
will try these
I'm using Drupal 5.7, and the error message I quoted above is complete. There are are many, too many to count: I have to scroll all the way down the page to see anything other than my node title, but the node content does get displayed, just not the taxonomy terms I have set up my code to output.
I'll give your suggestions a try and report back. There's no way to learn about how to do these things other than by doing them. When I read about arrays on php.net, I found that the contents of arrays are always converted to strings, so I'm not sure why there is any issue here, but obviously something is not matching up. And probably I didn't quite understand what I read. Thanks again.
Anthony
--
anthonymosakowski.com
what about this?
Haven't had a chance to try your suggestions yet, but I did a little more "light reading" on php.net and found the array_key function, so I added this code:
which output this on my page:
It shows that keys are present in both arrays but don't match, (or that the taxonomy_get_tree function assigns some sort of arbitrary key at any rate) does that mean anything?
Anthony
--
anthonymosakowski.com
Yes, it means...
I'm less optimistic about the first option, and more optimistic about the second.
When I said I meant keys other than the default 1, 2, 3… – every array has some sort of key, sometimes they carry significant information. It seems that the second array, at least, uses the tid as a key.
It would be more useful to print output of;
But try option 2 first.
___________________
It’s in the detaιls…
demonstration portfolio
success at last
Hi Zeta,
I finally had some time to work this all out and now have some code that does what I want:
I ended up finding out about and using create_function() to define the callback function. At first I just used function, but for some reason that version of my snippet would only work if I included in the body of a node (otherwise it would complain that the function had already been declared), and I am trying to get this code into a cck field eventually. The above snippet works in a cck text field, but has to be copied and pasted into each node manually which is a pain. I also have it in a block, but the block placement isn't as precise as I'd like it to be. Thanks again for your help in figuring out how to get the terms sorted in tree-order.
Anthony
--
anthonymosakowski.com
…just what I've basically
…just what I've basically been looking for - thank you very much for this thread - and this handy code! …although I must say that I somehow actually had strange problems with the return/explode line - and I don't know why. Additionally I wasn't 100% happy with the line "$node = node_load(arg(1));" - so I changed that to "$node_id = ($node->nid);". And then I anyways needed the hierarchical terms more separately - additionally I needed the related term-IDs to compare with the curent URL so that I can hide and/or style the 'active' term - and since I only have three 'levels' I did the following:
with this info I can do something like this:
…I use this on taxonomy pages - or actually on a panels page that overwrites a taxonomy page and therefore I get the term ID from arg(2)…
…greetz, t..
___________________________
How do one use this within
How do one use this within template.php then invoke it from node.tpl.php? Is it possible ? For example I have a vocabulary ($depth=2) and for the teasers I want to show only the deepest term and for the full node all of the terms. Thanks.
Moded to look like how Hierarchical Select displays terms
Excellent - thanks just what i needed.
I modified it since I needed it to display my taxonomy like the awesome Hierarchical Select module does - ex:
Canada, Nova Scotia
United States of America, Arizona, Phoenix
So my mod the terms are listed with each set (parent and children) on a separate line and NOT as links. Making them links is just a matter of reinserting the code from above.
PS: I put the snippet in a contemplate where it seemed to like "print" command versus "return"
oops ! ! !
My above code does not work if there is only one term. Also in this new code i put each set into a list item.