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

Form API Drupal 7: Erstellen von Formularen in Drupal

26/05/2025, by Ivan

In den vorherigen Lektionen haben wir uns mit den Hooks hook_block_info(), hook_block_view(), hook_menu(), hook_permission() vertraut gemacht und können nun beliebig viele Seiten und Blöcke programmatisch erstellen. In dieser Lektion lernen wir das Form API von Drupal 7 kennen, um Formulare zu erstellen. Wir erstellen ein Formular zur Administration der Modulfunktionen und versuchen, möglichst viele bereits bekannte Hooks zu verwenden, um die Fähigkeiten zu festigen.

Zu Beginn geben wir 3 Blöcke aus, das sollte für euch kein Problem sein.

function sitemade_block_info(){
    $blocks = array(); // leeres Array initialisieren
    $blocks[1]['info'] = 'Benutzerliste'; // Blocktitel für das Admin-Interface
    $blocks[2]['info'] = 'Nodeliste';
    $blocks[3]['info'] = 'Terminliste';
    return $blocks; // Liste der Blöcke zurückgeben
}

function sitemade_block_view($delta = ''){
    $block = array(); // leeres Block-Array initialisieren
    switch ($delta){
        case 1: // delta wie in hook_block_info() definiert
          $block['subject'] = 'Benutzer'; // Blocktitel ausgeben
          $block['content'] = ''; // leere Stringvariable initialisieren
          $query = db_select('users', 'u') // Auswahlabfrage für Benutzer
            ->fields('u', array('uid', 'name')) // Felder auswählen
            ->orderBy('u.uid', 'DESC') // absteigend sortieren
            ->range(0, 5) // fünf Benutzer auswählen
            ->execute(); // DB-Abfrage ausführen
          $users = $query->fetchAll(PDO::FETCH_ASSOC); // Ergebnis als Array holen
          foreach($users as $user){
            $block['content'] .= '<div><a href="' . base_path() . 'user/' . $user['uid'] . '">' . $user['name'] . '</a></div>';
            // base_path() gibt den Pfad zur Seitenwurzel zurück
          }
        break;
        case 2:
          $block['subject'] = 'Nodes'; // Blocktitel ausgeben
          $block['content'] = '';
          $query = db_select('node', 'n')
            ->fields('n', array('nid', 'title'))
            ->orderBy('n.nid', 'DESC')
            ->range(0, 10)
            ->execute();
          $nodes = $query->fetchAll(PDO::FETCH_ASSOC);
          foreach($nodes as $node){
            $block['content'] .= '<div><a href="' . base_path() . 'node/' . $node['nid'] . '">' . $node['title'] . '</a></div>';
        }            
        break;
        case 3:
          $block['subject'] = 'Termine'; // Blocktitel ausgeben
          $block['content'] = '';
          $query = db_select('taxonomy_term_data', 't')
            ->fields('t', array('tid', 'name'))
            ->orderBy('t.tid', 'DESC')
            ->range(0, 10)
            ->execute();
          $terms = $query->fetchAll(PDO::FETCH_ASSOC);
          foreach($terms as $term){
            $block['content'] .= '<div><a href="' . base_path() . 'taxonomy/term/' . $term['tid'] . '">' . $term['name'] . '</a></div>';
          }            
        break;
    }
    return $block;
}

Cache leeren, damit die neuen Blöcke im Admin-Bereich erscheinen. Die Blöcke im linken Sidebar ausgeben:

Drupal blocks

Nun erstellen wir eine Admin-Seite, auf der später das Verwaltungsformular für diese drei Blöcke liegen wird:

function sitemade_permission(){
    return array(
      'admin content blocks' => array(
        'title' => t('Admin content blocks'),
        'description' => t('Nodes, Users, Terms'),
      ),
    );
}

function sitemade_menu(){
    $items = array(); // Array für Menüeinträge initialisieren   
    $items['admin/config/content/content_blocks'] = array(
      'title' => 'Benutzer-, Node- und Termblöcke',
      'description' => 'Blockverwaltung',
      'page callback' => '_sitemade_content_blocks',
      'access arguments' => array('admin content blocks'),
    );
    return $items; // Liste der Seiten zurückgeben
}

function _sitemade_content_blocks(){
    $content = 'Lorem ipsum!';
    return $content;
}

Die Seite wurde erstellt, es sollte nun eine Platzhalter-Seite unter admin/config/content/content_blocks erscheinen:

Drupal admin page

Als nächstes setzen wir die Berechtigungen für Administratoren zum Zugriff auf diese Seite (dazu haben wir hook_permission() hinzugefügt).

Drupal permission

Nun ändern wir den Code der Hooks. Zunächst erstellen wir ein Administrationsformular. Was wollen wir in diesen drei Blöcken verwalten? Ich schlage vor: Blocktitel und die Anzahl der angezeigten Entitäten (Nodes, Benutzer, Terms).

