logo

Extra Block Types (EBT) - Neue Erfahrung im Layout Builder❗

Extra Block Types (EBT) - gestylte, anpassbare Blocktypen: Diashows, Registerkarten, Karten, Akkordeons und viele andere. Eingebaute Einstellungen für Hintergrund, DOM Box, Javascript Plugins. Erleben Sie die Zukunft der Layouterstellung schon heute.

Demo EBT-Module EBT-Module herunterladen

❗Extra Absatztypen (EPT) - Erfahrung mit neuen Absätzen

Extra Paragraph Types (EPT) - analoger, auf Absätzen basierender Satz von Modulen.

Demo EPT-Module EPT-Module herunterladen

Scroll

9.8.1. hook_form_alter() – Hinzufügen von Submit- und Validierungsfunktionen zu bestehenden Formularen

27/05/2025, by Ivan

In einer der vorherigen Lektionen haben wir gelernt, was Hooks sind. In dieser Lektion arbeiten wir praktisch mit hook_form_alter() und fügen einem bestehenden Formular neue Funktionalitäten hinzu.

Beispiele für den Code finden Sie auf GitHub:
https://github.com/levmyshkin/drupalbook8

Wir beginnen mit hook_form_alter(). Um einen Hook im Modul hinzuzufügen, müssen wir eine Datei namens MODULENAME.module anlegen, hier also drupalbook.module. Diese PHP-Datei enthält unsere Hooks und Hilfsfunktionen, während der Rest besser in separaten Dateien und Klassen im src-Ordner organisiert wird. Zunächst genügt ein öffnendes PHP-Tag.

drupalbook

Wenn Sie PhpStorm verwenden, können Sie beim Schreiben eines Hook-Namens eine automatische Auswahl nutzen, die die Funktionsparameter für Sie einfügt:

function

Sie müssen „hook“ durch Ihren Modulnamen ersetzen. Drupal ruft die Funktion dann an den entsprechenden Stellen auf. Das Ergebnis sollte so aussehen:

/**
 * Implements hook_form_alter().
 */
function drupalbook_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {

}

In $form, $form_state und $form_id werden das Formular, dessen Status und die Formular-ID gespeichert, die wir in der getFormId() Methode definiert haben:

function getFormId() {
  return 'drupalbook_admin_settings';
}

Alternativ können Sie die ID auch im HTML mit einem DOM-Inspector prüfen:

settings

Dabei ersetzen Sie Bindestriche (-) durch Unterstriche (_). Die Formular-ID kann bei AJAX-Aufrufen mit Nummern enden (z. B. drupalbook-admin-settings-0), Sie brauchen aber nur den Basisnamen ohne Nummer.

Wir beschränken nun den Hook-Code auf dieses spezielle Formular, da hook_form_alter() für alle Formulare ausgeführt wird:

if ($form_id == 'drupalbook_admin_settings') {
  // Unser Code hier.
}

Fügen wir für das API-Key-Formular Platzhalter in die Textfelder ein, damit Benutzer wissen, was sie eintragen sollen:

if ($form_id == 'drupalbook_admin_settings') {
  $form['drupalbook_api_key']['#attributes']['placeholder'] = 'API key';
  $form['drupalbook_api_client_id']['#attributes']['placeholder'] = 'API client ID';
}

Leeren Sie danach den Cache, damit die Änderungen wirksam werden.

api key

Auch wenn #attributes nicht offiziell in der Dokumentation für Textfelder steht, funktioniert es, um HTML-Attribute wie class, placeholder etc. zu setzen.

Validierung: Wir wollen sicherstellen, dass der API-Key mit „google“ beginnt. Normalerweise schreibt man dazu eine validateForm() Methode im Formular, aber oft arbeiten wir mit Formularen aus Contrib-Modulen. Daher fügen wir eine eigene Validierungsfunktion per hook_form_alter() hinzu:

$form['#validate'][] = 'drupalbook_settings_validate';

Das #validate-Array enthält alle Callback-Funktionen, die Drupal zur Validierung des Formulars aufruft. Nun definieren wir die Funktion in drupalbook.module:

/**
 * Custom validation callback.
 */
function drupalbook_settings_validate(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {

}

Die eigentliche Validierung sieht so aus:

function drupalbook_settings_validate(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
  if (strpos($form_state->getValue('drupalbook_api_key'), 'google') === FALSE) {
    $form_state->setErrorByName('drupalbook_api_key', t('API Key must start from "google".'));
  }
}

Wir verwenden den strengen Vergleich ===, da strpos() 0 zurückgibt, wenn „google“ am Anfang steht, und 0 == FALSE in PHP sonst true wäre.

Bei falscher Eingabe wird eine Fehlermeldung angezeigt und das Formular wird nicht abgesendet:

settings form

Submit: Nach erfolgreicher Validierung ruft Drupal die Submit-Funktionen auf. Wir hängen eine eigene Callback-Funktion an:

$form['#submit'][] = 'drupalbook_settings_submit';

Und definieren diese Funktion in drupalbook.module:

/**
 * Custom submit callback.
 */
function drupalbook_settings_submit(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
  \Drupal::messenger()->addStatus(
    t(htmlentities('Insert API key in your <head> tag: <script src="https://example.com"></script>.'))
  );
}

Wir verwenden htmlentities(), damit HTML-Tags als Text angezeigt werden und nicht ausgeführt werden.

Die Meldung erscheint nur, wenn keine Validierungsfehler vorliegen:

drupalbook form

Früher wurde drupal_set_message() verwendet, heute ist der Messenger-Service Standard.

Hier der gesamte Code der drupalbook.module:

/**
 * Implements hook_form_alter().
 */
function drupalbook_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id == 'drupalbook_admin_settings') {
    $form['drupalbook_api_key']['#attributes']['placeholder'] = 'API key';
    $form['drupalbook_api_client_id']['#attributes']['placeholder'] = 'API client ID';

    $form['#validate'][] = 'drupalbook_settings_validate';
    $form['#submit'][] = 'drupalbook_settings_submit';
  }
}

/**
 * Custom validation callback.
 */
function drupalbook_settings_validate(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
  if (strpos($form_state->getValue('drupalbook_api_key'), 'google') === FALSE) {
    $form_state->setErrorByName('drupalbook_api_key', t('API Key must start from "google".'));
  }
}

/**
 * Custom submit callback.
 */
function drupalbook_settings_submit(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
  \Drupal::messenger()->addStatus(
    t(htmlentities('Insert API key in your <head> tag: <script src="https://example.com"></script>.'))
  );
}

Das war unsere Lektion zum Form API. Wir werden noch öfter Validierung, Submit und AJAX behandeln.

Codebeispiele gibt es auf GitHub:
https://github.com/levmyshkin/drupalbook8