以编程方式在视图中添加FILTER CRITERIA


18

我想以filter criteria编程方式添加/修改。

例如,对于一个视图,我添加了一个“电子邮件地址”过滤器,该过滤器的值需要动态更改,需要将其设置为当前登录用户的电子邮件ID。

如何实现呢?请参阅附件图像以获取更多详细信息。请帮忙。

在此处输入图片说明

Answers:


24

使用Devel模块,dpm($view)然后dpm($query)将“ test@email.com”这样的图片放入图片中的“值”字段中。查看视图的对象/数组结构,并从devel输出中查询。

然后,使用hook_views_query_alter(&$view, &$query)模块中的函数定位WHERE条件过滤条件,并将其设置为所需的值。

就像是:

function MYMODULE_views_query_alter(&$view, &$query) {
  global $user;
  dpm($view, __FUNCTION__);
  dpm($query, __FUNCTION__);
  if ($view->name === 'your_view_machine_name') {
    // This will only work as-is if you always have something in the filter by
    // default, I guess. This hook runs always so you could just put
    // 'test@test.com' as the email to filter by in views and this
    // will always override it. I'm sure there is a cleaner way to put
    // the filter dynamically at runtime. But i think thats more complex
    // php that customizes a view.
    //
    // The index 2 below is the index of the condition for the email filter.
    // Your $query structure may be different in your dpm() of the View $query.
    $query->where[1]['conditions'][2]['field']['value'] = $user->email;
  }
}

非常感谢!你能告诉我我先在哪里写信dpm($view);吗?
Shafiul 2012年

您将创建一个自定义模块并将其放置在上面的函数中。如果启用了视图,则挂钩将触发,并且在启用自定义模块和Devel模块后,您将在页面顶部看到$ view和$ query。然后只需更改我的代码以在其中使用视图的计算机名称即可,并使$ query值与您的确切查询一起使用...
tenken 2012年

那是一个很好的答案。在Drupal 7中,您实际上是这样做的:$ query-> where [1] ['conditions'] [2] ['value'] = $ user-> email
ArturKędzior16年

我个人认为使用下面的钩子的答案要好得多drupal.stackexchange.com/a/200870/9634
kbrinner

6

这是一个替代方案:

$view = views_get_view('view_machine_name');
$view->init_display('default');
$view->display_handler->display->display_options['filters']['your_filter_name']['default_value'] = 'your_value';
$view->is_cacheable = FALSE;  
$view->execute();
print $view->render();

我知道您可能应该使用一些深奥的,令人费解的方法进行设置,但是如果您只想快速而又肮脏地访问而又不弄乱它,那将使您到达那里。


5

最好在挂钩中而不是在渲染时更改它们,以免破坏站点性能和缓存。花了我很长时间才弄清楚hook_views_pre_build()触发得太晚了,您需要hook_views_pre_view()

我找到了使用$ view-> add_item()的参考,但为示例而苦苦挣扎,以下是我的解决方案,用于过滤一组分类法术语以仅包含某些词汇:

function MODULENAME_views_pre_view(&$view, &$display_id, &$args) {

  if ($view->name == 'VIEWNAME' && $display_id == 'DISPLAYID') {
    // Add all the terms of a vocabulary to the terms listing widget select field
    $vids = array();
    $vocab = taxonomy_vocabulary_machine_name_load('vocab_name');
    $vids[ $vocab->vid ] = $vocab->vid;

    // Get the existing filters
    $filters = $view->display_handler->get_option('filters');

    if (empty($filters['vid'])) {
      // There is no vid filter so we have to add it
      $view->add_item(
        $view->current_display,
        'filter',
        'taxonomy_term_data',
        'vid',
        array(
          'operator' => 'in',
          'value' => $vids,
          'group' => 1
        )
      );
    }
    else {
      // Add to pre-existing filter
      foreach($vids as $vid) {
        $filters['vid']['value'][ $vid ] = $vid;
      }
      $view->display_handler->override_option('filters', $filters);
    }
  }
}

编辑说明:对do小组的评论帮助我弄清楚了如何使用来获取视图过滤器$view->display_handler->get_option('filters'),然后使用来覆盖它们$view->display_handler->override_option('filters', $filters);


2

我遇到过类似的问题,但是尝试将多个参数传递给过滤器。我使用了“ views_get_view”方法,但是将参数传递给视图。希望对您有所帮助。您可以根据需要替换任何参数类型或值:

我已经向视图本身添加了上下文过滤器(来自高级视图设置字段集)。第一个是“内容:具有分类术语ID”。第二个是“内容:nid”,其中“允许多个”已选中,“排除”复选框已选中(来自上下文过滤器弹出窗口中的“更多”字段集)。

args [] ='1'; //条款ID
args [] ='1 + 2 + 3'; //要排除/包含的节点ID

$ view = views_get_view($ view_name);
$ view-> init();
$ view-> set_display($ display);
$ view-> set_arguments($ args);
$ view-> execute();
$ view->结果

更新:我忘了提及,在上下文过滤器值中,您可能需要选择php代码并返回传入的视图参数。例如:

返回$ view-> args [1];

1

在Drupal 8中,您可以用来ViewExecutable::setHandler($display_id, $type, $id, $item)以编程方式设置过滤器。


4
这个答案可能会更加冗长。我经常喜欢链接和引用文档页面。这将帮助询问者更多地了解Drupal API,并在将来为自己找到信息。
mradcliffe

1

这是一个示例,说明如何在Drupal 8中以编程方式添加过滤条件:

/**
 * @param ViewExecutable $view
 * @param QueryPluginBase $query
 *
 * Sets a custom custom filter criteria (takes current language into account)
 */
function MODULE_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
  if ($view->storage->id() === 'my_view_id') {
    $query->addWhere(0, 'node__field_custom_criteria.field_custom_criteria_value', \Drupal::languageManager()->getCurrentLanguage()->getId(), '=');
  }
}

上面的查询将添加一个条件,该条件将过滤field_custom_criteria字段等于当前所选语言的节点。

可以在文档中找到更多信息:hook_views_query_alter


0

根据我认为最好的@ Duncanmoo回答,我在视图中添加了以下过滤器-认为这些示例将非常有用,以防您不尝试根据引用的分类法而是基于引用的实体或NID:

function [MYMODULE]_views_pre_view(&$view, &$display_id, &$args) {
  if (($view->name == '[your view name]') && ($display_id == '[your display id]')) {
    // Get referenced service - example for entity reference.
    $node = menu_get_object();
    $node_wrapper = entity_metadata_wrapper('node', $node->nid);
    $referenced_service = $node_wrapper->field_service_ref->value();
    // Add service id as a filter to view.
    $filters = $view->display_handler->get_option('filters');
    if (empty($filters['field_service_ref_target_id'])) {
      // Only display operations nodes that reference the same service.
      $view->add_item(
        $display_id,
        'filter',
        'field_data_field_service_ref',
        'field_service_ref_target_id',
        array(
          'operator' => '=',
          'value' => ['value' => $referenced_service->id],
          'group' => 1
        )
      );
    }
    // Add nid as a filter to view - example for NID filter
    if (empty($filters['nid'])) {
      // Don't include current operation in list of related operations.
      $view->add_item(
        $display_id,
        'filter',
        'node',
        'nid',
        array(
          'operator' => '!=',
          'value' => ['value' => $node->nid],
          'group' => 1
        )
      );
    }
  }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.