欢迎各位兄弟 发布技术文章
这里的技术是共享的
Drupal Views让你可透过界面设定所需条件,轻松抓取特定资料。不过开发者创意无限,Views架构没可能完全满足您的要求。在此时,可以考虑使用hook_views_query_alter()修改/增强Views预设不能满足的条件。
引用Drupal Taiwan论坛上一问题作例子:
做出一个列表,当使用者登入后,可以看到同一组别的成员
对于Views,这类列表本是很简单,但要实现时却发现问题:Views 只能过滤登入使用者的ID (User: Current)。要以登入使用者的角色或其他因素似乎有点难度。
在主题中,我提出了使用Contextual的方案,问题的确能解决,但你的URL将变成:my-group-member/{使用者的组别}。也不太完美。(另外,也提及了Views PHP,估计也能达成效果,但笔者想更深入地看看万能的方法)
不能确认原发问者需求,为此教程,笔者定义组员列表规格:
列表中只能看到同一组别的成员(此教学中,我们将要列出K Team 成员)
URL:example.com/ my-group-member
透过Profile增加一个Team ( field_team )选择栏位,包括选项:K Team | Drupal Team
在此略过写模组的基本需要。我们来建立一个View,然后如下图设置。(为了说的更清晰,笔者去除了多余的设定)
我们增加了User: Team (= Drupal Team)。这并不是我们想要的,但没关系,因为即将下来透过程式码进行修改。
此时,如果你有打开SQL预览,可以对比增加Filter Criteria前后的SQL变化。没错,会写程式的你应看懂Views是在做什么..
( [admin/structure/views/settings] -> Live preview settings -> Show the SQL query)
Views将一个资料库表关连了,并设定了WHERE过滤条件。所以,我们最终要改变的将是WHERE条件中的IN('Drupal Team')为当前使用者的Team。
***下面程式码包含了详细注释,由上至下细看***
(dpm是Drupal Devel模组的Debug Function )
/**
* hook_views_query_alter
* 模組名_views_query_alter
*/
function alterquery_views_query_alter(&$view, &$query) {
// 看看有什麼東西
dpm($view, 'Views 的所有資訊');
dpm($query, 'Views SQL 查詢');
if (
// Views 的 Machine Name
$view->name == 'my_group_member'
// Views 頁面 Machine Name (收藏在設定頁面的 Advanced 裏)
&& $view->current_display == 'page'
)
{
if(!isset($user)) { // $user 是保存當前使用者資訊的變數。在這裏我們檢查有否載入
$user = user_load($GLOBALS['user']->uid);
}
dpm($user, '當前使用者資訊');
/**
* $user_team = $user->field_team['und'][0]['value'];
* 上面這行較直接,但之前談過,由於 Drupal 是支援多語言,這不是最好的方法。
* 看:https://notabluescreen.com/field_get_items
*/
$team = field_get_items('user', $user, 'field_team');
$user_team = $team[0]['value'];
dpm($team, '使用者組別資訊');
/**
* [K-1]我們需要修改 field_data_field_team.field_team_value 這一項
*/
foreach ($query->where['1']['conditions'] as $key => $value) {
if ($query->where['1']['conditions'][$key]['field'] == 'field_data_field_team.field_team_value') {
$query->where['1']['conditions'][$key]['value'][0] = $user_team;
break;
}
}
// 看看有沒有正確修改
dpm($query, '修改後的Views SQL 查詢');
}
}
清除Drupal Caches,重新整理网页,应有其效果了!
(到此为止,要是看不懂,猜想还没达到PHP基本水平。好好再学学PHP 。 )
上面[K-1]处的我们使用了FOREACH语句。只要你掌握到所需的资料表,你还可以取消Filter Criteria: User: Team (= Drupal Team),及将该处程式码替代为:
// 增加上面關聯的資料表
$query->add_table('field_data_field_team');
// 增加 WHERE 條件 (不難看出吧!跟上面 [K-1] 的程式碼是對應的)
$query->add_where(0, 'field_data_field_team.field_team_value', array($user_team), 'in');
除了注释,实际只有十行左右。附上测试模组。
Kay.LDrupal , Drupal 7 , Drupal API ,hook_views_query_alter() , views ,模组
HI,谢谢你还特别写了这篇文章!
现在已经可以成功列出同一个群组的使用者了!!
但我有一个小小的问题@@~
我的如果筛选的话是这个样子
WHERE (( (field_data_field_unit_select.field_unit_select_tid = '6') ))
我也有修改了一下您附上的测试模组
$query->add_where(0, 'field_data_field_unit_select.field_unit_select_tid', array($user_unit), 'in');
想问,最后那个in,是什么意思?
因为我看到你附上的是IN ('Drupal Team')
而我的因为是下拉选单,所以是数字然后是”=”
可是没有特别修改,也可以列出同个单位的人耶!
如果是IN('Drupal Team', 'Kay Team'),即为包含'Drupal Team' 及'Kay Team' 的意思。所以只有一个IN('6'),就等同于= '6'。可以Google “mySQL IN OR mySQL WHERE IN OR SQL IN” 看看相关教学
IN部分是Comparison Operators (比较运算子),应能接受以下所有:
http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html
喔喔ˊ~
了解了!!
谢谢你的解说^^
您好,我想请问hook_views_query_alter() 这个函数该要怎么使用?
我的情况是有一份由Webform产生,再建立的View资料表。
系统预设是捞出所有DATA,我想仅显示当前登入使用者的资料;但是系统的FILTER CRITERIA条件没有这条件,所以目前想透过SQL方式修改WHERE条件看能否可行。
但是hook_views_query_alter的说明文件第一行我就看不懂了Q_Q
(不知该怎么确定那个MODULENAME(随意自订吗?),及该放入哪个资料夹,跟该从哪个路径可以执行/触发它)
恳请指导
您好,抱歉回覆晚了。
有User:Current这个条件,但是没有效果,SQL的指令如下
SELECT webform_submissions.sid AS sid, webform_views.name AS webform_views_name, webform_views._date AS webform_views__date, webform_submissions.nid AS webform_submissions_nid, webform_submissions.uid AS webform_submissions_uid, node.uid AS node_uid, webform_views.sid AS webform_views_sid
FROM
{webform_submissions} webform_submissions
LEFT JOIN { webform_views} webform_views ON webform_submissions.sid = webform_views.sid
LEFT JOIN {webform_submissions} webform_submissions_webform_views ON webform_views.sid = webform_submissions_webform_views.sid
LEFT JOIN {node} node ON webform_submissions.nid = node.nid
LEFT JOIN {users} users_node ON node.uid = users_node.uid
WHERE (users_node.uid = '1')
我的View是照论坛上的文章做成的。
华生,我发现盲点了!
原来是我Relationship设错了,原先我设为[Webform views : Sid] 改为[Webform submissions: 使用者]后,就可以使用[User: Current]等条件来过滤为当前使用者。
终于解决啦,非常感谢QAQ
“我想仅显示当前登入使用者的资料;但是系统的FILTER CRITERIA条件没有这条件”
“User: Current” 没有吗? 你仔细看看
请教如何显示用户的各种类型的内容?每个用户一行,每个类型显示两个field。
实际上每个用户的每个内容类型最多一个node。
研究views join没成功。因为内容在相同的table里。
来自 https://notabluescreen.com/hook_views_query_alter/