How to make views accept multiple CCK values as arguments

As of the date of this writing views 2 for Drupal does not have a canned method of accepting multiple arguments that are CCK fields. The case where this came up for me was in a CCK select field that had dynamically generated options (created through php). The options were years, and the user was allowed to chose multiple years. How then, can one set a view to dynamically filter for content that had been marked with at least one of the years sent in the argument?

If this sounds confusing bear with me a second, because I did find a solution. The idea is this: I have a view with a path “car” and I send an argument in the url for the years (1997+1998) etc… So the url would look like so cars/1997+1998. So how do I get views to accept this code? Well first of all you have to look at what fields are capable of accepting multiple arguments, and what you will find is the only one that even remotely applies is node nid. So how do we go from accepting years and feed the view a list of nids that match the results we want? The answer: validator options with PHP code.

Now to start off I entered this code under the validator options PHP code section:

$values =  get_nodes_by_years($argument, $handler);
//By setting the $handler->argument we give the view a new set of arguments from the function that was called.
$handler->argument = $values[‘args’];
//We determine whether the argument validates.
return $values[‘return’];

Obviously this isn’t going to make sense yet because you don’t know where the data came from. In a custom module I created the following function:

function get_nodes_by_years($argument, $handler) {
  //Turn the years from the original argument into an array
  $year_array = explode(‘ ‘, $argument);
  //Use the drupal placeholders function for safe dynamic placeholders
  $placeholders = db_placeholders($year_array, ‘text’);
  //Query the database to get the nids that match our needs
  $result = db_query(“SELECT cy.nid FROM {content_field_year} cy, {node} n WHERE cy.field_year_value IN ($placeholders) AND cy.nid = n.nid AND n.type =’product'”,$year_array);
  $nid_array = array();
  while ($products = db_fetch_object($result)) {
    //Check if already in the array to avoid duplicates
    if (!in_array($products->nid, $nid_array)) {
      $nid_array[] = $products->nid;
    }
  }
  // Convert the nid_array back into a string and store it
  $values[‘args’] = implode(‘+’,$nid_array);
  // Decide whether the argument will validate or not
  if (is_array($nid_array)) {
    $values[‘return’] = TRUE;
  }
  else {
    $values[‘return’] = FALSE;
  }
  //Send the $values array to the validator code
  return $values;
}

Now if you study the code you might be able to tell what I am doing here, but it does take a certain degree of understanding of php and Drupal.

Basically we take the incoming list of years and we run our own queries in order to return a list of nodes that we can then feed to views.

Now you might be asking why I didn’t use taxonomy instead since taxonomy already has the capacity to accept multiple arguments. There are several reasons why taxonomy didn’t fit with what I was trying to do, but there was a moment when I almost threw in the towel and converted the fields to taxonomy. I’m sure you could think of other situations where you would want multiple arguments of CCK fields, in fact that’s probably why you ended up on this page.

Good luck.