Tables are described to Views via hook_views_data(), which returns an array of table information, keyed by the name of the table. For example, if your module is describing three tables, 'foo', 'bar' and 'baz', your array will look like this:
$data = array( 'foo' => array( // ...info here... ), 'bar' => array( // ...info here... ), 'baz' => array( // ...info here... ), );
The key should be the actual database name of the table (not including prefix), but it can be an alias as long as the join information (explained later) contains the real name of the table.
Each item in the array should be a field in the table, with the exception of a special information section called 'table'. Example:
$data['foo'] = array( 'table' => array( // ... info about the table, described later ... ), 'bar' => array( // ... info about the field named 'bar', i.e, foo.bar, ), 'baz' => array( // ... info about the field named 'baz', i.e, foo.baz, ), );
Once you get down to an array that contains actual data, that piece of the array will often be referred to as the definition.
Each table should have a 'table' section in it, which is used to set default information for the table, such as the group, as well as the very important joins and whether or not this is a base table.
First, there are several items that are actually for fields but can be placed here so that all fields within the table inherit them:
In general, having 'title' and 'help' at the table level doesn't make a lot of sense, but usually every item in a table is in the same group. Thus it is very common to define the 'group':
$data['foo']['table']['group'] = t('Foo');
The other items in the 'table' section are described in the following sections.
If your table is a base table -- meaning it can be the primary, central table for a View to use, you can declare it to be a base table. This primarily provides UI information so that it can be selected.
// Advertise this table as a possible base table $data['node']['table']['base'] = array( 'field' => 'nid', 'title' => t('Node'), 'help' => t("Nodes are a Drupal site's primary content."), 'weight' => -10, );
The following items are available in the base section :
// In settings.php for your site // Your drupal (site) database needs to be called 'default' $db_url['default'] = 'mysqli://user:pass@host/drupal_db'; $db_url['budget'] = 'mysqli://user:pass@host/other_db';
Then when you are describing the external database in your base table you would write something like this:
$data[$table]['table']['base'] = array( 'field' => 'Primary key', 'title' => t('Field name'), 'help' => t('Field description'), 'database' => 'budget', 'weight' => -10, );
For Views to use your table, it has to either be a base table, or know how to link to an existing base table. Or sometimes both. Views uses this information to create a path to the base table; when the table is added to the query, Views will walk along this path, adding all tables required into the query.
In the above example, to use these with 'node' as the base table, both 'term_data' and 'term_node' need to be defined, and they each need a join handler for node:
$data['term_data']['table']['join']['node'] = array( 'left_table' => 'term_node', 'left_field' => 'tid', 'field' => 'tid', );
The above can be read as "In order to join to the node table, the term_data table must first link to the term_node table, and they join on the 'tid' field.". When adding this table to the query for a node view, Views will look at this and then look for the term_node table.
$data['term_node']['table']['join']['node'] = array( 'left_field' => 'nid', 'field' => 'nid', );
Above, the fact that 'left_table' is left out lets us know that term_node links directly to the node table, using the 'nid' field on both sides of the join.
Quite a few more fields are available in this definition:
Aside from the special table tag, each table can also have an unlimited number of field designations; these correspond roughly to fields on the table, though it is very common to use non-fields to display data that isn't directly in a field, such as data arrived from formulae, or special links related to the object the table is part of.
Each field is described in the view data with an array, keyed to the database name of the field. This array may contain some information fields, plus an entry in each of the five types of items Views has per field: argument, field, filter, relationship, sort. For example:
$data['node']['nid'] = array( 'title' => t('Nid'), 'help' => t('The node ID of the node.'), // The help that appears on the UI, // Information for displaying the nid 'field' => array( 'handler' => 'views_handler_field_node', 'click sortable' => TRUE, ), // Information for accepting a nid as an argument 'argument' => array( 'handler' => 'views_handler_argument_node_nid', 'name field' => 'title', // the field to display in the summary. 'numeric' => TRUE, 'validate type' => 'nid', ), // Information for accepting a nid as a filter 'filter' => array( 'handler' => 'views_handler_filter_numeric', ), // Information for sorting on a nid. 'sort' => array( 'handler' => 'views_handler_sort', ), );
The above example describes the 'nid' field on the 'node' table, providing 4 of the 5 handlers. Note that while field is normally expected to be the database name of the field, it doesn't have to be; you can use an alias (which is how you get multiple handlers per field) or something completely made up for items that aren't tied to the database. For example:
$data['node']['edit_node'] = array( 'field' => array( 'title' => t('Edit link'), 'help' => t('Provide a simple link to edit the node.'), 'handler' => 'views_handler_field_node_link_edit', ), );
The above handler definition an edit link to a node, but this isn't a field in and of itself. For aliased fields, here is another example:
$data['users']['uid_current'] = array( 'real field' => 'uid', 'title' => t('Current'), 'help' => t('Filter the view to the currently logged in user.'), 'filter' => array( 'handler' => 'views_handler_filter_user_current', ), );
The above definition provides an alternate filter handler on the uid field for the current user.
The following items are allowed in the field definition:
For more information about what handlers need/use what data, visit the Views API site and check out the available handlers.