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.10.3. Arbeiten mit Feldern in Drupal. Erstellen Sie Ihren eigenen Feldtyp, Widget und Formatter zum Einfügen von Videos von Youtube.

27/05/2025, by Ivan

Menu

In früheren Artikeln haben wir gesehen, wie der Feldtyp Link funktioniert: Storage, Widget, Formatter. In diesem Artikel erstellen wir unseren eigenen Feldtyp, um Videos von YouTube auf einer Seite in zwei verschiedenen Formaten und mit Einstellungen auszugeben.

Dieser Artikel konzentriert sich auf die Fields API. Wenn Sie jedoch einfach nur ein YouTube-Video-Feld auf Ihrer Seite hinzufügen möchten, ist es besser, das fertige Modul zu verwenden:

https://www.drupal.org/project/video_embed_field

Ich habe den gesamten Code auf GitHub im Modul drupalbook_youtube hinzugefügt, Sie können das Modul herunterladen und auf Ihrer Seite installieren:

https://github.com/levmyshkin/drupalbook8

Schauen wir uns den Code des Moduls an und ich werde versuchen zu beschreiben, wie dieser Feldtyp funktioniert:

modules/custom/drupalbook_youtube/drupalbook_youtube.info.yml

name: DrupalBook Youtube
type: module
description: Youtube embed field
core: 8.x
package: Custom

Hier definieren wir die Metadaten für das Modul.

modules/custom/drupalbook_youtube/src/Plugin/Field/FieldType/DrupalbookYoutubeItem.php

<?php
 
namespace Drupal\drupalbook_youtube\Plugin\Field\FieldType;
 
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\TypedData\DataDefinition;
 
/**
 * Plugin-Implementierung des Feldtyps 'drupalbook_youtube'.
 *
 * @FieldType(
 *   id = "drupalbook_youtube",
 *   label = @Translation("Embed Youtube video"),
 *   module = "drupalbook_youtube",
 *   description = @Translation("Output video from Youtube."),
 *   default_widget = "drupalbook_youtube",
 *   default_formatter = "drupalbook_youtube_thumbnail"
 * )
 */
class DrupalbookYoutubeItem extends FieldItemBase {
  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) {
    return [
      'columns' => [
        'value' => [
          'type' => 'text',
          'size' => 'tiny',
          'not null' => FALSE,
        ],
      ],
    ];
  }
 
  /**
   * {@inheritdoc}
   */
  public function isEmpty() {
    $value = $this->get('value')->getValue();
    return $value === NULL || $value === '';
  }
 
  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    $properties['value'] = DataDefinition::create('string')
      ->setLabel(t('Youtube video URL'));
 
    return $properties;
  }
}

Diese Klasse definiert den Feldtyp, damit Drupal weiß, was in der Datenbanktabelle für dieses Feld gespeichert wird.

Nun erstellen wir ein Widget, um Daten einzugeben:

modules/custom/drupalbook_youtube/src/Plugin/Field/FieldWidget/DrupalbookYoutubeWidget.php

<?php
 
namespace Drupal\drupalbook_youtube\Plugin\Field\FieldWidget;
 
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
 
/**
 * Plugin-Implementierung des Widgets 'drupalbook_youtube'.
 *
 * @FieldWidget(
 *   id = "drupalbook_youtube",
 *   module = "drupalbook_youtube",
 *   label = @Translation("Youtube video URL"),
 *   field_types = {
 *     "drupalbook_youtube"
 *   }
 * )
 */
class DrupalbookYoutubeWidget extends WidgetBase {
 
  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $value = isset($items[$delta]->value) ? $items[$delta]->value : '';
    $element += [
      '#type' => 'textfield',
      '#default_value' => $value,
      '#size' => 32,
      '#maxlength' => 256,
      '#element_validate' => [
        [$this, 'validate'],
      ],
    ];
    return ['value' => $element];
  }
 
  /**
   * Validiert das Textfeld für die YouTube-URL.
   */
  public function validate($element, FormStateInterface $form_state) {
    $value = $element['#value'];
    if (strlen($value) == 0) {
      $form_state->setValueForElement($element, '');
      return;
    }
    if (!preg_match("#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=v\/)[^&\n]+(?=\?)|(?<=v=)[^&\n]+|(?<=youtu.be/)[^&\n]+#", $value, $matches)) {
      $form_state->setError($element, t("Youtube video URL ist nicht korrekt."));
    }
  }
}

Das Widget ermöglicht es, beim Bearbeiten der Entität Daten einzugeben. Die Validierung stellt sicher, dass die eingegebene URL eine gültige YouTube-Video-URL ist.

Nun fügen wir den Field Formatter hinzu, um die Daten auszugeben.

modules/custom/drupalbook_youtube/src/Plugin/Field/FieldFormatter/DrupalbookYoutubeThumbnailFormatter.php

<?php

namespace Drupal\drupalbook_youtube\Plugin\Field\FieldFormatter;

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

/**
 * Plugin-Implementierung des Formatters 'drupalbook_youtube_thumbnail'.
 *
 * @FieldFormatter(
 *   id = "drupalbook_youtube_thumbnail",
 *   module = "drupalbook_youtube",
 *   label = @Translation("Displays video thumbnail"),
 *   field_types = {
 *     "drupalbook_youtube"
 *   }
 * )
 */