Zuerst ändern wir die Eigenschaft 'page callback' im hook_menu:

function sitemade_menu(){
    $items = array();
    $items['admin/config/content/content_blocks'] = array(
      'title' => 'Benutzer-, Node- und Termblöcke',
      'description' => 'Blockverwaltung',
      'page callback' => 'drupal_get_form',
      'page arguments' => array('_sitemade_content_blocks'),
      'access arguments' => array('admin content blocks'),
    );
    return $items;
}

Beschreibung der Funktion drupal_get_form():

drupal_get_form($form_id)

Wrapper für drupal_build_form(), wenn $form_state nicht benötigt wird.

Parameter von drupal_get_form()

$form_id ist die eindeutige Kennung der Formularfunktion. Existiert diese Funktion, wird der Formular-Array-Konstruktor aufgerufen. Module, die ähnliche $form_id benötigen, können hook_forms() implementieren, um $form_id-Werte auf Konstruktorfunktionen abzubilden.

Weitere übergebene Argumente werden an die Formularfunktion angehängt. Beispiel: Das Formular node_edit benötigt das Node-Objekt, was über hook_form_alter() oder hook_FORM_ID_alter() mit $form_state['build_info']['args'] möglich ist.

Rückgabewert von drupal_get_form()

Das Formular-Array

Nun schreiben wir die Funktion _sitemade_content_blocks() um, damit sie ein Formular-Array zurückgibt.

function _sitemade_content_blocks(){
    $form = array(); // Formular-Array initialisieren
    $form['nodes-title'] = array(
      '#type' => 'textfield',
      '#title' => t('Blocktitel für Nodes'),
      '#default_value' => variable_get('node_block', ''),
      '#size' => 60,
      '#maxlength' => 64,
      '#description' => t('Blocktitel für Nodes'),
    );
    $form['node-selected'] = array(
      '#type' => 'select',
      '#title' => t('Anzahl der Nodes im Block'),
      '#options' => array(
        1 => t('1'),
        2 => t('2'),
        3 => t('3'),
        4 => t('4'),
        5 => t('5'),
        6 => t('6'),
        7 => t('7'),
        8 => t('8'),
        9 => t('9'),
        10 => t('10'),
      ),
      '#default_value' => variable_get('node_block_range', 5),
      '#description' => t('Anzahl der im Block angezeigten Nodes'),
    );    
    $form['users-title'] = array(
      '#type' => 'textfield',
      '#title' => t('Blocktitel für Benutzer'),
      '#default_value' => variable_get('user_block', ''),
      '#size' => 60,
      '#maxlength' => 64,
      '#description' => t('Blocktitel für Benutzer'),
    );    
    $form['user-selected'] = array(
      '#type' => 'select',
      '#title' => t('Anzahl der Benutzer im Block'),
      '#options' => array(
        1 => t('1'),
        2 => t('2'),
        3 => t('3'),
        4 => t('4'),
        5 => t('5'),
        6 => t('6'),
        7 => t('7'),
        8 => t('8'),
        9 => t('9'),
        10 => t('10'),
      ),
      '#default_value' => variable_get('user_block_range', 5),
      '#description' => t('Anzahl der im Block angezeigten Benutzer'),
    );        
    $form['terms-title'] = array(
      '#type' => 'textfield',
      '#title' => t('Blocktitel für Terms'),
      '#default_value' => variable_get('term_block', ''),
      '#size' => 60,
      '#maxlength' => 64,
      '#description' => t('Blocktitel für Terms'),
    );        
    $form['term-selected'] = array(
      '#type' => 'select',
      '#title' => t('Anzahl der Terms im Block'),
      '#options' => array(
        1 => t('1'),
        2 => t('2'),
        3 => t('3'),
        4 => t('4'),
        5 => t('5'),
        6 => t('6'),
        7 => t('7'),
        8 => t('8'),
        9 => t('9'),
        10 => t('10'),
      ),
      '#default_value' => variable_get('term_block_range', 5),
      '#description' => t('Anzahl der im Block angezeigten Terms'),
    );        
    $form['actions'] = array('#type' => 'actions'); // Speichern-Button hinzufügen
    $form['actions']['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Speichern'),
    );
    return $form;
}

'#type' - Elementtyp.
'#title' - Überschrift.

'#description' - Beschreibung.

'#options' - Dropdown-Optionen.
'#default_value' - Standardwert, hier laden wir gespeicherte Werte.

Das Administrationsformular sollte nun so aussehen:

Drupal admin form

Wir haben das Formular ausgegeben, jetzt müssen wir die Formularverarbeitung hinzufügen. Dafür verwenden wir die Hooks hook_formID_validate() und hook_formID_submit() für Validierung und Verarbeitung.

Formular-Generierung

Verfügbare Funktionen zur Verarbeitung und Ausgabe von HTML-Formularen in Drupal.

