Onde posso aprender sobre como criar um filtro exposto personalizado para as Views 3 e D7?

18

Estou tentando aprender como criar um filtro exposto personalizado para um módulo contribuído (selecionado ou outro). Encontrei este tutorial para o Drupal 6, mas o código não parece funcionar imediatamente no Drupal 7.

Também tentei examinar o código no módulo de seleção hierárquica , mas parece ser muito mais complexo do que estou tentando fazer.

Alguém tem alguma sugestão de tutoriais ou módulos que implementam filtros expostos personalizados de uma maneira relativamente simples (por exemplo, não há um grande número de manipuladores personalizados como o módulo de localização) com os quais posso aprender?

Patrick Kenny
fonte

Respostas:

6

Resposta curta: lugar nenhum.

Mas você pode encontrar informações aqui e ali.

O primeiro lugar a procurar é nas fontes do Views, principalmente na implementação de filtros existentes, começando pelos mais simples.

Pessoalmente, participei deste tópico que foi muito instrutivo, mas não completamente satisfatório, como você verá se o ler. Eu acho que as informações aqui são úteis e, pelo menos, posso dizer que eram precisas no momento em que foram escritas.

Countzero
fonte
2
Aqui está uma conferência do último Drupalcon que eu acabei de descobrir e inclui informações incrivelmente úteis, incluindo a menção de Views, parte da documentação do api.drupal.org, que eu não conhecia. Este é o melhor ponto de partida para o desenvolvimento do Views que eu conheço até agora.
Countzero 27/03
10

Eu estava rondando a Internet tentando encontrar respostas para a mesma pergunta e é isso que eu tenho como resultado:

  1. Implemente vários ganchos em seu módulo personalizado. Substitua modulenamee filternamepor seus nomes reais.

    /**
     * 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. Crie uma pasta nomeada incdentro da pasta do módulo e crie um arquivo nomeado modulename_handler_filter_filtername.inclá (consulte o código acima para referência implícita a esse arquivo). Não esqueça de usar nomes reais de módulos e filtros.

  3. Cole o seguinte código nesse modulename_handler_filter_filtername.incarquivo. O código que usei para este exemplo cria um conjunto de botões de opção que apresentam anos. Portanto, você pode filtrar os nós por ano criado, usando apenas os anos em que os nós foram criados.

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

É tudo o que você precisa para que o filtro exposto personalizado mais simples funcione!

Observe que o uso FROM_UNIXTIMEna condição de SELECTconsulta pode reduzir a velocidade do seu banco de dados.

eu sou estranho
fonte
primeiro: obrigado! o melhor guia sempre !, segundo: para aqueles que estão à procura de um uso mais avançado de consulta (), consulte views_handler_filter_numeric.inc
hkoosha
Além disso, há um uso mais elegante, onde você não tem que escrever a consulta e substituições manualmente, como: $this->query->add_where($this->options['group'], $real_field_name, $this->value['value'], $this->operator);. Pode ser encontrado no link acima.
hkoosha
2
Funciona para mim no Drupal 7. No entanto, para fazer esse trabalho, eu tive que 1) Excluir a implementação da função hook_views_handler e 2) Adicionar isso ao arquivo .info: files [] = inc / modulename_handler_filter_filtername.inc 3) Baseei essas duas alterações sobre este post 4) Muito obrigado!
Roger