OR operator in Drupal View Filters

18,548

Solution 1

if you want do it with view_query_alter hook, you should use $query->add_where() where you can specify if it's AND or OR. From views/include/query.inc

  /**
   * Add a simple WHERE clause to the query. The caller is responsible for
   * ensuring that all fields are fully qualified (TABLE.FIELD) and that
   * the table already exists in the query.
   *
   * @param $group
   *   The WHERE group to add these to; groups are used to create AND/OR
   *   sections. Groups cannot be nested. Use 0 as the default group.
   *   If the group does not yet exist it will be created as an AND group.
   * @param $clause
   *   The actual clause to add. When adding a where clause it is important
   *   that all tables are addressed by the alias provided by add_table or
   *   ensure_table and that all fields are addressed by their alias wehn
   *   possible. Please use %d and %s for arguments.
   * @param ...
   *   A number of arguments as used in db_query(). May be many args or one
   *   array full of args.
   */
  function add_where($group, $clause)

Solution 2

If you are using Views 3 / Drupal 7 and looking for the answer to this question, it is baked right into Views. Where it says "add" next to filters, click the dropdown, then click "and/or; rearrange". It should be obvious from there.

Solution 3

Unfortunately this is still a missing feature in Views2. It has long been asked for and was promised a while ago, but seems to be a tricky piece of work and is now scheduled for Views3.

In the meantime you could try the Views Or module mentioned in that thread. As of today, it is still in dev status, but seems to be actively maintained and the issue queue does not look to bad, so you might want to give it a try.

Solution 4

I added it by concatenating the string.

It is relatively specific to the implementation - people would need to play with field to match for OR - node.title in the following code and the field to match it with - node_revisions.body in this case.

Extra piece of code to make sure that node_revisions.body is in the query.

/**
 * Implementation of hook_views_api().
 */
function eventsor_views_api() { // your module name into hook_views_api
  return array(
  'api' => 2,
  // might not need the line below, but in any case, the last arg is the name of your module
  'path' => drupal_get_path('module', 'eventsor'),
 );
}

/**
 *
 * @param string $form
 * @param type $form_state
 * @param type $form_id 
 */
function eventsor_views_query_alter(&$view, &$query) {

  switch ($view->name) {
    case 'Events':
      _eventsor_composite_filter($query);
      break;
  }
}

/**
 * Add to the where clause.
 * @param type $query 
 */
function _eventsor_composite_filter(&$query) {
  // If we see "UPPER(node.title) LIKE UPPER('%%%s%%')" - then add and to it.
  if (isset($query->where)) {

    $where_count = 0;
    foreach ($query->where as $where) {
      $clause_count = 0;
      if (isset($where['clauses'])) {
        foreach ($where['clauses'] as $clause) {
          $search_where_clause = "UPPER(node.title) LIKE UPPER('%%%s%%')";
          // node_data_field_long_description.field_long_description_value
          $desirable_where_clause = "UPPER(CONCAT_WS(' ', node.title, node_revisions.body)) LIKE UPPER('%%%s%%')";
          if ($clause == $search_where_clause) {
            //  $query->add_where('or', 'revisions.body = %s'); - outside of what we are looking for
            $query->where[$where_count]['clauses'][$clause_count] = $desirable_where_clause;

            // Add the field to the view, just in case.
            if (!isset($query->fields['node_revisions_body'])) {
              $query->fields['node_revisions_body'] = array(
                'field' => 'body',
                'table' => 'node_revisions',
                'alias' => 'node_revisions_body'
              );
            }
          }
          $clause_count++;
        }
      }
      $where_count++;
    }
  }
}
Share:
18,548
Vodde
Author by

Vodde

Updated on June 04, 2022

Comments

  • Vodde
    Vodde almost 2 years

    I need to implement an OR operator between some filters in a Drupal View. By default, Drupal AND's every filter together.

    By using

    hook_views_query_alter(&$view, &$query)
    

    I can access the query ( var $query ) , and I can change either :

    $query->where[0]['type'] 
    

    to 'OR', or

    $query->group_operator 
    

    to 'OR'

    The problem is however, that I do not need OR's everywhere. I've tried changing both of them to OR seperately, and it doesn't yield the desired result.

    It seems changing those values, puts OR's everywhere, while I need => ( filter 1 AND filter 2 ) OR ( filter 3 ), so just 1 OR.

    I could just check the Query of the View, copy it, modify it, and run it through db_query, but that's just dirty ..

    Any suggestions ?

    Thx in advance.