web-dev-qa-db-fra.com

Comment créer un filtre exposé personnalisé?

J'essaie de créer un filtre exposé personnalisé dans les vues 3 de Drupal 7

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

Quelqu'un a mis un exemple de code dans l'URL ci-dessus, mais il semble que ce soit dans les vues 2!? Est-ce que quelqu'un sait comment le faire dans les vues 3.

Dans le module:

/**
 * 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;
}

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

Il y a un module qui fournit quelques exemples ici: https://www.drupal.org/project/views_plugin_examples . C'est limité mais a un exemple de filtre exposé.

Discussion générale ici: https://api.drupal.org/api/views/views.api.php/group/views_plugins/7

Dans les grandes lignes:

  1. Créer un module personnalisé, avec un sous-répertoire appelé "vues"

  2. Dans votre fichier .info, ajoutez une ligne: files[] = views/MODULE_handler_filter_FILTERNAME.inc Votre filtre n'apparaîtra jamais si vous oubliez cela!

  3. Dans le fichier .module, ajoutez une implémentation de hook_views_api ():

    function MODULE_views_api() {
      return array(
        'api' => 3,
        'path' => drupal_get_path('module', 'MODULE') . '/views',
      );
    }
    
  4. Dans le sous-répertoire des vues, vous devrez créer deux fichiers, MODULE.views.inc et MODULE_handler_filter_FILTERNAME.inc

  5. Dans MODULE.views.inc, vous devrez implémenter:

hook_views_data_alter () - pour un nouveau filtre sur un type d'entité existant qui a déjà l'intégration des vues, ce qui est plus courant OU

hook_views_data () - pour fournir l'intégration des vues pour votre entité personnalisée, y compris les filtres.

La documentation de l'API est disponible pour les deux fonctions.

Un exemple rapide:

    function MODULE_views_data_alter(&$data) {
       if ( isset($data['users']) && !isset($data['users']['FILTERNAME']) ) {
        $data['users']['FILTERNAME'] = array(
          'real field' => 'uid', // name of entity field to which filter applies
          'title' => t('HUMAN READABLE NAME OF FILTER'),
          'help' => t('HELP TEXT'),
          'filter' => array(
            'handler' => 'MODULE_handler_filter_FILTERNAME',
          ),
        );
      }
    }
  1. Tout le vrai travail se passe dans MODULE_handler_filter_FILTERNAME.inc. Ce fichier définit une nouvelle classe qui implémente votre filtre, la classe MODULE_handler_filter_FILTERNAME.

Vous souhaiterez généralement étendre l'une des classes de gestionnaires de filtres de vues existantes pour tirer parti du code existant. Beaucoup d'entre eux se trouvent dans les sous-répertoires du répertoire du module de vues. Les filtres de base se trouvent dans le sous-répertoire "handlers", mais de nombreux filtres plus complexes peuvent être trouvés enfouis dans les sous-répertoires du sous-répertoire "modules". Les gestionnaires de filtres de vues que vous trouverez sont la meilleure documentation pour implémenter un filtre, ainsi que pour étendre un filtre existant, et vous devriez les lire.

Normalement, votre classe de filtre personnalisée a) ajoutera des champs au formulaire de paramètres du filtre étendu, b) dans le cas d'un filtre exposé, modifiera le widget exposé, puis c) implémentera une méthode query () qui fait le vrai travail, basée sur les paramètres enregistrés et les entrées du widget exposé.

12
Giles B

Ran dans le même problème et compris, ressemble à l'op originale a le même problème.

Lorsque vous définissez votre formulaire de filtre exposé dans value_form (), la clé que vous utilisez dans le tableau doit être la même que celle utilisée dans view_data (ou views_data_alter).

par exemple. dans mon cas:

function value_form(&$form, &$form_state) {

  parent::value_form($form, $form_state);

  $form['users']['welcome_email_sent'] = array(
    '#type' => 'select',
    '#options' => array(
      0 => '- Any -',
      1 => 'Welcome Email',
      2 => 'Notification Email',

    ),
    '#title' => t('Email History'),
  );

  return $form;

}

Et..

function ca_email_history_views_data_alter(&$data) {

  $data['users']['welcome_email_sent'] = array(
    'title' => t('Welcome email sent'),
    'help' => t('Filter based on e-mails the user has received'),
    'filter' => array(
      'handler' => 'ca_email_history_welcome_email_sent_handler',
    ),
  );

  return $data;

}

Remarquez comment les deux ont la clé comme 'welcome_email_sent', si je les change pour qu'ils ne correspondent plus au problème où la fonction query () n'est jamais appelée se produit à nouveau.

0
Fool