Add Table Join, Where, and Order By to Views Query in views_query_alter()

user830694 picture user830694 · Jul 28, 2011 · Viewed 14.1k times · Source

I am trying to modify the query for Views in Drupal (Views version 3, Drupal version 7).

What I want to do is change the query prior to running such that it LEFT JOINs a table in which I have weights assigned to the nodes.

If I was to write the query I want in SQL, it would look like this:

    SELECT a.nid, a.title, a.description
    FROM node a
    LEFT OUTER JOIN node_weights b
    ON a.nid = b.nid
    WHERE b.uid = $uid
    ORDER BY b.weight DESC

This query works like a champ when I run it in the query analyzer. So, now I need to make it work in my module.

I've seen multiple approaches detailed on various blogs for different ways to modify View queries, but they seem to be addressing different versions of Views. So it is very confusing to try to determine whether anything I'm looking at could even possibly work for my application.

It seems that I need to use a MODULE_NAME_views_tables() function to tell Views what the relationship is between the table I want to join and the node table.

I've added the following functions to MODULE_NAME.views.inc:

    function MODULE_NAME_views_tables() {
      $tables['node_weights'] = array(
        "name" => "node_weights",
        "join" => array(
          "left" => array(
            "table" => "node",
            "field" => "nid"
          ),
          "right" => array(
            "field" => "nid"
          ),
        ),
      );
      return $table;  
    }

This does seem to be working because when I use Krumo to look at the query array, I see my "node_weights" table in the "table_queue" element.

In the views_query_alter() function, I'd like it to work something like this:

    function MODULE_NAME_views_query_alter(&$view, &$query) {
      $uid = $_COOKIE['uid']; 
      $view->query->add_relationship('node_weights', new views_join('node_weights', 'nid', 'node', 'nid','LEFT'));
      $view->query->add_where('node_weights', "node_weights.uid", $uid);
      krumo($query);
    }

This function barfs pretty badly. Although my join table is appearing in the $view object, the add_relationship method is throwing an error for a 3rd argument, but I don't see any examples online that have 3 arguments so I don't know what it's missing.

Also, I'm pretty sure my add_where method isn't correct, but I don't know what the inputs should actually be. This is just a blind guess.

The bottom line is that I want to join the node table to my node_weights table, and then make sure my weights are used in the query to sort the results in a descending fashion where the user id = the user id in my table, and the tables are joined on the nid field.

Thanks in advance.

Answer

ummdorian picture ummdorian · Aug 5, 2015

WHEREs are pretty easy to add once you've got the JOIN in. You can both in a query alter (Drupal 7).

function MODULE_NAME_views_query_alter(&$view, &$query){

// Only alter the view you mean to.
if($view->name == 'VIEW NAME' && $view->current_display == 'DISPLAY'){

    // Create the join.
    $join = new views_join();
    $join->table = 'table_name';
    $join->field = 'entity_id';
    $join->left_table = 'node';
    $join->left_field = 'nid';
    $join->type = 'left';
    // Add the join the the view query.
    $view->query->add_relationship('table_name', $join, 'node');

    // Add the where.
    $view->query->where[1]['conditions'][] = array(
        'field' => 'table_name.collumn_name',
        'value' => 'value',
        'operator' => '='
    );
}}