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
20/06/2025, by Ivan

Menu

Dieses Tutorial wurde ursprünglich auf Web Wash veröffentlicht. Allerdings fragte Berdir, ob ich das Tutorial hier veröffentlichen könnte, also ist es jetzt hier.

Ein Modul in Drupal 7 ermöglicht das Speichern von Code-Beispielen/Snippets in einem Feld. Es enthält ein benutzerdefiniertes Feld namens „Snippets Field“ und zeigt drei Formularelemente an: Beschreibung, Quellcode und Syntax-Hervorhebungsmodus (welche Programmiersprache).

Nun ist es an der Zeit, das Modul auf Drupal 8 zu aktualisieren.

In diesem Tutorial zeige ich Ihnen, wie ich ein „grundlegendes“ benutzerdefiniertes Feld in Drupal 8 erstellt habe. Ich werde nicht auf Details zu PSR-4, Annotations oder Plugins eingehen, da das Tutorial sonst zu umfangreich wäre.

Stattdessen werde ich Links zu anderen Seiten bereitstellen, die diese Konzepte näher erklären.

Wenn Sie detaillierte Dokumentation zur Field API in Drupal 8 suchen, schauen Sie sich folgende Reihen an:

In Drupal 8 werden Felder nicht mehr mit Hooks wie in Drupal 7 implementiert. Stattdessen werden sie mit der neuen Drupal 8 Plugin-API erstellt. Das bedeutet, dass wir statt Hooks Klassen für Widgets, Formatter und Field Items definieren. Die meisten Drupal 7 Hooks wie hook_field_schema oder hook_field_is_empty sind jetzt Methoden in Klassen.

Schritt 1: Implementierung des Feldelements

Der erste Schritt ist, eine Klasse namens SnippetsItem zu definieren, die FieldItemBase erweitert.

1. In Drupal 8 werden Klassen per PSR-4 geladen.

Daher müssen wir die Klasse SnippetsItem in der Datei module/src/Plugin/Field/FieldType/SnippetsItem.php anlegen.

/**
 * @file
 * Enthält \Drupal\snippets\Plugin\Field\FieldType\SnippetsItem.
 */

namespace Drupal\snippets\Plugin\Field\FieldType;

use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\TypedData\DataDefinition;

Wir definieren den Namespace Drupal\snippets\Plugin\Field\FieldType und verwenden drei Klassen:

  • Drupal\Core\Field\FieldItemBase
  • Drupal\Core\Field\FieldStorageDefinitionInterface
  • Drupal\Core\TypedData\DataDefinition

2. Nun müssen wir Details des Feldes wie ID, Label, Standard-Widget und Formatter angeben. Dies ersetzt hook_field_info aus Drupal 7.

In Drupal 8 werden viele Info-Hooks durch Annotations ersetzt.

/**
 * Plugin-Implementierung des Feldtyps 'snippets'.
 *
 * @FieldType(
 *   id = "snippets_code",
 *   label = @Translation("Snippets Field"),
 *   description = @Translation("Dieses Feld speichert Code-Snippets in der Datenbank."),
 *   default_widget = "snippets_default",
 *   default_formatter = "snippets_default"
 * )
 */
class SnippetsItem extends FieldItemBase { }

Die Annotationen benötigen keine weitere Erklärung. Achten Sie darauf, dass default_widget und default_formatter auf die ID der Widget- und Formatter-Annotation verweisen, nicht auf die Klasse.

Mehr über Annotationen erfahren Sie auf der Seite zur plugin-basierten Annotation in drupal.org.

3. Nun fügen wir Methoden hinzu, beginnend mit schema().

In Drupal 7 definiert man das Feldschema mit hook_field_schema. In Drupal 8 definieren wir das Schema in der Methode schema() der Klasse SnippetsItem.

Die Schema API Dokumentation beschreibt die Struktur des Schemas.

/**
 * {@inheritdoc}
 */
public static function schema(FieldStorageDefinitionInterface $field) {
  return [
    'columns' => [
      'source_description' => [
        'type' => 'varchar',
        'length' => 256,
        'not null' => FALSE,
      ],
      'source_code' => [
        'type' => 'text',
        'size' => 'big',
        'not null' => FALSE,
      ],
      'source_lang' => [
        'type' => 'varchar',
        'length' => 256,
        'not null' => FALSE,
      ],
    ],
  ];
}

4. Nun fügen wir die Methode isEmpty() hinzu, die bestimmt, wann das Feld als leer gilt – analog zu hook_field_is_empty in Drupal 7.

/**
 * {@inheritdoc}
 */
public function isEmpty() {
  $value = $this->get('source_code')->getValue();
  return $value === NULL || $value === '';
}

5. Als letztes implementieren wir die Methode propertyDefinitions().

/**
 * {@inheritdoc}
 */
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
  $properties['source_description'] = DataDefinition::create('string')
    ->setLabel(t('Snippet description'));

  $properties['source_code'] = DataDefinition::create('string')
    ->setLabel(t('Snippet code'));

  $properties['source_lang'] = DataDefinition::create('string')
    ->setLabel(t('Programming Language'))
    ->setDescription(t('Language of the snippet code'));

  return $properties;
}

Diese Methode definiert die Datentypen der Feldwerte. Das „Snippets“-Feld hat nur drei Werte: Beschreibung, Code und Sprache, daher werden diese als Strings definiert.

Mehr dazu finden Sie im Abschnitt Wie die Entity API die Typed Data API implementiert auf drupal.org.

