Gdzie mogę dowiedzieć się, jak utworzyć niestandardowy filtr narażony dla widoków 3 i D7?

18

Próbuję dowiedzieć się, jak utworzyć niestandardowy filtr narażony dla wniesionego modułu (wybranego lub innego). Znalazłem ten samouczek dla Drupala 6, ale wydaje się, że kod nie działa od razu po wyjęciu z pudełka na Drupal 7.

Próbowałem też spojrzeć na kod w hierarchicznym module wyboru , ale wydaje się, że jest on znacznie bardziej złożony niż to, co próbuję zrobić.

Czy ktoś ma jakieś sugestie dotyczące samouczków lub modułów, które implementują niestandardowe filtry narażone w stosunkowo prosty sposób (np. Nie ogromna liczba niestandardowych programów obsługi, takich jak moduł lokalizacji), z których mogę się uczyć?

Patrick Kenny
źródło

Odpowiedzi:

6

Krótka odpowiedź: nigdzie.

Ale tu i tam można znaleźć fragmenty informacji.

Najpierw należy zajrzeć do źródeł Widoki, szczególnie do implementacji istniejących filtrów, zaczynając od tych prostszych.

Osobiście brałem udział w tym wątku, który był bardzo pouczający, ale nie do końca satysfakcjonujący, bo zobaczysz, jeśli go przeczytasz. Myślę, że informacje tutaj są przydatne i mogę przynajmniej powiedzieć, że były dokładne w momencie ich pisania.

Countzero
źródło
2
Oto konferencja z ostatniego Drupalcona, którą właśnie odkryłem, i zawiera niezwykle przydatne informacje, w tym wzmiankę o części Widoki dokumentacji api.drupal.org , o której nie wiedziałem. To najlepsze miejsce, w którym do tej pory tworzyłem widoki, o którym wiem.
Countzero
10

Czaiłem się w Internecie, próbując znaleźć odpowiedź na to samo pytanie i oto, co mam w rezultacie:

  1. Zaimplementuj kilka haków w swoim module niestandardowym. Zamień modulenamei na filternameswoje rzeczywiste nazwiska.

    /**
     * Implements hook_views_api().
     */
    function modulename_views_api() {
      return array(
        'api' => 2,
        'path' => drupal_get_path('module', 'modulename') . '/inc',
      );
    }
    
    /**
     * Implementation of hook_views_handlers() to register all of the basic handlers
     * views uses.
     */
    function modulename_views_handlers() {
      return array(
        'info' => array(
          // path to handler files
          'path' => drupal_get_path('module', 'modulename') . '/inc',
        ),
        'handlers' => array(
          // register our custom filter, with the class/file name and parent class
          'modulename_handler_filter_filtername' => array(
            'parent' => 'views_handler_filter',
          ),
        ),
      );
    }
    
    function modulename_views_data() {
      $data = array();
    
      $data['node']['filtername'] = array(
        'group' => t('Custom'),
        'real field' => 'my_custom_filter_field',
        'title' => t('My custom filter'),
        'help' => t('Some more detailed description if you need it.'),
        'filter' => array(
          'handler' => 'modulename_handler_filter_filtername',
        ),
      );
    
      return $data;
    }
  2. Utwórz folder o nazwie incwewnątrz folderu modułu i utwórz plik modulename_handler_filter_filtername.inctam nazwany (patrz kod powyżej dla niejawnego odniesienia do tego pliku). Nie zapomnij użyć rzeczywistych nazw modułów i filtrów.

  3. Wklej następujący kod do tego modulename_handler_filter_filtername.incpliku. Kod użyty w tym przykładzie tworzy zestaw przycisków radiowych prezentujących lata. Możesz więc filtrować węzły według utworzonych lat, używając tylko lat, w których zostały utworzone węzły.

    class modulename_handler_filter_filtername extends views_handler_filter {
    
      /**
       * Options form subform for setting exposed filter options.
       */
      function value_form(&$form, &$form_state) {
        parent::value_form($form, $form_state);
    
        // get list of years from database
        $query = db_select('node', 'n');
        $query->addExpression("FROM_UNIXTIME(n.created, '%Y')", 'year');
        if (isset($this->view->filter['type'])) {
          $query->condition('n.type', $this->view->filter['type']->value, 'IN');
        }
        $result = $query->orderBy('year', 'ASC')
          ->execute()
          ->fetchAllAssoc('year');
    
        $years = array(
          '0' => t('All'),
        );
        foreach ($result as $k => $v) {
          $years[$k] = $k;
        }
    
        // create form element with options retrieved from database
        $form['value']['year'] = array(
          '#type' => 'radios',
          '#options' => $years,
          '#default_value' => end($years),
        );
      }
    
      /**
       * Alters Views query when filter is used.
       */
      function query() {
        // make sure base table is included in the query
        $this->ensure_my_table();
    
        // retrieve real filter name from view options
        // this requires 'real field' filter option to be set (see code above)
        $real_field_name = $this->real_field;
        // get the value of the submitted filter
        $value = $this->view->exposed_data[$real_field_name];
    
        // finally, alter Views query
        if (is_numeric($value) && $value != 0) {
          /* 
            Having several custom exposed filters, make sure subsitution patterns
            (e.g. :filtername_value below) don't match across different filters.
            I spent some time figuring out why all my filters had the same value.
            It looks like the query skeleton is built first and then all replacements
            are made in bulk. Prefixing value with filter name looks good imo.
          */
          $this->query->add_where_expression($this->options['group'],
            "FROM_UNIXTIME(node.created, '%Y') = :filtername_value",
            array(':filtername_value' => $value));
        }
      }
    }

To wszystko, czego potrzebujesz, aby uzyskać najprostszy niestandardowy filtr z widocznym działaniem!

Pamiętaj, że użycie FROM_UNIXTIMEwarunku SELECTzapytania może spowolnić bazę danych.

jestem dziwny
źródło
po pierwsze: dzięki! najlepszy przewodnik w historii !, po drugie: dla tych, którzy szukają bardziej zaawansowanego użycia zapytania (), zobacz views_handler_filter_numeric.inc
hkoosha
Ponadto, jest bardziej elegancki Wykorzystanie gdzie nie trzeba pisać zapytania oraz podstawienia ręcznie, jak: $this->query->add_where($this->options['group'], $real_field_name, $this->value['value'], $this->operator);. Można go znaleźć w powyższym linku.
hkoosha
2
Działa to dla mnie na Drupal 7. Jednak aby to zadziałało, musiałem 1) Usunąć implementację funkcji hook_views_handler i 2) Dodać to do pliku .info: files [] = inc / modulename_handler_filter_filtername.inc 3) Oparłem te dwie zmiany na ten post 4) Wielkie dzięki!
Roger,