logo

Extra Block Types (EBT) - Nuova esperienza con Layout Builder❗

Extra Block Types (EBT) - tipi di blocchi stilizzati e personalizzabili: Slideshows, Tabs, Cards, Accordion e molti altri. Impostazioni integrate per sfondo, DOM Box, plugin javascript. Vivi oggi il futuro della costruzione dei layout.

Demo moduli EBT Scarica moduli EBT

❗Extra Paragraph Types (EPT) - Nuova esperienza con Paragraphs

Extra Paragraph Types (EPT) - insieme di moduli basati su paragrafi in modo analogo.

Demo moduli EPT Scarica moduli EPT

Scorri

9.10.3. Lavorare con i campi in Drupal. Creare un proprio tipo di campo, widget e formatter per inserire video da YouTube.

17/10/2025, by Ivan

Menu

Negli articoli precedenti abbiamo visto come funziona il tipo di campo Link: Storage, Widget, Formatter. In questo articolo creeremo un nostro tipo di campo personalizzato per visualizzare video di YouTube su una pagina, con due formati e impostazioni differenti.

Questo articolo è dedicato alla Fields API e, se hai bisogno di aggiungere un campo video di YouTube al tuo sito, è meglio utilizzare il modulo già pronto:

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

Ho aggiunto tutto il codice su GitHub nel modulo drupalbook_youtube, puoi scaricare il modulo e aggiungerlo al tuo sito:

https://github.com/levmyshkin/drupalbook8

Vediamo ora la struttura di questo modulo e cercherò di descrivere come funziona questo tipo di campo:

modules/custom/drupalbook_youtube/drupalbook_youtube.info.yml

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

Definiamo i metadati del modulo.

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;

/**
 * Implementazione del plugin per il tipo di campo '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 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;
  }

}

Creiamo un tipo di campo in modo che Drupal sappia cosa verrà memorizzato nella tabella per questo campo.

<?php

namespace Drupal\drupalbook_youtube\Plugin\Field\FieldType;

use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\TypedData\DataDefinition;
Definisci gli spazi dei nomi per il nostro tipo di campo.

/**
 * Implementazione del plugin per il tipo di campo '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"
 * )
 */

Scriviamo un'annotazione per la nostra classe: da questa annotazione Drupal prenderà il nome del nostro tipo di campo e il suo machine name.

class DrupalbookYoutubeItem extends FieldItemBase {

Il nome della classe è meglio scriverlo con "Item" alla fine.

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

Definiamo che memorizzeremo nel database un campo value di tipo testo.

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

Nel caso in cui il campo venga richiamato da codice esterno, restituiamo un valore vuoto come fallback se il campo non contiene dati.

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

  return $properties;
}

Descriviamo le colonne per la tabella MySQL e l’oggetto entità. Di conseguenza, verrà memorizzato l’intero link:

select

Ora che abbiamo aggiunto un tipo di campo, creiamo un Widget per l’inserimento dei dati:


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;

/**
 * Implementazione del plugin per il widget '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 += array(
      '#type' => 'textfield',
      '#default_value' => $value,
      '#size' => 32,
      '#maxlength' => 256,
      '#element_validate' => array(
        array($this, 'validate'),
      ),
    );
    return array('value' => $element);
  }

  /**
   * Validazione del campo di testo.
   */
  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."));
    }
  }

}

Il widget ci permette di inserire i dati nel form di modifica dell’entità.

Abbiamo specificato nella annotazione della classe il field_type che abbiamo creato prima, cioè drupalbook_youtube.

Alla fine del nome della classe aggiungiamo Widget per indicare che la classe serve per un Field Widget.

Creiamo un semplice campo di testo tramite la Form API in cui inseriremo il link al video YouTube.

La callback di validazione che abbiamo indicato sopra in #element_validate serve per assicurarci che l’utente inserisca un link valido di YouTube. L’espressione regolare è presa da StackOverflow; puoi sostituirla se non funziona correttamente.

Ora possiamo inserire i dati nel nostro campo; manca solo aggiungere un Field Formatter per l’output dei dati.