Adicionar critérios de filtro em modos de exibição programaticamente

18

Quero adicionar / modificar um filter criteriaprogramaticamente.

Por exemplo, para uma visualização, adicionei um filtro "Endereço de email" cujo valor é necessário para alterar dinamicamente, é necessário definir o ID de email do usuário conectado no momento.

Como conseguir isso? Por favor, veja a imagem em anexo para mais detalhes. Por favor ajude.

insira a descrição da imagem aqui

Shafiul
fonte

Respostas:

24

Use o módulo Develdpm($view) e dpm($query)depois de colocar como "[email protected]" no campo "value" encontrado na sua foto. Veja a estrutura do objeto / matriz da visualização e consulta da saída devel.

Em seguida, use a função hook_views_query_alter(&$view, &$query)em seu módulo para direcionar a condição do filtro de condição WHERE e defina-a com o valor desejado.

Algo como:

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
    // '[email protected]' 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;
  }
}
tenken
fonte
Muito Obrigado! Você pode, por favor, me dizer onde eu primeiro escrevo dpm($view);?
Shafiul 25/03/12
você cria um módulo personalizado e coloca a função acima. O gancho será acionado se as visualizações estiverem ativadas e você verá as $ view e $ query na parte superior da página depois de ativar o módulo personalizado e o módulo Devel. Em seguida, basta alterar o código para ter o nome de máquina do seu ponto de vista, em ... e fazendo a valores de consulta $ trabalho com sua consulta exata ...
Tenken
Essa é uma ótima resposta. No Drupal 7 você realmente faz: $ query-> where [1] ['conditions'] [2] ['value'] = $ user-> email
Artur Kędzior
Pessoalmente, acho que a resposta usando os ganchos abaixo é muito melhor drupal.stackexchange.com/a/200870/9634
kbrinner 10/01
6

Aqui está uma alternativa:

$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();

Eu sei que você provavelmente deve definir isso usando algum método esotérico e complicado, mas se você quiser apenas um acesso rápido e sujo sem mexer com isso, você chegará lá.

rix
fonte
5

Seria preferível alterá-los nos ganchos, e não no tempo de renderização, para que você não comprometa o desempenho e o cache do site. Levei idade para descobrir que o hook_views_pre_build () é acionado tarde demais, você precisa do hook_views_pre_view () .

Encontrei referência ao uso de $ view-> add_item (), mas lutei por exemplos. Abaixo estava minha solução para filtrar um conjunto de termos de taxonomia para incluir apenas determinados vocabs:

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);
    }
  }
}

Nota de edição : este comentário no grupo me ajudou a descobrir como obter os filtros de visualizações usando $view->display_handler->get_option('filters')e depois substituí-los usando $view->display_handler->override_option('filters', $filters);.

Duncanmoo
fonte
2

Eu tive um problema semelhante, mas onde tentando passar vários argumentos para um filtro. Eu usei o método "views_get_view", mas passando argumentos para a exibição. Eu espero que isso ajude alguém. Você pode substituir qualquer tipo ou valor de argumento para suas necessidades:

Adicionei filtros contextuais à própria exibição (no conjunto de campos das configurações avançadas da exibição). O primeiro é um "conteúdo: possui ID do termo de taxonomia". O segundo é "content: nid" com a caixa de seleção "permitir vários" marcada e "excluir" (a partir do conjunto de campos 'more' no pop-up de filtro contextual).

args [] = '1'; // ID do termo
args [] = '1 + 2 + 3'; // IDs do nó a serem excluídos / incluídos

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

Atualização: esqueci de mencionar, dentro dos valores contextuais do filtro, você pode precisar selecionar o código php e retornar os argumentos de exibição passados. Por exemplo:

retornar $ view-> args [1];
Seb
fonte
1

No Drupal 8, você pode usar ViewExecutable::setHandler($display_id, $type, $id, $item)para definir um filtro programaticamente.

vlledo
fonte
4
Esta resposta pode ser um pouco mais detalhada sobre por que isso funciona. Muitas vezes, gosto de vincular e citar as páginas de documentação. Isso ajudaria o solicitante a aprender mais sobre a API Drupal e a encontrar informações para si no futuro.
Mrclcliffe 02/09/19
1

Aqui está um exemplo de como os critérios de filtro podem ser adicionados programaticamente no 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(), '=');
  }
}

A consulta acima adicionará um critério que filtra os nós onde o field_custom_criteriacampo é igual ao idioma atualmente selecionado.

Mais informações podem ser encontradas nos documentos: hook_views_query_alter

estrar
fonte
0

Baseado em @ Duncanmoo 's resposta acima que eu sentia era melhor, eu adicionei os seguintes filtros para meu ponto de vista - pensei que estes seriam exemplos úteis no caso de você não estavam tentando filtro baseado em uma taxonomia referenciados, mas em vez disso, uma entidade referenciado ou um 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
        )
      );
    }
  }
}
kbrinner
fonte