You are here

Add a LIKE operator to Views Exposed Filters?

A problem I ran into with Views involved implementing an exposed filter in a block that acted like a search. It was easy enough to filter a list of users based on a specific field. In my case, this field was just a taxonomy term reference to a vocabulary. Out of the box, the filter definitely worked if you knew the exact name of the term you were looking for. It even provided an autocomplete to help you out here. However, Views only provided a limited number of operations for these filters.

When configuring the view, we set the operator to 'one of' (aka OR if you're writing SQL). This worked for the prototype but on the first round of revisions the client said they wanted the exposed filter to work more like a "fuzzy search" - this way one could type in a string like 'O' and return 'Oracle' as a result.

I thought I would need to do a hook_views_query_alter() and just replace the operator. Unfortunately, like most Drupal solutions, this would not be that simple because...

The exposed filter has error handling that happens during the exposed filter's validation callback!

So by the time we actually got to the Views query, the taxonomy term name was already set.

Once I realized this, it was easy to shift in my own validation callback ahead of Views' default one. I then replace the original search string with a comma separated list of db_query results.

Here's all the module code needed for these Views exposed filter alterations:

  * Implements hook_form_FORM_ID_form_alter().
function directory_form_views_exposed_form_alter(&$form, &$form_state) {
  if($form['#id'] == 'views-exposed-form-directory-page') 
    array_unshift($form['#validate'], 'directory_views_exposed_form_validate');
  * Replace exact string match with a fuzzy search.
function directory_views_exposed_form_validate($form, &$form_state) {
  $vid = db_query('SELECT vid FROM {taxonomy_vocabulary} 
    WHERE machine_name = :machine', array(':machine' => 'companies'))->fetchField();
  $search = db_query('SELECT name FROM {taxonomy_term_data}
    WHERE vid = :vid AND name LIKE :name', array(':vid' => $vid, ':name' =>"%" .
    $form_state['values']['field_user_company_name_tid'] . "%" ))->fetchAll();
  $results = '';
  foreach ($search as $item) {
    $results .= $item->name . ', ';
  $form_state['values']['field_user_company_name_tid'] = substr($results, 0, -2);

So yeah... we didn't actually add a new operator to Views - sorry if that's what you're looking for!

In order package this search with the view and deploy it, the code was actually inserted into a Features module. The Feature has both the vocabulary and its term reference field saved in code. The module also contains a View with the exposed filter in it. With our configuration saved in code, the vocabulary machine_name should never change (even if the vid does) and the client can sleep easy knowing their clients will have an easy time searching on the website.

Submitted by brant on Fri, 08/17/2012 - 18:53