View Argument Handling Code - Using Multiple Taxnomy Term Names as Arguments

We encourage users to post events happening in the community to the community events group on https://www.drupal.org.
electBlake-dupe's picture

Preface:

I've read a lot of requests for using multiple taxonomy term names as view arguments. I found a code, but it didnt work for me.
Views default argument handling using termid rather then name works beautifully, using forms like: "mydomain.com/viewpage/termid1,termid3,termid2" or "mydomain.com/viewpage/termid1+termid2+termid3", but I found the support for term names lacking.

Concept:

  • What I did with my handling code was basically grab the arguments array from mydomain.com/viewpage/term1/term2/term3, then convert any string arguments to a termid, and then flatten the arguments array (which is now all term id's) to the form of "termid1,termid2,termid3", so I can take advantage of the great termid argument support.

Setup

  1. Setup a view with ONE argument field of type: Taxonomy Term ID Notice it is term ID NOT term name
  2. Paste Code below into Argument handling Code
  3. browse your view with: mydomain.com/viewpage/termname1/termname2/termname3
    NOTE: with this setup, you can use term id's as well as termnames at the same time, and in any order you want!

Code:

// Blake Edwards Arugment Handling Code
// - Multiple Taxonomy Term Names as Arguments
$exclude_vocab = array('13');

if ($args[0]):
//replace underscores with spaces
foreach ($args as $key=>$arg) { $args[$key] = str_replace('_',' ',$arg); }
$args_original = $args;
$args_processed = array();
foreach ($args as $key=>$arg)
{
   if (!is_numeric($arg) || strlen($arg) == 4)
   {
       $terms = taxonomy_get_term_by_name($arg); //do a search for terms, return term objects
       if (count($terms) > 1)
       {
           //Exclude Vocabularies
            foreach ($terms as $key=>$term) { if (in_array($term->vid,$exclude_vocab)) { unset($terms[$key]); } }
       }
       array_push($args_processed,$terms[0]->tid);
    }
    else { array_push($args_processed,$arg); }
}

//Flatten Array to one Argument Comma Separated
foreach ($args_processed as $arg) { $newargs .= "$arg,"; }
$newargs = substr($newargs,0,-1);


return array($newargs);
ENDIF;

Comments

Thanks for your solution. Am

basby@drupal.org's picture

Thanks for your solution.

Am I correct if I state that your solution works for "mydomain.com/viewpage/termid1,termid3,termid2" but not for "mydomain.com/viewpage/termid1+termid2+termid3"?

Do you have a solution for the latter one?

Thanks!

yea, currently the setup is

electBlake-dupe's picture

yea, currently the setup is for termid1,termid2,termid3

but that can be changed easily!

If you look down at the bottom of the handling code, you see the line:
foreach ($args_processed as $arg) { $newargs .= "$arg , "; }

Thats the final part which formats the term ids into one argument, if you change the , (that I bolded and spaced above) to a plus sign, it will give you termid1+termid2+termid3

Just a little modification

patricksettle's picture

A quick mod to your code to meet my needs. Thought I would share.

The difference in the code (aside from the _ to a - in the str_replace) is instead of removing the $exclude_vocab, which would lead to an ever growing list, I've switched it to explicitly stating the vocab to search in via $vocab_required something that for my case won't be changing very often if ever.

I also removed the "strlen($arg) == 4" only because I couldn't see a reason to limit the $arg to four. Any reason for that I'm missing?

$vocab_required = array('6');
//replace underscores with spaces
foreach ($args as $key=>$arg) { $args[$key] = str_replace('-',' ',$arg); }
$args_original = $args;
$args_processed = array();
foreach ($args as $key=>$arg) {
  if (!is_numeric($arg)) {
    $possibilities = taxonomy_get_term_by_name($arg);
    $arg_tid = NULL; // tid match if any.
    foreach ($possibilities as $possibility) {
      if (in_array($possibility->vid,$vocab_required)){
          $arg_tid = $possibility->tid;
      }
    }
    array_push($args_processed,$arg_tid);
  }
  else { array_push($args_processed,$arg); }
}

//Flatten Array to one Argument Comma Separated
foreach ($args_processed as $arg) { $newargs .= "$arg,"; }
$newargs = substr($newargs,0,-1);

array($newargs);

This code works like a dream

daniel.hunt's picture

This code works like a dream for me - thanks

how about ...OG

najibx's picture

My need is content is published in to more than one groups, and I want to use Views to filter and put it in a block inside a og_panel.

I was wondering how this can be adapted for "Argument: OG: Group name". Secondly how we can have these context forwarded to og_panel. I have no problem with single group.

Thanks

-najibx -
<a href="http://www.successideaweb.com>Drupal web developer | designer in Malaysia

Slight improvements

gramie's picture

I'm not sure why you used your own code to flatten the array. Why not just

implode(',', $args_processed);

and for that matter (not that I'm criticizing you, but I'm used to seeing code written differently):

array_push($args_processed, $arg);

could be

$args_processed[] = $arg;

And to replace underscores with spaces, you can use the str_replace function, which will go through an array:

str_replace('_', ' ', $args);

Hi, How would it be possible

Summit's picture

Hi,
How would it be possible to filter on these terms with only a certain depth on views2?
I tried this on www.drupal.org/node/496756
greetings, Martijn

I am trying to set something

emilyf's picture

I am trying to set something like this up in Views 2, but it doesn't appear to work properly there. Can anyone provide any pointers on getting it to work with Views 2?
thanks much!

a_c_m's picture

Here is a modified version - which will work for views 2.

Place this code into a 'Term ID' argument as the PHP validation code. Make sure the "Allow multiple terms per argument." is selected.

The $exclude_vocab is still there (set to -1 for now, meaning it wont exclude anything).

The line, "$handler->argument = implode('+', $args_processed)" sets how the terms will interact, change + to a , if you want AND instead of OR.

This code if given the arguments 'foo/bar', will find everything that been tagged with ANY term called 'foo' or 'bar'. This is handy if you have the same term name in more than one vocabulary.

// - Multiple Taxonomy Term Names as Arguments
$exclude_vocab = array('-1');
$args = $view->args;
$args_processed = array();

if ($args[0]):
  //replace underscores with spaces
  foreach ($args as $key=>$arg) {
    $args[$key] = str_replace('_',' ',$arg);
  }
  foreach ($args as $key=>$arg)
  {
    $terms = taxonomy_get_term_by_name($arg); //do a search for terms, return term objects

    //Exclude Vocabularies, add the rest.
    foreach ($terms as $key=>$term) {
      if (!in_array($term->vid,$exclude_vocab)) {
        array_push($args_processed,$terms[$key]->tid);
      }
    }
  }

  //Flatten Array to one Argument Comma Separated
  $handler->argument = implode('+', $args_processed);
ENDIF;

return TRUE;

@emilyf -- i just got this

arh1's picture

@emilyf -- i just got this working by using two Taxonomy Term arguments, and making sure the "Allow multiple arguments to work together" box was checked for both (per http://drupal.org/node/428742#comment-1461586 ). try leaving the argument validators off initially, then experimenting with those values.

hth!

But: multiple args will give logical OR?

1kenthomas's picture

If you do this (immediately above), your view will result in a logical OR, not an AND, correct?

~kwt

Or to put that somewhat

1kenthomas's picture

Or to put that somewhat differently: to robustly deal with tnames instead of tids, raises a number of issues, for instance, what behavior is desired by the user when tnames overlap in different vocabularies?

One could think through building a GUI handler for these situations, but so far, each of my clients' needs has been different enough to require a custom "twist..." and usually won't fit into tid args or multiple tax terms... (heck, in the end, I wind up abandoning views args handling code on anything big, and throwing an array of the nids I want @ views ... but that's another story). s,

What I'm saying is that to deal in tnames, (which most clients will want), with any sophistication, may not be possible from a GUI, and requires some planning &, most likely, custom coding.

~kwt

nonsense terms

mybinaryromance's picture

the views 2 version will work fine, but arguments like /somevalidarg/somenonsensearg will still produce a list of all nodes with somevalidarg. this means:

  • nonsense input is ignored
  • you possibly get LOADS of 'duplicated content' in search engine terms, as eg. mydomain.com/content/argument/fsihaf and mydomain.com/content/argument/jijiojo and mydomain.com/content/argument/sawaq... (and ANY other invalid letter combination) all share the same content. google and friends will probably not like this.

you can prevent this by returning FALSE like this:
replace
$terms = taxonomy_get_term_by_name($arg); //do a search for terms, return term objects

with
$terms = taxonomy_get_term_by_name($arg); //do a search for terms, return term objects
if(empty($terms)) return FALSE;

Pretty useful, thanx acm.

Marko B's picture

Pretty useful, thanx acm. Wondering how to print out variables in views, for debuging purpose?

Drupal Specialist at http://adriadrop.com/

What if I want a "second" argument?

Moi_Kaka's picture

Hi,
Your code it's useful but I've got a problem.
I need a "second" argument apart from the taxonomy terms.
For example:
TAXONOMY TERMS: Milk, Sugar, Water
SUPERMARKETS: Tesco, Asda

I want a URL like that:
myexample/blablabla/Milk+Sugar/Tesco

But if I try to put a second argument (with your code in the first one) it just breaks

Any solution?

Thxs

Maybe splitting your arg[0] by +

jordimateubesancon's picture

@Moi_Kaka I'm completly new in php but modifying the code provided you could start doing somethig like this:

$view = views_get_current_view();
$arg0 = $view->args[0];
$args_processed = array();
$tnames= explode("+", $arg0);
foreach ($tnames as $key=>$tname) {
   $terms = taxonomy_get_term_by_name($tname);
   foreach ($terms as $key=>$term) {
      array_push($args_processed,$terms[$key]->tid);
      }
   }
$handler->argument = implode('+', $args_processed);
return TRUE;

I know I should change my nikname by "mrcopypaste" but it works for me ;-)

What in a multilanguage site?

jordimateubesancon's picture

First of all thanks all for this so useful information... I was getting mad with this. Today I achieved to get this nice piece of code working and my problem is nearly 100% resolved. Mine is a multilanguage site and now my view shows the content according to the (multiple) term names passed as arguments and the selected language. But it only works when I send term names in the default language. I've set my vocabularies with the option Localize terms. Terms are common for all languages, but their name and description may be localized (to say you the true this was long time ago and if I'm not wrong it was because of Ubercart needs in a multilanguage environment). So the question is what shall I modify in the code to make it work 100% in a multilanguage site?
Any help will be apreciated.

pdpravindeshmukh's picture

I want to pass multiple nids to views. I m using Drupal 7.
ex. If url is localhost/pravin/cars/40/46/47/../../

than the view should show the details of the passed nids(40/46/47/....) in tabular format.
I have created a view which is accepting only one argument.
Any help will be apreciated.

Argument Handling Code

owenkie's picture

Hello Guys,
Where can I find this Argument Handling Code??