9.10. Drupal Fields API. I campi di Drupal nel database.
In questo articolo capiremo come funzionano i campi in Drupal, perché sono necessari e come i campi aiutano a sviluppare rapidamente siti in Drupal.
Abbiamo già lavorato con i campi negli articoli precedenti:
7.5. Scrittura del blocco dei servizi con colonne bootstrap
7.6. Galleria Isotope per Drupal
7.7. Blocco con video YouTube in Drupal
Ora capiremo come funziona. Andiamo a modificare i campi del tipo di contenuto Articolo e aggiungiamo un nuovo campo di tipo Link:
/admin/structure/types/manage/article/fields
Quando crei un nuovo articolo, avrai due campi di input per gli URL e i link di testo:
Ogni volta che crei un nuovo campo tramite l'amministrazione, vengono create due tabelle nel database:
{entity_type}___field_name}
{entity_type}_revision___field_name}
Drupal supporta le revisioni, quindi tutti i dati saranno duplicati almeno una volta, poiché l'unica revisione è la revisione corrente del tuo articolo. In questo modo, i campi e l'intera Fields API di Drupal sono necessari per semplificare il lavoro con il database. Creiamo semplicemente i campi tramite l'amministrazione, e Drupal crea già le tabelle nel database.
Dal nome delle tabelle MySQL dovrebbe essere chiaro che lo stesso campo può essere utilizzato per un tipo di entità. Ad esempio, possiamo ora utilizzare il campo Link nel contenuto del tipo di nodo Basic Page come già esistente:
/admin/structure/types/manage/page/fields/add-field
Ma se vuoi creare un campo Link in un blocco, dovrai creare un nuovo campo. Non è possibile usare lo stesso campo in entità di tipi differenti. Creiamo un campo Link per il tipo di blocco Basic Block:
/admin/structure/block/block-content/manage/basic/fields/add-field
Come puoi vedere, quando crei un campo, non c'è la possibilità di scegliere il campo Link tra i campi esistenti, perché Blocchi e Nodi sono tipi di entità differenti.
Proprio come per i nodi, avremo due tabelle per memorizzare i dati del campo Link per i blocchi:
block_content_revision__field_link e block_content__field_link.
Ora cerchiamo di capire come Drupal memorizza i dati dello stesso campo per nodi di bundle differenti. Abbiamo creato il campo Link per il tipo di nodo Articolo, ma poi lo abbiamo riutilizzato nel tipo di nodo Basic Page. Per comodità, è meglio caricare la configurazione del sito in una cartella e vedere i file, ma puoi anche trovare la configurazione necessaria tramite Adminer o phpMyAdmin nella tabella di configurazione:
Se cerchi tutte le configurazioni che contengono la parola "link":
SELECT * FROM `config` WHERE CONVERT(`name` USING utf8mb4) LIKE '%link%' LIMIT 50
Troveremo le seguenti configurazioni per il nostro campo field_link:
field.field.block.block_content.basic.field_link
field.field.node.article.field_link
field.field.node.page.field_link
field.storage.block_content.field_link
field.storage.node.field_link
Per ogni tipo di entità, ogni campo crea la propria configurazione di Field Storage. Questa configurazione risponde a come memorizzare i dati nelle tabelle {entity_type}__{field_name}, {entity_type}_revision__{field_name}. Nei nostri casi, queste sono le tabelle block_content_field_link, block_content_revision_field_link, node__field_link, node_revision__field_link. Ora esamineremo come il modulo Link memorizza i dati. Apriamo la configurazione di Field Storage per il campo Link:
uuid: dba847ef-f4d6-4462-a2ee-f642a007fca6
langcode: en
status: true
dependencies:
module:
- block_content
- link
id: block_content.field_link
field_name: field_link
entity_type: block_content
type: link
settings: { }
module: link
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
Esaminiamo ciascuna di queste righe per capire cosa viene effettivamente memorizzato nella configurazione di Field Storage.
uuid: dba847ef-f4d6-4462-a2ee-f642a007fca6
Qui viene memorizzato l'ID di configurazione, unico per ogni configurazione. Non è necessario creare il campo manualmente su staging se l'hai creato localmente e caricato le configurazioni. Il campo sarà creato automaticamente. Se elimini il campo e elimini la configurazione localmente, eliminerai anche tutti i dati dopo averli importati in staging. Pertanto, se hai creato un campo su staging, carica le configurazioni e aggiungile a git per non perdere le modifiche.
langcode: en
Nei siti multilingue, per le diverse versioni dei nodi per lingue differenti, nella tabella dei campi vengono memorizzati tutti i dati per tutte le lingue, indicando quale lingua utilizza determinati dati:
Ho la stessa lingua, quindi la lingua predefinita nella configurazione è la stessa.
status: true
Comune a tutte le entità di configurazione è il campo status che indica se questa entità è attiva o disabilitata. La configurazione di Field Storage utilizza l'entità di configurazione creata in Drupal, consulta la classe FieldStorageConfig, che è ereditata da ConfigEntityBase:
https://api.drupal.org/api/drupal/core!modules!field!src!Entity!
dependencies:
module:
- block_content
- link
Dipendenza dai moduli aggiuntivi. Poiché abbiamo usato il campo Link nei blocchi, abbiamo il modulo obbligatorio Block content.
id: block_content.field_link
Il nome univoco della nostra configurazione.
field_name: field_link
Il nome macchina del campo che abbiamo creato e che Drupal utilizza, quindi questo nome macchina può essere usato, ad esempio, quando accedi all'oggetto nodo $node->field_link->uri
. Come fare riferimento al campo dell'Entità lo capiremo nei prossimi articoli.
Entity_type: block_content
Che tipo di entità è la nostra configurazione di Field Storage
type: link
Il tipo di campo di Drupal, ora sappiamo che questo tipo di campo link è creato dal modulo Link. Puoi vedere la classe:
core/modules/link/src/Plugin/Field/FieldType/LinkItem.php
Che viene utilizzata nella nostra configurazione.
settings: { }
Qui vengono memorizzate le impostazioni per il tipo di campo, ora sono vuote, ma ad esempio per il campo body c'è un'impostazione per visualizzare il teaser o meno:
config/sync/field.field.block_content.basic.body.yml
settings:
display_summary: false
module: link
Un modulo che ha un tipo di campo link. Ora abbiamo lo stesso nome del modulo e tipo di campo link, ma possono essere differenti, ad esempio, in un modulo possono essere implementati diversi tipi di campi, come nel modulo DateTime:
core/modules/datetime/src/Plugin/Field/FieldType/DateTimeFieldItemList.php
core/modules/datetime/src/Plugin/Field/FieldType/DateTimeItem.php
locked: false
Indica se il campo è disponibile per la modifica. Ciò significa configurare il campo. Tempo fa, ad esempio, il campo Billing Information e Shipping Information nel modulo Commerce era bloccato perché l'esistenza di questo campo era obbligatoria quando si utilizzavano calcoli di spedizione e tasse.
cardinality: 1
Il numero di valori che possono essere inseriti per un'entità in questo campo. Abbiamo selezionato un valore, ma qui potrebbe esserci un altro numero come 2, 3, 5, ecc. Per un numero illimitato di valori si usa cardinality: -1.
translatable: true
Questo campo è traducibile in altre lingue?
indexes: { }
Indici SQL aggiuntivi per migliorare la ricerca in questo campo. Di solito è necessario per configurare e ottimizzare le query del database.
persist_with_no_fields: false
Indica se eliminare il Field Storage quando i campi sono stati rimossi da tutte le entità. Ad esempio, se eliminiamo il campo da Articolo e Basic Page, il Field Storage non verrà eliminato.
custom_storage: false
Lo storage personalizzato implica che abbiamo una tabella speciale per memorizzare i dati del campo, non {entity_type}__{field_name}. Non utilizzeremo nulla di simile, ma a volte è comodo per l'integrazione con altri sistemi.
Ora apriamo il file del tipo di campo link:
core/modules/link/src/Plugin/Field/FieldType/LinkItem.php
Vediamo che dati memorizza questo campo nel database. Questo può essere visto nel metodo propertyDefinitions():
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties['uri'] = DataDefinition::create('uri')
->setLabel(t('URI'));
$properties['title'] = DataDefinition::create('string')
->setLabel(t('Link text'));
$properties['options'] = MapDataDefinition::create()
->setLabel(t('Options'));
return $properties;
}
Come puoi vedere memorizziamo i dati URI, Title, Options. Se apri la tabella node__field_link
, vedrai gli stessi campi:
Ora siamo arrivati al tema della Fields API in Drupal. Creiamo un tipo di campo tramite un modulo in un file PHP con la classe LinkItem. Questo ci permette di creare un campo per l'Entità e poi usarlo per inserire dati e memorizzare questi dati nel database. Questo è il caso per l'inserimento dei dati. La Fields API configura anche il modulo per l'inserimento dei dati e l'output per i nostri campi.
Torniamo al momento in cui creiamo i campi per i tipi di contenuto Articolo e Basic Page. Abbiamo un file di configurazione per il Field Storage nel nodo: field.storage.node.field_link.yml
, ma anche quando creiamo il campo, creiamo un altro file di configurazione per ogni bundle nell'Entità, quindi per esempio ora abbiamo tre file di configurazione per il campo:
field.field.node.article.field_link.yml
field.field.node.page.field_link.yml
field.field.block.block_content.basic.field_link.yml
Queste configurazioni memorizzano i dati dal modulo di configurazione del campo:
In questo modo possiamo personalizzare il modulo di inserimento dei dati per il campo in modi diversi per ciascun Bundle. Ogni singola configurazione di campo in un Bundle è chiamata Field Instance in Drupal, quindi prima creiamo un campo Field Storage che può essere usato separatamente in ogni Bundle in Field Instance. In Drupal 8, a differenza di Drupal 7, non ci sono più funzioni per lavorare con le Field Instances, e la funzionalità per lavorare con le istanze è migrata nell'API CRUD:
https://www.drupal.org/node/2054619
Esempi di come lavorare con i campi tramite codice li puoi vedere nella documentazione ufficiale:
https://www.drupal.org/node/2012896
Abbiamo visto solo la parte della Fields API che riguarda la memorizzazione dei dati del campo nel database. Nelle prossime lezioni esamineremo come la Fields API lavora con l'inserimento dei dati e l'output dei dati dei campi, nonché creeremo il nostro tipo di campo completo.