Hier klicken für die vollständige Datei. Hinweis: Sie muss noch auf PSR-4-Spezifikationen aktualisiert werden. Mehr dazu unter https://www.drupal.org/node/2128865.

Schritt 2: Implementierung des Feld-Widgets

Nachdem wir den Feldelement-Klasse definiert haben, erstellen wir nun das Feld-Widget. Die Klasse heißt SnippetsDefaultWidget und erweitert WidgetBase.

1. Erstellen Sie die Datei SnippetsDefaultWidget.php im Verzeichnis module/src/Plugin/Field/FieldWidget/SnippetsDefaultWidget.php.

/**
 * @file
 * Enthält \Drupal\snippets\Plugin\Field\FieldWidget\SnippetsDefaultWidget.
 */

namespace Drupal\snippets\Plugin\Field\FieldWidget;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;

Der Namespace lautet Drupal\snippets\Plugin\Field\FieldWidget. Verwenden Sie außerdem:

  • Drupal\Core\Field\FieldItemListInterface
  • Drupal\Core\Field\WidgetBase
  • Drupal\Core\Form\FormStateInterface

2. Definieren Sie das Widget mit einer Annotation. Dies ersetzt hook_field_widget_info aus Drupal 7.

/**
 * Plugin-Implementierung des 'snippets_default' Widgets.
 *
 * @FieldWidget(
 *   id = "snippets_default",
 *   label = @Translation("Snippets default"),
 *   field_types = {
 *     "snippets_code"
 *   }
 * )
 */
class SnippetsDefaultWidget extends WidgetBase { }

Stellen Sie sicher, dass das Attribut field_types die Feldtypen-IDs enthält, hier snippets_code, entsprechend der ID in @FieldType.

3. Implementieren Sie die Methode formElement(), um das eigentliche Widget-Formular zu definieren – ähnlich zu hook_field_widget_form in Drupal 7.

/**
 * {@inheritdoc}
 */
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {

  $element['source_description'] = [
        '#title' => $this->t('Description'),
        '#type' => 'textfield',
        '#default_value' => isset($items[$delta]->source_description) ? $items[$delta]->source_description : NULL,
      ];
  $element['source_code'] = [
        '#title' => $this->t('Code'),
        '#type' => 'textarea',
        '#default_value' => isset($items[$delta]->source_code) ? $items[$delta]->source_code : NULL,
      ];
  $element['source_lang'] = [
        '#title' => $this->t('Source language'),
        '#type' => 'textfield',
        '#default_value' => isset($items[$delta]->source_lang) ? $items[$delta]->source_lang : NULL,
      ];
  return $element;
}

Hier klicken für die vollständige Datei. Hinweis: Muss noch auf PSR-4 aktualisiert werden, mehr dazu unter https://www.drupal.org/node/2128865.

Schritt 3: Implementierung des Feldformatierers

Der letzte Teil ist der Feldformatierer, den wir mit der Klasse SnippetsDefaultFormatter erstellen, die FormatterBase erweitert.

1. Erstellen Sie die Datei SnippetsDefaultFormatter.php in module/src/Plugin/Field/FieldFormatter/SnippetsDefaultFormatter.php.

/**
 * @file
 * Enthält \Drupal\snippets\Plugin\Field\FieldFormatter\SnippetsDefaultFormatter.
 */

namespace Drupal\snippets\Plugin\Field\FieldFormatter;

use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Field\FieldItemListInterface;

Der Namespace lautet Drupal\snippets\Plugin\Field\FieldFormatter. Verwenden Sie außerdem:

  • Drupal\Core\Field\FieldItemListInterface
  • Drupal\Core\Field\FormatterBase

2. Definieren Sie den Formatter mit einer Annotation, ähnlich wie bei Widget und FieldType – entspricht hook_field_formatter_info aus Drupal 7.

/**
 * Plugin-Implementierung des 'snippets_default' Formatierers.
 *
 * @FieldFormatter(
 *   id = "snippets_default",
 *   label = @Translation("Snippets default"),
 *   field_types = {
 *     "snippets_code"
 *   }
 * )
 */
class SnippetsDefaultFormatter extends FormatterBase { }

3. Implementieren Sie die Methode viewElements(), die den eigentlichen Formatierungsprozess übernimmt, ähnlich zu hook_field_formatter_view in Drupal 7.

/**
 * {@inheritdoc}
 */
public function viewElements(FieldItemListInterface $items, $langcode) {
  $elements = [];
  foreach ($items as $delta => $item) {
    // Ausgabe mit dem Theme 'snippets_default' rendern.
    $source = [
      '#theme' => 'snippets_default',
      '#source_description' => $item->source_description,
      '#source_code' => $item->source_code,
    ];

    $elements[$delta] = ['#markup' => drupal_render($source)];
  }

  return $elements;
}

Ich verwende hier ein benutzerdefiniertes Template snippets_default, um die Snippets zu rendern, damit die Logik und das HTML nicht direkt in der Methode viewElements() liegen.

Hier klicken für die vollständige Datei. Hinweis: Muss noch auf PSR-4 aktualisiert werden, mehr dazu unter https://www.drupal.org/node/2128865.

Fazit

Das größte Änderungskonzept in Drupal 8 ist, dass Felder mit der Plugin API erstellt werden statt mit Hooks. Sobald Sie dies verstehen, ist das Erstellen von Feldern ähnlich wie in Drupal 7. Viele Methoden in Drupal 8 entsprechen Hooks in Drupal 7.

Wenn Sie Snippets testen möchten, laden Sie die 8.x-dev Version herunter und probieren Sie es aus.

Drupal’s online documentation is © 2000-2020 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License.