Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 492
user830694 Avatar asked Jul 27 '11 22:07

user830694


2 Answers

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' => '='
    );
}}
like image 86
ummdorian Avatar answered Nov 06 '22 18:11

ummdorian


I found the OP's comments helpful in creating a join in the hook_views_query_alter function, so I wanted to put the parts I found useful in a more digestible answer. I was using Views 2x on Drupal 6x, but I assume it would be very similar to use on D7 Views 2.

The OP mentions describing the relationship of the join in hook_views_table. This wasn't necessary for me, as I was not linking to a custom table, but one that existed in core.

The join creation in the HOOK_views_query_alter() function was very helpful though:


$join = new views_join;
$join->construct('table_name',
        'node',  // left table
        'nid',   // left field
        'nid',   // field
    )

See views_join::construct documentation for more information. In particular, I didn't need to use the 'extra' parameter that the OP used. Perhaps this is necessary with a custom table.

Finally, add the join to the query, and whatever other elements are needed from it:

// Add join to query; 'node' is the left table name
$view->query->add_relationship('table_name',$join,'node');

// Add fields from table (or where clause, or whatever)
$view->query->add_field('table_name','field_name');
...
like image 3
TwainJ Avatar answered Nov 06 '22 17:11

TwainJ