Answers:
我进一步看了一下,但实际上找不到任何描述此内容的文档。
我需要的是一种将users表与其他两个为用户保存数据的表联接的方法。但是,其他两个表与用户表之间存在“一对多”关系,这意味着如果我尝试同时将用户表与这两个表连接在一起,将导致笛卡尔连接。但是,由于我只需要计算与任何给定用户关联的其他两个表中的记录数,因此子查询应该可以解决问题。但是,我找不到有关视图和子查询的任何文档-所以这就是我所做的。
我通过hook_views_data()创建了两个虚拟字段(我将其称为“下载”和“监听”)。字段的定义在下面列出。
function hook_views_data() {
$data['users'] = array(
'downloads' => array(
'title' => t('Downloads'),
'field' => array(
'handler' => 'views_handler_field_numeric',
'click sortable' => TRUE,
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'sort' => array(
'handler' => 'views_handler_sort',
),
),
'listens' => array(
'title' => t('Listens'),
'field' => array(
'handler' => 'views_handler_field_numeric',
'click sortable' => TRUE,
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'sort' => array(
'handler' => 'views_handler_sort',
),
)
),
);
现在,当您为用户配置视图时,将出现“下载”和“监听”字段。但是,现在尝试运行查询将导致错误,因为虚拟字段毕竟是虚拟字段。它们不存在。这些字段的唯一目的是向我们的hook_views_query_alter()实现发送信号,它需要执行一些替换菜单。
这里的技巧是检查给定查询是否包含“下载”或“侦听”字段。如果是这样,我们将从查询中删除字段并将其替换为子查询。该功能的实现如下。
function mta_views_query_alter(&$view, &$query) {
foreach ($query->fields as $field_key => &$field_values) {
if ($field_values['table'] == 'users') {
switch ($field_values['field']) {
case 'downloads':
unset($query->fields[$field_key]);
$query->add_field(null, "(SELECT COUNT(*) FROM {fileusage} fu WHERE fu.externaluser = {users}.uid AND fu.action = 0)", $field_key);
break;
case 'listens':
unset($query->fields[$field_key]);
$query->add_field(null, "(SELECT COUNT(*) FROM {fileusage} fu WHERE fu.externaluser = {users}.uid AND fu.action = 1)", $field_key);
break;
}
}
}
}
请注意,我们正在为子查询重用已删除字段的别名。这样,Views会认为从子查询返回的值实际上来自虚拟字段(毕竟不存在)。
那是。我们没有得到笛卡尔联接,并且“下载”和“监听”都正确计数。
在需要子查询继承过滤器值之前,我一直使用sbrattla的解决方案。现在,我使用views_field_view模块嵌入执行计数查询的单独视图。我可以通过上下文过滤器值,以经由嵌入式视图 views_filterfield模块,使得可作为视场(从而令牌)滤波器值(我写)。
计数查询现在可以工作并继承主查询上公开的筛选器。