class DrupalbookYoutubeThumbnailFormatter extends FormatterBase {

  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $elements = [];

    foreach ($items as $delta => $item) {
      preg_match("#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=v\/)[^&\n]+(?=\?)|(?<=v=)[^&\n]+|(?<=youtu.be/)[^&\n]+#", $item->value, $matches);

      if (!empty($matches)) {
        $content = '';
        $elements[$delta] = [
          '#type' => 'html_tag',
          '#tag' => 'p',
          '#value' => $content,
        ];
      }
    }

    return $elements;
  }
}

Dieser Formatter zeigt das Vorschaubild des Videos mit einem Link zum YouTube-Video an.

Jetzt ein komplexerer Formatter mit Template und Einstellmöglichkeiten:

modules/custom/drupalbook_youtube/src/Plugin/Field/FieldFormatter/DrupalbookYoutubeVideoFormatter.php

<?php
 
namespace Drupal\drupalbook_youtube\Plugin\Field\FieldFormatter;
 
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
 
/**
 * Plugin-Implementierung des Formatters 'drupalbook_youtube_video'.
 *
 * @FieldFormatter(
 *   id = "drupalbook_youtube_video",
 *   module = "drupalbook_youtube",
 *   label = @Translation("Displays Youtube video"),
 *   field_types = {
 *     "drupalbook_youtube"
 *   }
 * )
 */
class DrupalbookYoutubeVideoFormatter extends FormatterBase {
 
  /**
   * {@inheritdoc}
   */
  public static function defaultSettings() {
    return [
      'width' => '600',
      'height' => '450',
    ] + parent::defaultSettings();
  }
 
  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state) {
    $elements['width'] = [
      '#type' => 'textfield',
      '#title' => t('Youtube video width'),
      '#default_value' => $this->getSetting('width'),
    ];
    $elements['height'] = [
      '#type' => 'textfield',
      '#title' => t('Youtube video height'),
      '#default_value' => $this->getSetting('height'),
    ];
 
    return $elements;
  }
 
  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $elements = [];
    $width = $this->getSetting('width');
    $height = $this->getSetting('height');
 
    foreach ($items as $delta => $item) {
      preg_match("#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=v\/)[^&\n]+(?=\?)|(?<=v=)[^&\n]+|(?<=youtu.be/)[^&\n]+#", $item->value, $matches);
 
      if (!empty($matches)) {
        $elements[$delta] = [
          '#theme' => 'drupalbook_youtube_video_formatter',
          '#width' => $width,
          '#height' => $height,
          '#video_id' => $matches[0],
        ];
      }
    }
 
    return $elements;
  }
 
  /**
   * {@inheritdoc}
   */
  public function settingsSummary() {
    $summary = [];
 
    $settings = $this->getSettings();
 
    if (!empty($settings['width']) && !empty($settings['height'])) {
      $summary[] = t('Video size: @width x @height', ['@width' => $settings['width'], '@height' => $settings['height']]);
    }
    else {
      $summary[] = t('Define video size');
    }
 
    return $summary;
  }
}

Am Anfang stehen die üblichen Namespaces und Annotations.

Der Klassennamen endet auf Formatter, um anzuzeigen, dass es sich um einen Field Formatter handelt.

Wir definieren Standard-Einstellungen für die Bildgröße und ein Einstellungsformular, das auf der Seite "Anzeige verwalten" erscheint.

Die Methode settingsSummary() liefert eine Zusammenfassung, die in der Feldbeschreibung angezeigt wird.

Die wichtigste Methode ist viewElements(), in der wir die Daten vorbereiten und ein Template aufrufen:

$elements[$delta] = [
  '#theme' => 'drupalbook_youtube_video_formatter',
  '#width' => $width,
  '#height' => $height,
  '#video_id' => $matches[0],
];

Im Modul selbst registrieren wir das Template:

modules/custom/drupalbook_youtube/drupalbook_youtube.module

/**
 * Implements hook_theme().
 */
function drupalbook_youtube_theme() {
  return [
    'drupalbook_youtube_video_formatter' => [
      'variables' => ['width' => 600, 'height' => 450, 'video_id' => NULL],
    ],
  ];
}

Das Template selbst liegt hier:

modules/custom/drupalbook_youtube/templates/drupalbook-youtube-video-formatter.html.twig

{#
/**
 * @file
 * Standard-Theme-Implementierung für ein einfaches Youtube-Video.
 *
 * Verfügbare Variablen:
 * - width: Breite des Youtube-Videos.
 * - height: Höhe des Youtube-Videos.
 * - video_id: Youtube-Video-ID.
 *
 * @see template_preprocess()
 * @see template_drupalbook_youtube_video_formatter()
 *
 * @ingroup themeable
 */
#}
{% spaceless %}
  <iframe width="{{ width }}" height="{{ height }}" src="https://www.youtube.com/embed/{{ video_id }}" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
{% endspaceless %}

Jetzt können Sie das YouTube-Video-Feld erstellen und auf der Seite verwenden:

Feld erstellen

Damit beenden wir die Erstellung benutzerdefinierter Felder und wenden uns der Entity API zu, wo wir eigene Entitätstypen erstellen werden.