logo

Extra Block Types (EBT) - Nieuwe Layout Builder ervaring❗

Extra Block Types (EBT) - gestileerde, aanpasbare bloktypes: Slideshows, Tabs, Cards, Accordions en vele andere. Ingebouwde instellingen voor achtergrond, DOM Box, javascript-plugins. Ervaar vandaag al de toekomst van layout building.

Demo EBT-modules Download EBT-modules

❗Extra Paragraph Types (EPT) - Nieuwe Paragraphs ervaring

Extra Paragraph Types (EPT) - analoge op paragrafen gebaseerde set modules.

Demo EPT-modules Download EPT-modules

Scroll

Overzicht: een aangepast veld aanmaken

30/09/2025, by Ivan
Deze tutorial werd oorspronkelijk gepubliceerd op Web Wash. Maar Berdir vroeg of ik de tutorial hier kon plaatsen, dus bij deze.

De module in Drupal 7 maakt het mogelijk om codevoorbeelden / snippets op te slaan in een veld. Het wordt geleverd met een aangepast veld genaamd “Snippets-veld” en toont drie formelementen: beschrijving, broncode en syntax highlighting modus (welke programmeertaal).

Maar nu is het tijd om de module bij te werken naar Drupal 8.

In deze les laat ik je zien hoe ik een “basis” aangepast veld in Drupal 8 heb gemaakt. Ik zal niet in detail ingaan op PSR – 4, annotaties of plugins, anders wordt deze les enorm.

In plaats daarvan voeg ik links toe naar andere sites die dit concept verder uitleggen.

Als je echter op zoek bent naar uitgebreide documentatie over de Field API in Drupal 8, bekijk dan de volgende series:

 

In Drupal 8 worden velden niet geïmplementeerd met hooks zoals in Drupal 7. In plaats daarvan worden ze aangemaakt met behulp van de nieuwe Drupal 8 plugin API. Dit betekent dat we in plaats van hooks te implementeren een klasse definiëren voor de widget, de formatter en het velditem. De meeste hooks uit Drupal 7, zoals hook_field_schema, hook_field_is_empty en anderen, zijn nu methodes in klassen.

Stap 1: Implementatie van het velditem

Het eerste wat we moeten doen, is een klasse voor het velditem definiëren met de naam SnippetsItem, die de klasse FieldItemBase uitbreidt.

1. In Drupal 8 worden klassen geladen met behulp van PSR-4.

Dus om de klasse SnippetsItem te definiëren, moeten we een bestand SnippetsItem.php maken en dit plaatsen in “module” /src/Plugin/Field/FieldType/SnippetsItem.php

/**
 * @file
 * Contains \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;

Vervolgens voegen we in het bestand de namespace Drupal\snippets\Plugin\Field\FieldType toe en drie use-statements: Drupal\Core\Field\FieldItemBase, Drupal\Core\Field\FieldStorageDefinitionInterface en Drupal\Core\TypedData\DataDefinition.

2. Nu moeten we de feitelijke details van het veld definiëren, zoals veld-ID, label, standaardwidget, formatter enz. Dit is gelijk aan de implementatie van hook_field_info in Drupal 7.

In Drupal 8 zijn veel, zo niet alle, info-hooks vervangen door annotaties.

/**
 * Plugin implementation of the 'snippets' field type.
 *
 * @FieldType(
 *   id = "snippets_code",
 *   label = @Translation("Snippets field"),
 *   description = @Translation("This field stores code snippets in the database."),
 *   default_widget = "snippets_default",
 *   default_formatter = "snippets_default"
 * )
 */
class SnippetsItem extends FieldItemBase { }

Dus in plaats van hook_field_info te implementeren, definiëren we het veld als een annotatie in de commentaar boven de klasse.

De annotatie-attributen spreken voor zich. Zorg er gewoon voor dat default_widget en default_formatter verwijzen naar de annotatie-ID’s van de widget en de formatter, niet naar de klassen.

Wil je meer weten over annotaties, bezoek dan de documentatiepagina voor plugin-annotaties op drupal.org.

3. Nu we de klasse voor het velditem hebben, moeten we een paar methodes definiëren. De eerste die we bekijken is schema()

In Drupal 7, bij het maken van een aangepast veld, definieer je schema met hook_field_schema. In Drupal 8 definiëren we schema door een methode schema() toe te voegen in de klasse SnippetsItem.

De Schema API documentatie bevat een beschrijving van de arraystructuur en mogelijke waarden.
/**
 * {@inheritdoc}
 */
public static function schema(FieldStorageDefinitionInterface $field) {
  return array(
    'columns' => array(
      'source_description' => array(
        'type' => 'varchar',
        'length' => 256,
        'not null' => FALSE,
      ),
      'source_code' => array(
        'type' => 'text',
        'size' => 'big',
        'not null' => FALSE,
      ),
      'source_lang' => array(
        'type' => 'varchar',
        'length' => 256,
        'not null' => FALSE,
      ),
    ),
  );
}

4. Nu moeten we de methode isEmpty() toevoegen en definiëren wat een leeg velditem is. Deze methode is gelijk aan de implementatie van hook_field_is_empty in Drupal 7.

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

5. De laatste methode die we aan de klasse toevoegen is propertyDefinitions().

/**
 * {@inheritdoc}
 */
static $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('Snippet code language'));

    return $properties;
  }

