Direkt zum Inhalt

Module und Theme niemals gleich benennen - oder: warum mein hook zweimal ausgeführt wird?

veröffentlicht von gngn am Mo, 06/08/2015 - 08:33

Neulich musste ich beim Debuggen feststellen, dass ein von mir in einem eigenen Modul geschriebener Hook (konkret war es hook_form_alter) bei einem Seitenaufruf zweimal ausgeführt wurde.

Abgesehen von unnötig ausgeführtem Code, ist das zwar unschön und irritierend, aber damit kann mensch in Zeiten begrenzter Software-Budgets vielleicht noch leben - wird die gleiche Anpassung eben zweimal ausgeführt, mir doch egal...

Spätestens wenn in dem Hook aber etwas durchgeführt wird, das wirklich nur einmal gemacht werden darf (z.B. Zugriff auf externes System), haben wir ein Problem, Houston.

Nach etwas Rumgesuche habe ich den Grund dafür gefunden:

  • neben dem eigenen Modul gab es auch ein eigenes Theme
  • beide hießen naheliegenderweise so wie das Projekt (als Beispiel my_project)
  • ergo hießen Modul und Theme gleich!

Kurz gesagt hat das den Nebeneffekt, dass eine z.B. im .module stehenden Hook-Implementierung my_project_form_alter() aus Drupal-Sicht

  • den Hook zweimal anbietet:  einmal fürs Modul und einmal fürs Theme
  • und dementsprechend auch zweimal aufgerufen wird

Etwas genauer geschieht in drupal_alter() folgendes:

  • Zuerst holt sich Drupal per module_implements($hook) alle Module, die den Hook implementieren
  • findet (neben evtl. anderen Modulen) mein Modul my_project mit my_project_form_alter()
  • und merkt sich die entsprechenden Funktionen in einem Array $functions.
  • Dann wird für das aktuelle Theme geschaut, ob es eine Funktion <theme>_<hook> anbietet
  • Und zwar mittels if (function_exists('my_project_form_alter')
  • Mein Theme heißt my_project... also wird my_project_form_alter() erneut gefunden!
  • Schwupps landet die Funktion nochmal in $functions
  • dann wird noch jede gesammelte Funktion aufgerufen
  • et voila: doppelter Aufruf von my_project_form_alter()!

Also: niemals Modul und Theme gleich nennen!

Btw: drush fnh form_alter (ebenso fn-hook, hook) zeigt schnell alle Module, die form_alter implementieren.

Neuen Kommentar schreiben