Home >> Blogs
Sep 03, 2010 Brandon 1 Comment Views, query alter, hook_views_query_alter, drupal, alter

Building a website I recently ran into an issue where I had HTML search facets interacting with Drupal views. The user would click on the facet and it would filter the view depending on the argument. I ended up implementing hook_views_query_alter. To make sure the values I wanted to filter on were in the view, I added the search facets into the view as fields. This automatically joins the necessary tables so that you don’t have to. Implementing hook_views_query_alter requires two parameters, view and query, both are passed by reference. Since this hook is called for every view the first thing I did was check that I was altering the right query by adding an if statement that checks the view name. After that you're free to modify the query as you wish. In my example, I looped through the search facets and added them as where statements and arguments to the query.

function search_views_query_alter(&$view, &$query) {   if($view->name == 'example_view_name'){     foreach($parsed_url AS $key => $value){       $query->where[0]['clauses'][] = 'profile_values_profile_' . $key . '.value IN ("%s")';       $query->where[0]['args'][] = $value;     }   } }

One of the search facets was a taxonomy filter which the user was allowed to multi select. In order to get the view to grab the correct values, I had to add join clauses to dynamically create term_node table aliases. This is done by adding a join clause to the table_queue and tables array elements within the query object. I was able to just copy the existing term_node table_queue and tables array elements because I only wanted to create different aliases. Then I incremented the existing term_node table count within the tables array. If you wanted to create a new table join dynamically, the same approach is used but the table_queue and tables definitions need to be created by hand.

foreach($parsed_url AS $key => $value){   $vid = _search_get_vocabulary_id(str_replace('_', ' ', $key));   $tid = _search_get_term_by_vocabulary($vid, $value);   $table_term_node_join = $query->table_queue['term_node'];   $query->table_queue['term_node_' . $count] = $table_term_node_join;   $query->table_queue['term_node_' . $count]['alias'] = 'term_node_' . $count;   $query->tables['term_node']['count']++;   $query->where[0]['args'][] = $tid->tid;   $query->where[0]['clauses'][] .= 'term_node_' . $count . '.tid = %d';   $count++; }

The query table_queue and tables array elements looks like so: Table Queue:

'table_queue' => array (   'term_node' => array (     'table' => 'term_node',     'num' => 1,     'alias' => 'term_node',     'join' => views_join::__set_state(array(       'definition' => array (       'left_field' => 'vid',       'field' => 'vid',       'table' => 'term_node',       'left_table' => 'node',     ),     'extra_type' => 'AND',     'table' => 'term_node',     'left_table' => 'node',     'left_field' => 'vid',     'field' => 'vid',     'type' => 'LEFT',     'adjusted' => true,     )   ) Tables: 'tables' => array (     'node' => array (       'node' => array (       'count' => 1,       'alias' => 'node',       ),     'term_node' => array (       'count' => 1,       'alias' => 'term_node',     )   ), );

In my book this makes views more comfortable to use because it gives me more control over them. This along with a view preprocessor allows me to style and output pretty much anything I want within a view.

Subscribe to RSS - blogs

Comments


May 10, 2013 at 05:49pm

thanks! seems a very useful case, but maybe the author does not know that the source code is displayed without break lines (at least for my case).

Add new comment

Appnovation Technologies