Où puis-je savoir comment créer un filtre exposé personnalisé pour les vues 3 et D7?

18

J'essaie d'apprendre à créer un filtre exposé personnalisé pour un module contribué (sélectionnez ou autre). J'ai trouvé ce tutoriel pour Drupal 6 mais le code ne semble pas fonctionner immédiatement sur Drupal 7.

J'ai également essayé de regarder le code dans le module de sélection hiérarchique, mais il semble être beaucoup plus complexe que ce que j'essaie de faire.

Quelqu'un a-t-il des suggestions de tutoriels ou de modules qui implémentent des filtres exposés personnalisés d'une manière relativement simple (par exemple, pas un grand nombre de gestionnaires personnalisés comme le module de localisation) que je peux apprendre?

Patrick Kenny
la source

Réponses:

6

Réponse courte: nulle part.

Mais vous pouvez trouver des informations ici et là.

Le premier endroit à regarder est dans les sources de vues, en particulier la mise en œuvre des filtres existants, en commençant par les plus simples.

Personnellement, j'ai participé à ce fil conducteur très instructif mais pas totalement satisfaisant, comme vous le verrez si vous allez le lire. Je pense que les informations ici sont utiles, et je peux au moins dire qu'elles étaient exactes au moment où elles ont été écrites.

Countzero
la source
2
Voici une conférence du dernier Drupalcon que je viens de découvrir et comprend des informations incroyablement utiles, y compris la mention de la partie Views de la documentation d' api.drupal.org que je ne connaissais pas. C'est le meilleur point de départ pour le développement de vues que je connaisse jusqu'à présent.
Countzero
10

Je rôdais sur Internet en essayant de trouver la réponse à la même question et voici ce que j'ai en résultat:

  1. Implémentez plusieurs hooks dans votre module personnalisé. Remplacez modulenameet filternamepar vos noms réels.

    /**
     * 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. Créez un dossier nommé à l' incintérieur de votre dossier de module et créez un fichier nommé à modulename_handler_filter_filtername.inccet endroit (voir le code ci-dessus pour une référence implicite à ce fichier). N'oubliez pas d'utiliser les noms de module et de filtre réels.

  3. Collez le code suivant dans ce modulename_handler_filter_filtername.incfichier. Le code que j'ai utilisé pour cet exemple crée un ensemble de boutons radio qui présentent des années. Vous pouvez donc filtrer les nœuds par année de création, en utilisant uniquement les années au cours desquelles les nœuds ont été créés.

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

C'est tout ce dont vous avez besoin pour que le filtre exposé personnalisé le plus simple fonctionne!

Notez que l'utilisation FROM_UNIXTIMEen condition de SELECTrequête peut ralentir votre base de données.

je suis étrange
la source
d'abord: merci! le meilleur guide de tous les temps !, deuxième: pour ceux qui recherchent une utilisation plus avancée de query (), voir views_handler_filter_numeric.inc
hkoosha
En outre, il y a un usage plus élégant où vous n'avez pas à écrire la requête et substitutions manuellement, comme: $this->query->add_where($this->options['group'], $real_field_name, $this->value['value'], $this->operator);. Il peut être trouvé dans le lien ci-dessus.
hkoosha
2
Cela fonctionne pour moi sur Drupal 7. Cependant, pour que cela fonctionne, j'ai dû 1) Supprimer l'implémentation de la fonction hook_views_handler et 2) Ajouter ceci au fichier .info: files [] = inc / modulename_handler_filter_filtername.inc 3) J'ai basé ces deux changements sur ce post 4) Merci beaucoup!
Roger