logo

Palette - Maak het kleurrijk🎨

Palette - Visuele Page Builder. Je hoeft geen designer te zijn.

Live demo Palette downloaden

Scroll

9.10.3. Werken met velden in Drupal. Maak je eigen veldtype, widget en formatter voor het invoegen van video's van YouTube.

17/10/2025, by Ivan

Menu

In eerdere artikelen hebben we gezien hoe het veldtype Link werkt: Storage, Widget, Formatter. In dit artikel gaan we ons eigen veldtype maken voor het weergeven van een YouTube-video op een pagina, met twee verschillende weergaveformaten en instellingen.

Dit artikel richt zich op de Fields API, en als je gewoon een YouTube-videoveld aan je site wilt toevoegen, kun je beter de kant-en-klare module gebruiken:

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

Ik heb alle code op GitHub toegevoegd in de module drupalbook_youtube; je kunt de module downloaden en aan je site toevoegen:

https://github.com/levmyshkin/drupalbook8

Laten we de bestanden van deze module bekijken, en ik zal proberen uit te leggen hoe dit type veld werkt:

modules/custom/drupalbook_youtube/drupalbook_youtube.info.yml

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

We bepalen hiermee de metadata van de module.

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 implementation of the 'drupalbook_youtube' field type.
 *
 * @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 array(
      'columns' => array(
        'value' => array(
          '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;
  }
 
}

We maken een veldtype aan zodat Drupal weet wat er in de tabel voor dit veld zal worden opgeslagen.

<?php
 
namespace Drupal\drupalbook_youtube\Plugin\Field\FieldType;
 
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\TypedData\DataDefinition;
Definieer namespaces voor ons veldtype.

/**
 * Plugin implementation of the 'drupalbook_youtube' field type.
 *
 * @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"
 * )
 */

We schrijven een abstract voor onze klasse; vanuit deze abstractie zal Drupal de naam en machine-naam van ons veldtype afleiden.

class DrupalbookYoutubeItem extends FieldItemBase {

De naam van de klasse eindigt bij voorkeur op Item.

/**
 * {@inheritdoc}
 */
public static function schema(FieldStorageDefinitionInterface $field_definition) {
  return array(
    'columns' => array(
      'value' => array(
        'type' => 'text',
        'size' => 'tiny',
        'not null' => FALSE,
      ),
    ),
  );
}

We definiëren dat we de waarde van het veld als tekst zullen opslaan.

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

Als er een aanroep van dit veld plaatsvindt vanuit externe code, geven we een lege waarde terug voor het geval het veld leeg is.

/**
 * {@inheritdoc}
 */
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
  $properties['value'] = DataDefinition::create('string')
    ->setLabel(t('Youtube video URL'));
 
  return $properties;
}

We beschrijven onze kolommen voor de MySQL-tabel en het entiteitsobject. Als resultaat slaan we de volledige link op:

select

Nu we het veldtype hebben toegevoegd, maken we een Widget om gegevens in te voeren:

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 implementation of the 'drupalbook_youtube' widget.
 *
 * @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 += array(
      '#type' => 'textfield',
      '#default_value' => $value,
      '#size' => 32,
      '#maxlength' => 256,
      '#element_validate' => array(
        array($this, 'validate'),
      ),
    );
    return array('value' => $element);
  }
 
  /**
   * Validate the color text field.
   */
  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 is not correct."));
    }
  }
 
}

De widget maakt het mogelijk om gegevens in te voeren op het bewerkingsformulier van de entiteit.

/**
 * Plugin implementation of the 'drupalbook_youtube' widget.
 *
 * @FieldWidget(
 *   id = "drupalbook_youtube",
 *   module = "drupalbook_youtube",
 *   label = @Translation("Youtube video URL"),
 *   field_types = {
 *     "drupalbook_youtube"
 *   }
 * )
 */

In de annotatie bij de klasse moeten we het field_type vermelden dat we eerder hebben aangemaakt, namelijk drupalbook_youtube.

class DrupalbookYoutubeWidget extends WidgetBase {

Aan het einde van de klassenaam voegen we Widget toe, zodat duidelijk is dat deze klasse bedoeld is als Field Widget.