Filter/Search on multiple fields with Views 3.x

[Update: As of Views 7.x-3.4, you can now use the new "Global: Combine fields filter" to combine fields for an exposed search. Just add the fields you want to search to the view's Fields section, then add a 'Global: Combine fields filter' and select all the fields you want to search. Simple as that!]


A common need I run into with a ton of Drupal sites and Views is searching/filtering content based on multiple fields. For example, a lot of people would like to search for content using either the Title or the Body for a particular content type.

There are two primary solutions offered for this situation, but they both have downsides or are overly complex, in my opinion:

  • Use the Computed Field module to create yet another field stored in the database, combining the two (or more) fields you want to search, then expose a filter for that field instead of both of the individual fields. (I don't like this because it duplicates content/storage, and involves an extra module to do so).
  • Use the Views Filters Populate to invisibly populate a second field that you've added to a views OR group (using Views OR in Views 2.x, or the built-in AND/OR functionality in Views 3.x). (This module is slightly limited in that you can only work with strings, and again, it involves an extra module).

Instead of using an extra module, I simply do the following to achieve a multi-field search:

  1. Add an and/or group to the filters in Views 3.x (next to 'Filter criteria', click the 'Add' drop down and choose 'and/or, rearrange').
  2. Put the main field you'd like to search into the new filter group (in my case, the Title field), and set the new group to OR.
  3. Implement hook_views_query_alter() in a custom module. In the query alter, you'll simply get the keyword parameter, and add a join and where clause (if you want to join to another table, like the 'body' data table). The code I'm using in this particular instance is below:

<?php
/**
 * Implements hook_views_query_alter().
 *
 * Allow users to search the in the 'help' view by title OR body.
 */
function custom_views_query_alter(&$view, &$query) {
 
// Only do anything when using the 'help' view.
 
if ($view->name == 'help') {
   
// Get the keyword used for the search.
   
$keyword = isset($_GET['title']) ? $_GET['title'] : '';

   
// Add a new LEFT JOIN and WHERE clause for the help node body.
   
$join = new views_join();
   
$join->construct('field_data_body', 'node', 'nid', 'entity_id');
   
$query->table_queue['node__field_data_body'] = array(
     
'table' => 'field_data_body',
     
'num' => 1,
     
'alias' => 'node__field_data_body',
     
'join' => $join,
     
'relationship' => 'node',
    );
   
// The first parameter selects the 'AND/OR' group this WHERE will be added to.
    // In this case, we add it to the second group (the first one is an AND group for
    // 'status = published' and 'type = help').
   
$query->add_where(2, 'node__field_data_body.body_value', '%' . $keyword . '%', 'LIKE');
  }
}
?>

The documentation for a views_join() and add_where() are somewhat vague, but basically, the code above only runs on the 'help' view, it gets the keyword from the URL parameters (works with or without AJAX-enabled views), then adds a join from the node table (where the 'Title' is) to the field_data_body table (where the content is), and adds a 'where' clause to the new 'OR' group we created in steps 1-2 above.

If you want to dig deeper into the query, just use the Devel module's dpm() function to show the $query object (dpm($query);).

(Note: This illustrates a pretty simple two-field search. I've used the same technique to search on more fields, just adding more where clauses, and making sure there are joins to all the tables where I'm searching... in one example, I searched a list of users by their username, real name (fields), phone number (a field), or email address).

Comments

Nice Post. search_api give this option but then apache solr is requried for this. IMO bef should have this ability.

Yeah; for most searching needs, I steer people towards Solr solutions... But a lot of times, someone needs a specific view to have better search through filters, and either they don't want to use Solr or the view wouldn't easily be replicated with a custom search API search.

D7 Views 3.x has a feature for this out of the box now. Look in the filters section for a combined field filter in the Global group.

I can't seem to find anything like that; all I see in the Global group of filters is 'PHP'... I'm running Views 7.x-3.3 (latest stable release)...

Woah, awesome! Didn't notice that was added in Views 7.x-3.4... I'm going to update this post accordingly. This is a hundred times easier.

Still, the "Global:Combine fields filter" works for string only (just as the standalone "Views filter populate"). I am looking for a similar filter that supports NUMERIC fields. Or indeed write some code... Thanks for this post.

Funny! Working on old sites lately, it pays to google search a bit before trying to craft my own ridiculous work-around -- thanks for posting the update to your post. Guess I'll be updating this site from Views 3.2 to Views 3.7! #2014

Thank you, this saved my life, since in my site the Global: Combine fields filter doesn't work. No matter what I do, it doesn't display any search results.