Dodaj KRYTERIA FILTRÓW do widoków programowo

18

Chcę dodać / zmodyfikować filter criteriaprogramowo.

Na przykład, dla widoku dodałem filtr „Adres e-mail”, którego wartość jest potrzebna do dynamicznej zmiany, należy ustawić na identyfikator e-mail bieżącego zalogowanego użytkownika.

Jak to osiągnąć? Więcej informacji znajduje się w załączonym obrazku. Proszę pomóż.

wprowadź opis zdjęcia tutaj

Shafiul
źródło

Odpowiedzi:

24

Użyj Devel moduł i dpm($view)i dpm($query)po można umieścić jak „[email protected]” do „wartości” pola znaleźć w pic. Zobacz strukturę obiektu / tablicy widoku i zapytanie z danych wyjściowych devel.

Następnie użyj funkcji hook_views_query_alter(&$view, &$query)w swoim module, aby wybrać warunek filtru warunku GDZIE i ustawić go na żądaną wartość.

Coś jak:

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
źródło
Wielkie dzięki! Czy możesz mi powiedzieć, gdzie najpierw mam pisać dpm($view);?
Shafiul,
tworzysz moduł niestandardowy i umieszczasz w nim powyższą funkcję. Hak uruchomi się, jeśli widoki są włączone i zobaczysz $ view i $ zapytanie u góry strony po włączeniu modułu niestandardowego i modułu Devel. Następnie po prostu zmień mój kod, aby nazwa twojego widoku nazywała go w ... i aby wartości $ query działały z twoim dokładnym zapytaniem ...
tenken
To świetna odpowiedź. W Drupal 7 faktycznie robisz: $ query-> gdzie [1] ['warunki'] [2] ['wartość'] = $ user-> e
Artur Kędzior
Osobiście uważam, że odpowiedź przy użyciu poniższych haków jest znacznie lepsza drupal.stackexchange.com/a/200870/9634
kbrinner
6

Oto alternatywa:

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

Wiem, że powinieneś prawdopodobnie ustawić to za pomocą jakiejś ezoterycznej, skomplikowanej metody, ale jeśli chcesz tylko szybkiego i brudnego dostępu bez bałaganu, doprowadzi cię to.

rix
źródło
5

Lepiej byłoby zmienić je w zaczepach niż w czasie renderowania, aby nie wpływać na wydajność witryny i buforowanie. Wziąłem wiek, aby dowiedzieć się, że hook_views_pre_build () odpala za późno, potrzebujesz hook_views_pre_view () .

Znalazłem odniesienie do używania $ view-> add_item (), ale walczyłem o przykłady, poniżej było moje rozwiązanie do filtrowania zestawu terminów taksonomicznych, aby zawierały tylko niektóre słowniki:

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

Edytuj notatkę : Ten komentarz do do group pomógł mi dowiedzieć się, jak uzyskać filtry widoków, $view->display_handler->get_option('filters')a następnie je zastąpić $view->display_handler->override_option('filters', $filters);.

Duncanmoo
źródło
2

Miałem podobny problem, ale próbowałem przekazać wiele argumentów do filtra. Użyłem metody „views_get_view”, ale przekazałem argumenty do widoku. Mam nadzieję, że to komuś pomoże. Możesz zastąpić dowolny typ argumentu lub wartość własnymi potrzebami:

Do samego widoku dodałem filtry kontekstowe (z zestawu pól ustawień widoku zaawansowanego). Pierwszy to „treść: ma identyfikator terminu taksonomii”. Drugi to „content: nid” z zaznaczonym polem „zezwól na wiele” i pole wyboru „wyklucz” (z zestawu pól „więcej” w wyskakującym oknie filtru kontekstowego).

args [] = „1”; // Identyfikator terminu
args [] = „1 + 2 + 3”; // Identyfikatory węzłów do wykluczenia / włączenia

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

Aktualizacja: zapomniałem wspomnieć, że w ramach wartości filtru kontekstowego może być konieczne wybranie kodu php i zwrócenie przekazanych argumentów widoku. Np .:

return $ view-> args [1];
Seb
źródło
1

W Drupal 8 możesz użyć ViewExecutable::setHandler($display_id, $type, $id, $item)programowego ustawienia filtra.

Vlledo
źródło
4
Ta odpowiedź może być nieco bardziej szczegółowa na temat tego, dlaczego to działa. Często lubię linkować i cytować strony dokumentacji. Pomoże to pytającemu dowiedzieć się więcej o interfejsie API Drupala i pomoże znaleźć informacje dla siebie w przyszłości.
mradcliffe
1

Oto przykład, w jaki sposób programowo można dodawać kryteria filtrowania w 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(), '=');
  }
}

Powyższe zapytanie doda kryteria filtrujące węzły, w których field_custom_criteriapole jest równe aktualnie wybranemu językowi.

Więcej informacji można znaleźć w dokumentacji: hook_views_query_alter

estrar
źródło
0

Na podstawie powyższej odpowiedzi @ Duncanmoo , którą uważam za najlepszą, dodałem do mojego widoku następujące filtry - pomyślałem, że będą to użyteczne przykłady na wypadek, gdybyś nie próbował filtrować na podstawie taksonomii, do której się odwołujesz, ale zamiast tego na jednostce lub 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
źródło