Drupal 7 + Views 3 + hook_views_data + Date field (Filter / Sortierung / Handler)

Drupal 7 custom date field filter handlers

Drupal 7 Views (3) und Datums-Felder hassen sich! Das Gefühl werde ich einfach nicht los... besonders schlimm ist es anscheinend mit der Dokumentation dieser Kombination. Aber gehen wir ins Detail... und kommen zur Lösung!

Hintergrund

Alles was ich benötigte, war die Views-Einbindung eines eigenen MySQL Datenbank-Feldes vom Typ "datetime". Konkret ist ein Datum mit Uhrzeit enthalten. Soweit so gut.

Die Einbindung in Drupal Views ist mittels hook_views_data gar nicht so schwer. Einige gute Anleitungen dazu gibt es schon, z.B. hier.

Es konnte dementsprechend relativ schnell das Datum im View angezeigt und danach sortiert werden.
Nun benötigte ich eine Möglichkeit auf ein Datum (ohne Uhrzeit!) zu filtern. Also eine Tages-Granularität.

Dass dies generell sogar mit Popup-Datumsauswahl möglich ist, weiß man aus dem date.module (welches wir später hier unbedingt benötigen!).
Aber keine Chance, es gab zwar eine Filter-Maske für das Datumsfeld, allerdings ohne Auswahl der Granularität oder gar eine Popup Datumsauswahl. Wie ging es also weiter?

Erste Lösungsansätze

Zunächst machte ich mich nun mit dieser eingeschränkten Funktionalität nach einer Datumsauswahl. Wie ich schnell herausfand, wird eine jQuery Datumsauswahl für Datumsfelder vom better_exposed_filters.module angeboten. Getestet und leider enttäuscht! Die Datumsauswahl liefert ein falsches Format für das Filter-Feld. Und darüber hinaus sieht man in der Views Abfrage schnell, dass auch bei einer Datumsauswahl immer eine Umwandlung in den UNIX Timestamp stattfindet, sodass eine Uhrzeig angenommen wird. Wir wählen also z.B. den 07.02.2014, Drupal ergänzt von sich aber eine sekundengenaue Filterung. Das klappt so nicht!

Weiter recherchieren führt zum dürftig dokumentierten Erfolg!

Nach weiterer Recherche stieß ich zum Glück auf einen besseren Lösungsansatz mittels date.module!
Wie diese Beiträge dokumentieren, kann man sich an der Implementierung des date.module orientieren, um die Views-Felder mit dessen Funktionalität und Know-How auszustatten:
https://drupal.org/comment/7986659#comment-7986659

Mit noch etwas mehr Recherche findet man dann auch die zugehörige Implementierung:
http://drupalcontrib.org/api/drupal/contributions!date!date_views!date_views.module/function/date_views_date_views_fields/7

hook_date_views_fields() ist also die Lösung des Drupal Views Datums-Rätsels!

Wie implementiere ich es nun?

Die Lösung besteht aus 2 Komponenten. Zum einen muss das entsprechende Datumsfeld in hook_views_data mit den richtigen Handlern ausgestattet werden. Da ich generell die sekundengenaue Darstellung benötige, habe ich mich für folgende Variante entschieden:

  1. $data['example_table']['my_datetime_field'] = array(
  2.     'title' => t('Example DateTime'),
  3.     'help' => t('An example Datetime field.'),
  4.     'field' => array(
  5.       'handler' => 'views_handler_field_datetime',
  6.       'click sortable' => TRUE),
  7.     'is date' => TRUE,
  8.     'sort' => array('handler' => 'views_handler_sort_date'),
  9.     'filter' => array(
  10.       'handler' => 'date_views_filter_handler',
  11.       'empty field name' => t('Undated'),
  12.       'is date' => TRUE)
  13.     );

Es ist aber durchaus denkbar, die views-Handler aus dem date.module zu verwenden, wie der oberhalb verlinkte Kommentar zeigt!

Der zweite Teil der Lösung ist die Bekanntmachung der Datenbankkonfiguration des jeweiligen Felds via hook_date_views_fields(), wie oberhalb verlinkt.
Da ich ein DATE_DATETIME Feld in MySQL verwende, nutze ich dieses.

Hier also dieser Teil:

  1. function my_module_date_views_fields($field) {
  2.   $values = array(
  3.     // The type of date: DATE_UNIX, DATE_ISO, DATE_DATETIME.
  4.     'sql_type' => DATE_DATETIME,
  5.     // Timezone handling options: 'none', 'site', 'date', 'utc' .
  6.     'tz_handling' => 'site',
  7.     // Needed only for dates that use 'date' tz_handling.
  8.     'timezone_field' => '',
  9.     // Needed only for dates that use 'date' tz_handling.
  10.     'offset_field' => '',
  11.     // Array of "table.field" values for related fields that should be
  12.     // loaded automatically in the Views SQL.
  13.     'related_fields' => array(),
  14.     // Granularity of this date field's db data.
  15.     'granularity' => array('year', 'month', 'day', 'hour', 'minute', 'second'),
  16.   );
  17.  
  18.   switch ($field) {
  19.     case 'example_table.my_datetime_field':
  20.       return $values;
  21.   }
  22. }

Mit diesen zwei Komponenten erhält man in den Views Filtern dann ENDLICH die richtige Auswahl mit Granularität, Datums-Popup und vor allem einer absolut korrekten Umsetzung als Views Query.

Die Umsetzung durch Views und das Date Modul ist genial und die beiden hassen sich (doch) nicht. Aber die Dokumentation ist sehr schwierig zu finden (finde ich!).

Wenn Euch dieser Beitrag geholfen hat, freue ich mich über Eure Kommentare. Ich hoffe, dass ich damit dem ein oder anderen viel unnötige Recherche ersparen konnte.

Comments

Post new comment

The content of this field is kept private and will not be shown publicly.

More information about formatting options