Using Hook Views Query 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.

Comments
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