Posted 07/19/2009 - 16:43 by State68
Earlier this year I was developing a Drupal module for a charity which teaches computing skills to people with disabilities (depending on when you're reading this article that link might even take you to the charity's shiny new Drupal site). Since the charity's work is distributed (they teach people in their own homes, on their own computers), they need an efficient system whereby reports can be filed by tutors for every lesson that they give.
I used CCK to create a "lesson report" custom content type. I created a custom module (which went on to form the basis of my contributed School Report module) which allowed the logged in tutor to pick which student they had taught when creating a new lesson report. This was pretty simple: hook_user let me allocate each student to a tutor; hook_form_alter let me create a drop-down list on each lesson report creation page, containing only those students available to the currently logged-in tutor.
But then I wanted to build some views which listed lesson reports. This necessitated "exposing" my module to Views - telling the Views module what tables and columns I wanted it to know about. This was a relatively straightforward process to begin with, and was pretty well documented in the Views 2 API documentation.
Things got a great deal trickier, however, when I wanted to expose two tables to Views in a way which would indicate that those tables were related. I won't go into too much detail here (I have got a longer, more basic blog post on exposing modules to Views lined up); just think of Views as a front-end to SQL, which will generate SQL queries based on what you punch in to the Views UI. Exposing a module to views involves joining that table to a table which is already exposed to Views - node or users, for example. The problem is, how do you create joins that connect two separate tables - both created by a custom module - with one of these "base tables" in such a way that Views knows that the two custom tables are themselves connected.
Like a lot of Drupal stuff, it's simple when you know how. My module's tables are called allocated_nodes and allocations, and both contain a column, nid, which relates to node.nid. Joining allocated_nodes to node is simple:
<?php
$data['allocated_nodes']['table']['join'] = array(
'node' => array(
'left_field' => 'nid',
'field' => 'nid',
),
);
?>Then, use the following code to join allocations to node, via allocated_nodes:
<?php
$data['allocations']['table']['join'] = array(
'node' => array(
'left_table' => 'allocated_nodes',
'left_field' => 'student_uid', //this field is in the allocated_nodes table
'field' => 'student_uid', //this field is in the allocations table
),
);
?>Now you can get on with exposing all of the different columns in each table, and they will properly relate to each other when called in the same view.

The code sample at the end prevented me from hunting around views for an hour.
...because creating a simple join in views seems impossible. But where do you put this code?
And how, in the view, can you access it?
....the answer to the last commenter's question!
There's a couple of steps to this.
First of all, the easy bit: tell your module that you want to expose its tables to views. For this, you can use hook_views_api(). The documentation is pretty slick so I won't go over that here, other than to say that the default path for your module's Views include file - the file that actually tells Views precisely how to interpret the tables your module has added - is your module's folder: i.e., sites/all/modules/YOUR_MODULE/YOUR_MODULE.views.inc.
To get some tips on how to write your views.inc file, check out http://groups.drupal.org/node/17236. If you're still stuck, post back here with a link to your code, and details on what you're specifically trying to do, and I'll try to help more.