Drupal nutzt diese Funktionen, um die Formularverarbeitung und -anzeige kompatibel zu machen, den Code zu vereinfachen und die Menge an HTML-Code, den Module exakt generieren müssen, zu reduzieren. Die Hauptfunktion dafür ist drupal_get_form(), die den HTML-Code eines Formulars generiert. Ein Formular kann programmgesteuert ohne Benutzerinteraktion mit drupal_form_submit() erstellt werden.

drupal_get_form() akzeptiert, verarbeitet und gibt automatisch den generierten HTML-Code für Module aus. Unten ein Beispiel, wie man drupal_get_form() und andere Funktionen für die Formularerstellung nutzt.

<?php
$form = drupal_get_form('my_module_example_form');
...
function my_module_example_form($form, &$form_state) {
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Absenden'),
  );
  return $form;
}
function my_module_example_form_validate($form, &$form_state) {
  // Validierung der Eingaben.
}
function my_module_example_form_submit($form, &$form_state) {
  // Formularverarbeitung.
}
?>

Oder mit zusätzlichen Argumenten:

<?php
$extra = "extra";
$form = drupal_get_form('my_module_example_form', $extra);
...
function my_module_example_form($form, &$form_state, $extra) {
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => $extra,
  );
  return $form;
}
?>

Nun schreiben wir die Formularverarbeitung, damit die übermittelten Werte in Drupal-Variablen gespeichert werden. Installieren Sie das Modul Devel, das die Funktion dsm() bereitstellt, welche Arrays und Objekte ausgibt. Dann fügen wir im Modul noch einen Hook hinzu:

function sitemade_content_blocks_submit($form, &$form_values){
    dsm($form_values);
}

Damit werden die übermittelten Formularwerte auf dem Bildschirm ausgegeben:

drupal devel

Jetzt können wir die Werte einfach in Variablen speichern:

function sitemade_content_blocks_submit($form, &$form_values){
    //dsm($form_values);
    variable_set('node_block', $form_values['values']['nodes-title']);
    variable_set('user_block', $form_values['values']['users-title']);
    variable_set('term_block', $form_values['values']['terms-title']);
    variable_set('node_block_range', $form_values['values']['node-selected']);
    variable_set('user_block_range', $form_values['values']['user-selected']);
    variable_set('term_block_range', $form_values['values']['term-selected']);
}

Das Formular ist fertig. Nach dem Absenden werden die Werte mit variable_set() gespeichert und beim Laden der Formularfelder mit variable_get() als Standardwerte geladen.

Drupal form submit

Zum Schluss ändern wir noch hook_block_view(), damit Blocktitel und Anzahl der Links in den Blöcken mit variable_get() ausgelesen werden.

function sitemade_block_view($delta = ''){
    $block = array(); // leeres Block-Array initialisieren
    switch ($delta){
        case 1:
          $block['subject'] = variable_get('user_block', 'Benutzer'); // Blocktitel ausgeben
          $block['content'] = '';
          $query = db_select('users', 'u')
            ->fields('u', array('uid', 'name'))
            ->orderBy('u.uid', 'DESC')
            ->range(0, variable_get('user_block_range', 5))
            ->execute();
          $users = $query->fetchAll(PDO::FETCH_ASSOC);
          foreach($users as $user){
            $block['content'] .= '<div><a href="' . base_path() . 'user/' . $user['uid'] . '">' . $user['name'] . '</a></div>';
          }
        break;
        case 2:
          $block['subject'] = variable_get('node_block', 'Nodes');
          $block['content'] = '';
          $query = db_select('node', 'n')
            ->fields('n', array('nid', 'title'))
            ->orderBy('n.nid', 'DESC')
            ->range(0, variable_get('node_block_range', 5))
            ->execute();
          $nodes = $query->fetchAll(PDO::FETCH_ASSOC);
          foreach($nodes as $node){
            $block['content'] .= '<div><a href="' . base_path() . 'node/' . $node['nid'] . '">' . $node['title'] . '</a></div>';
          }
        break;
        case 3:
          $block['subject'] = variable_get('term_block', 'Terms');
          $block['content'] = '';
          $query = db_select('taxonomy_term_data', 't')
            ->fields('t', array('tid', 'name'))
            ->orderBy('t.tid', 'DESC')
            ->range(0, variable_get('term_block_range', 10))
            ->execute();
          $terms = $query->fetchAll(PDO::FETCH_ASSOC);
          foreach($terms as $term){
            $block['content'] .= '<div><a href="' . base_path() . 'taxonomy/term/' . $term['tid'] . '">' . $term['name'] . '</a></div>';
          }
        break;
    }
    return $block;
}

Nun kann man das Ergebnis auf der Startseite ansehen. Und nicht vergessen: „Cache leeren nicht vergessen“!

Drupal block