Deze methode wordt gebruikt om het datatype te definiëren dat aanwezig is in de veldwaarden. Het “Snippets-veld” heeft slechts drie waarden: beschrijving, code en taal. Daarom heb ik deze waarden als strings toegevoegd in de methode.

Om hier meer over te leren, ga naar Hoe de Entity API de Typed Data API implementeert op drupal.org.

Klik hier om het volledige bestand te bekijken. Let op: dit moet worden bijgewerkt naar de PSR-4-specificatie, zie https://www.drupal.org/node/2128865 voor meer informatie.

Stap 2: Implementatie van de veldwidget

Nu we het velditem hebben gedefinieerd, maken we een veldwidget. We moeten een klasse maken met de naam SnippetsDefaultWidget, die de klasse WidgetBase uitbreidt.

1. Maak dus het bestand SnippetsDefaultWidget.php en voeg dit toe in “module” /src/Plugin/Field/FieldWidget/SnippetsDefaultWidget.php.

/**
 * @file
 * Contains \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;

Zorg ervoor dat de namespace van het bestand Drupal\snippets\Plugin\Field\FieldWidget is en voeg de volgende drie use-statements toe: Drupal\Core\Field\FieldItemListInterface, Drupal\Core\Field\WidgetBase en Drupal\Core\Form\FormStateInterface.

2. Vervolgens moeten we de widget definiëren via een annotatie. Dit is gelijk aan het gebruik van hook_field_widget_info in Drupal 7.

/**
 * Plugin implementation of the 'snippets_default' widget.
 *
 * @FieldWidget(
 *   id = "snippets_default",
 *   label = @Translation("Snippets default"),
 *   field_types = {
 *     "snippets_code"
 *   }
 * )
 */
class SnippetsDefaultWidget extends WidgetBase { }

Let erop dat het attribuut field_types in de annotatie verwijst naar de veldtypen met hun ID. Voor deze module is dat snippets_code, omdat we id = "snippets_code" in de @FieldType-annotatie hebben toegevoegd.

3. Tot slot moeten we het daadwerkelijke formulier van de widget definiëren. Dat doen we door de methode formElement() toe te voegen in de klasse SnippetsDefaultWidget. Deze methode is gelijk aan het gebruik van hook_field_widget_form in Drupal 7.

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

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

Klik hier om het volledige bestand te bekijken. Let op: dit moet worden bijgewerkt naar de PSR-4-specificatie, zie https://www.drupal.org/node/2128865 voor meer informatie.

Stap 3: Implementatie van de veldformatter

Het laatste onderdeel is de veldformatter, die we maken door een klasse SnippetsDefaultFormatter te definiëren, die de klasse FormatterBase uitbreidt.

1. Maak het bestand SnippetsDefaultFormatter.php en voeg dit toe in “module” /src/Plugin/Field/FieldFormatter/SnippetsDefaultFormatter.php.

/**
 * @file
 * Contains \Drupal\snippets\Plugin\field\formatter\SnippetsDefaultFormatter.
 */

namespace Drupal\snippets\Plugin\Field\FieldFormatter;

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

Zorg ervoor dat de namespace van het bestand Drupal\snippets\Plugin\Field\FieldFormatter is en voeg de volgende use-statements toe: Drupal\Core\Field\FieldItemListInterface en Drupal\Core\Field\FormatterBase.

2. Vervolgens moeten we de formatter definiëren met een annotatie. Net zoals we dat deden voor de widget en het veldtype. Dit is gelijk aan het gebruik van hook_field_formatter_info.

/**
 * Plugin implementation of the 'snippets_default' formatter.
 *
 * @FieldFormatter(
 *   id = "snippets_default",
 *   label = @Translation("Snippets default"),
 *   field_types = {
 *     "snippets_code"
 *   }
 * )
 */
class SnippetsDefaultFormatter extends FormatterBase { }

3. Nu hoeven we alleen nog de methode viewElements() toe te voegen en de formattering van het veld te definiëren. Opnieuw is deze methode gelijk aan het gebruik van hook_field_formatter_view in Drupal 7.

/**
 * {@inheritdoc}
 */
public function viewElements(FieldItemListInterface $items, $langcode) {
  $elements = array();
  foreach ($items as $delta => $item) {
    // Render output using snippets_default theme.
    $source = array(
      '#theme' => 'snippets_default',
      '#source_description' => $item->source_description,
      '#source_code' => $item->source_code,
    );
    
    $elements[$delta] = array('#markup' => drupal_render($source));
  }

  return $elements;
}

Let erop dat ik een aangepast thema snippets_default gebruik om de snippets te renderen voordat ze door de formatter worden weergegeven.

De reden hiervoor is dat ik niet veel logica of HTML in de methode viewElements() wilde plaatsen.

Klik hier om het volledige bestand te bekijken. Let op: dit moet worden bijgewerkt naar de PSR-4-specificatie, zie https://www.drupal.org/node/2128865 voor meer informatie.

Conclusie

Zoals eerder aangegeven is de grootste verandering in Drupal 8 dat velden worden gemaakt met behulp van de plugin API en niet met hooks. Zodra je dit begrijpt, lijkt het concept van het maken van een veld erg op Drupal 7. Veel methodes in Drupal 8 komen overeen met de hooks uit Drupal 7.

Als je de code-snippets wilt testen, download dan de 8.x-dev release en probeer het uit.