Где я могу узнать о том, как создать настраиваемый фильтр для представлений 3 и D7?


18

Я пытаюсь узнать, как создать пользовательский фильтр для добавленного модуля (выберите или другой). Я нашел это руководство для Drupal 6, но, похоже, код не работает "из коробки" на Drupal 7.

Я также попытался просмотреть код в модуле иерархического выбора, но он кажется гораздо более сложным, чем то, что я пытаюсь сделать.

Есть ли у кого-нибудь предложения для учебных пособий или модулей, которые реализуют пользовательские открытые фильтры относительно простым способом (например, не огромное количество пользовательских обработчиков, таких как модуль определения местоположения), из которых я могу извлечь уроки?

Ответы:


6

Краткий ответ: никуда.

Но вы можете найти бит информации здесь и там.

Первое, на что нужно обратить внимание, это источники в Views, в частности реализация существующих фильтров, начиная с более простых.

Лично я принимал участие в этой теме, которая была очень поучительной, но не вполне удовлетворительной, как вы увидите, прочитав ее. Я думаю, что информация здесь полезна, и я могу, по крайней мере, сказать, что она была точной на момент написания.


2
Вот конференция последнего Drupalcon, которую я только что обнаружил, и содержит невероятно полезную информацию, в том числе упоминание части Views в документации api.drupal.org, о которой я не знал. Это лучшее начальное место для разработки Views, о которой я знаю до сих пор.
Countzero

10

Я бродил по Интернету, пытаясь найти ответ на тот же вопрос, и вот что я получил в результате:

  1. Реализуйте несколько хуков в вашем пользовательском модуле. Замените modulenameи filternameвашими настоящими именами.

    /**
     * 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. Создайте папку с именем incвнутри вашей папки модуля и создайте файл с именем modulename_handler_filter_filtername.incтам (см. Код выше для неявной ссылки на этот файл). Не забудьте использовать настоящие имена модулей и фильтров.

  3. Вставьте следующий код в этот modulename_handler_filter_filtername.incфайл. Код, который я использовал для этого примера, создает набор переключателей, отображающих годы. Таким образом, вы можете фильтровать узлы по годам создания, используя только годы, в которых были созданы узлы.

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

Это все, что вам нужно, чтобы получить простейший пользовательский фильтр!

Обратите внимание, что использование FROM_UNIXTIMEв условии SELECTзапроса может замедлить вашу базу данных.


первое: спасибо! лучшее руководство в мире !, второе: для тех, кто ищет более сложное
hkoosha

Кроме того , есть более элегантное использование , где вы не должны написать запрос и замену вручную, например: $this->query->add_where($this->options['group'], $real_field_name, $this->value['value'], $this->operator);. Это можно найти по ссылке выше.
hkoosha

2
Это работает для меня на Drupal 7. Однако, чтобы сделать эту работу, мне пришлось: 1) Удалить реализацию функции hook_views_handler и 2) Добавить это в файл .info: files [] = inc / modulename_handler_filter_filtername.inc 3) Я основал эти два изменения на этот пост 4) Большое спасибо!
Роджер

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.