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

Panoramica: creazione di un campo personalizzato

30/09/2025, by Ivan
Questo tutorial è stato originariamente pubblicato su Web Wash. Tuttavia Berdir ha chiesto se potevo pubblicarlo qui, quindi eccolo.

Un modulo in Drupal 7 consente di memorizzare esempi di codice / snippet in un campo. Viene fornito con un campo personalizzato chiamato “Campo Snippets” e mostra tre elementi del form: descrizione, codice sorgente e modalità di evidenziazione della sintassi (quale linguaggio di programmazione).

Ma ora è il momento di aggiornare il modulo a Drupal 8.

In questa lezione ti mostrerò come ho creato un campo personalizzato “base” in Drupal 8. Non entrerò nei dettagli di PSR-4, annotazioni o plugin, altrimenti la lezione diventerebbe enorme.

Invece, aggiungerò link ad altri siti che spiegano più a fondo questi concetti.

Detto questo, se cerchi documentazione dettagliata sulla Field API in Drupal 8, consulta le seguenti serie:

 

In Drupal 8 i campi non sono implementati con gli hook, come in Drupal 7. Invece vengono creati utilizzando la nuova API dei plugin di Drupal 8. Questo significa che invece di implementare hook, definiamo una classe per il widget, il formatter e l’elemento del campo. Molti hook di Drupal 7, come hook_field_schema, hook_field_is_empty e altri, ora sono metodi nelle classi.

Passo 1: Implementare l’elemento del campo

La prima cosa che dobbiamo fare è definire una classe per l’elemento del campo chiamata SnippetsItem, che estende la classe FieldItemBase.

1. In Drupal 8 le classi vengono caricate utilizzando PSR-4.

Quindi, per definire la classe SnippetsItem, dobbiamo creare il file SnippetsItem.php e posizionarlo in “modulo” /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;

Poi nel file aggiungiamo lo spazio dei nomi Drupal\snippets\Plugin\Field\FieldType e tre use statement: Drupal\Core\Field\FieldItemBase, Drupal\Core\Field\FieldStorageDefinitionInterface e Drupal\Core\TypedData\DataDefinition.

2. Ora dobbiamo definire i dettagli effettivi del campo, come l’ID, l’etichetta, il widget di default, il formatter, ecc. Questo è l’equivalente dell’implementazione di hook_field_info in Drupal 7.

In Drupal 8 molti, se non tutti, gli hook informativi sono stati sostituiti da annotazioni.

/**
 * 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 { }

Quindi, invece di implementare hook_field_info, definiamo il campo come annotazione all’interno del commento sopra la classe.

Gli attributi delle annotazioni non necessitano di molte spiegazioni. Basta assicurarsi che default_widget e default_formatter facciano riferimento agli ID delle annotazioni di widget e formatter, non alle classi.

Se vuoi saperne di più sulle annotazioni, visita la pagina della documentazione dei plugin basati su annotazioni su drupal.org.

3. Ora che abbiamo la classe dell’elemento del campo, dobbiamo definire alcuni metodi. Il primo che analizzeremo è schema().

In Drupal 7, quando creavi un campo personalizzato, definivi lo schema tramite hook_field_schema. In Drupal 8 definiamo lo schema aggiungendo un metodo schema() alla classe SnippetsItem.

La documentazione Schema API contiene la descrizione della struttura dell’array schema e dei valori possibili.
/**
 * {@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. Ora dobbiamo aggiungere il metodo isEmpty() e definire cosa costituisce un elemento vuoto del campo. Questo metodo è analogo all’implementazione di hook_field_is_empty in Drupal 7.

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

5. L’ultimo metodo che aggiungeremo alla classe è 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;
  }

Questo metodo serve a definire il tipo di dati presenti nei valori del campo. Il “Campo Snippets” ha solo tre valori: descrizione, codice e linguaggio. Perciò ho semplicemente aggiunto questi valori come stringhe nel metodo.

Per saperne di più su questo, vai alla sezione Come l’Entity API implementa la documentazione della Typed Data API su drupal.org.

Clicca qui per vedere l’intero file. Nota: deve essere aggiornato alla specifica PSR-4, per maggiori dettagli consulta https://www.drupal.org/node/2128865

Passo 2: Implementare il widget del campo

Ora che abbiamo definito l’elemento del campo, creiamo il widget. Dobbiamo creare una classe chiamata SnippetsDefaultWidget che estende la classe WidgetBase.

1. Crea il file SnippetsDefaultWidget.php e aggiungilo in “modulo” /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;

Assicurati che il namespace del file sia Drupal\snippets\Plugin\Field\FieldWidget e aggiungi i seguenti tre use statement: Drupal\Core\Field\FieldItemListInterface, Drupal\Core\Field\WidgetBase e Drupal\Core\Form\FormStateInterface.

2. Poi dobbiamo definire il widget tramite annotazione. Questo è l’equivalente dell’uso di 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 { }

Assicurati che l’attributo field_types nell’annotazione faccia riferimento ai tipi di campo utilizzando i loro ID. Per questo modulo è snippets_code, perché abbiamo aggiunto id = "snippets_code" nell’annotazione @FieldType.

3. Infine, dobbiamo definire il form effettivo del widget. Lo facciamo aggiungendo il metodo formElement() nella classe SnippetsDefaultWidget. Questo metodo è analogo all’uso di 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;
}

Clicca qui per vedere l’intero file. Nota: deve essere aggiornato alla specifica PSR-4, per maggiori dettagli consulta https://www.drupal.org/node/2128865

Passo 3: Implementare il formatter del campo

L’ultimo pezzo del puzzle è il field formatter, che creiamo definendo una classe chiamata SnippetsDefaultFormatter che estende la classe FormatterBase.

1. Crea il file SnippetsDefaultFormatter.php e aggiungilo in “modulo” /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;

Assicurati che il namespace del file sia Drupal\snippets\Plugin\Field\FieldFormatter e aggiungi i seguenti use statement: Drupal\Core\Field\FieldItemListInterface e Drupal\Core\Field\FormatterBase.

2. Poi dobbiamo definire il formatter come annotazione. Come abbiamo fatto per widget e tipo di campo, questo è l’equivalente dell’uso di 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. Ora non resta che aggiungere il metodo viewElements() e definire il modulo effettivo di formattazione del campo. Anche questo metodo è analogo all’uso di 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;
}

Nota che utilizzo un template personalizzato snippets_default per renderizzare gli snippet prima che vengano mostrati dal formatter.

La ragione è che non volevo inserire troppa logica o codice HTML nel metodo viewElements().

Clicca qui per vedere l’intero file. Nota: deve essere aggiornato alla specifica PSR-4, per maggiori dettagli consulta https://www.drupal.org/node/2128865

Conclusione

Come detto in precedenza, il cambiamento più grande in Drupal 8 è che i campi sono creati utilizzando l’API dei plugin, non gli hook. Una volta capito questo, il concetto di creazione di un campo è molto simile a Drupal 7. Molti metodi in Drupal 8 corrispondono agli hook in Drupal 7.

Se vuoi testare gli snippet di codice, scarica la release 8.x-dev e provali.