9.8.1. hook_form_alter() aggiungi submit e validate per un modulo esistente.
In una delle lezioni precedenti abbiamo imparato cosa sono gli hook, in questa lezione lavoreremo con gli hook hook_form_alter()
in pratica e aggiungeremo funzionalità al modulo esistente.
Esempi di codice sono disponibili su GitHub:
https://github.com/levmyshkin/drupalbook8
In questa lezione inizieremo a esaminare gli hook in pratica, più avanti torneremo sugli hook e vedremo un paio di altri esempi. Per ora, iniziamo con hook_form_alter()
.
Per aggiungere un hook al modulo, dobbiamo creare un file chiamato MODULENAME.module
, quindi creeremo un file chiamato drupalbook.module
. Questo sarà un file PHP in cui verranno memorizzati i nostri hook e le funzioni ausiliarie, per il resto è meglio usare file e classi separati nella cartella src
. Per ora puoi aggiungere solo il tag di apertura al file.
Ora aggiungiamo hook_form_alter()
. Se stai usando PhpStorm, inizia a scrivere il nome dell'hook e PhpStorm ti offrirà di scegliere uno degli hook. Quando selezioni un hook in questo modo, PhpStorm sostituirà automaticamente gli argomenti nella funzione e non dovrai ricordare o cercare nella documentazione quali argomenti devi aggiungere:
Quando vuoi aggiungere un hook, devi sostituire la parola "hook" con il nome del tuo modulo, e Drupal inserirà automaticamente il tuo codice nel punto in cui si trovano gli hook. Come risultato, dovresti ottenere questa funzione:
/**
* Implementa hook_form_alter().
*/
function drupalbook_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
}
Nella lezione precedente abbiamo già visto cosa deve essere memorizzato in $form
, $form_state
, mentre in $form_id
dobbiamo memorizzare l'ID del modulo, che abbiamo definito nel metodo appropriato:
9.8. Lavorare con i moduli in Drupal. Aggiungere un modulo di configurazione programmaticamente.
Ora estendiamo il modulo per l'aggiunta delle chiavi API che abbiamo fatto nell'ultima lezione. Per fare ciò, dobbiamo definire l'ID del modulo, che puoi vedere in questo metodo:
function getFormId() {
return 'drupalbook_admin_settings';
}
Oppure apri l'ispezionatore DOM e guarda l'attributo ID nell'HTML:
Qui dobbiamo sostituire il trattino (-) con il carattere di sottolineatura (_) (underscore). Ma fai attenzione, l'ID nell'attributo del tag del modulo può essere incrementato dopo una richiesta AJAX, ad esempio drupalbook-admin-settings-0
, drupalbook-admin-settings-1
, drupalbook-admin-settings-2
e così via. Abbiamo bisogno di una parte senza il numero finale, che è la parte formata dall'ID del modulo, che è specificato nel metodo getFormId()
.
Ora dobbiamo limitare l'esecuzione del nostro codice solo per il modulo drupalbook_admin_settings
, perché il codice che si trova in hook_form_alter()
verrà eseguito per tutti i moduli che vengono generati tramite la Form API di Drupal:
($form_id == 'drupalbook_admin_settings') {
// Il codice successivo qui.
}
All'interno di if
possiamo scrivere il nostro codice per il modulo delle chiavi API. Aggiungiamo i segnaposto per i campi di testo in modo che i campi vuoti mostrino cosa scrivere:
($form_id == 'drupalbook_admin_settings') {
$form['drupalbook_api_key']['#attributes']['placeholder'] = 'API key';
$form['drupalbook_api_client_id']['#attributes']['placeholder'] = 'API client ID';
}
Per applicare hook_form_alter()
, pulisci la cache.
Anche se #attributes
non è elencato nella documentazione come una chiave possibile per il textfield
:
Tuttavia, questa chiave può comunque essere utilizzata per specificare gli attributi dei tag: classe, segnaposto, e vari attributi rel
. Una tabella più chiara è quella per la Drupal 7 Form API:
https://api.drupal.org/api/drupal/developer%21topics%21forms_api_reference.html/7.x
Puoi trovare #attributes
qui per i campi di tipo textfield
.
I valori degli attributi sono impostati nella Form API quando si genera (renderizza) un elemento del modulo nel metodo setAttributes
:
Anche se non dichiarato nella documentazione dell'API del modulo, puoi vedere con i tuoi occhi che funziona.
Puoi anche vedere quali altri valori puoi impostare per i campi del modulo nella classe base FormElement
:
https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21Element%21FormElement.php/class/FormElement/8.2.x
La Drupal Form API può sembrare poco chiara e confusa, quindi è, io stesso non capisco ancora alcune cose. Ma usarla è abbastanza semplice e chiaro, se hai un esempio funzionante a portata di mano. Pertanto, se hai domande e non sai come fare in un modulo, cerca su Internet e troverai un esempio funzionante al 100%. Devi sapere che tutti i moduli passano attraverso tutte le API di Drupal: Cache, Render, Theming e qualsiasi campo nel modulo puoi cambiarlo tramite hook_form_alter()
, e puoi scoprire come fare questo tramite Google. Inoltre, più ti imbatti nella Form API e più analizzi gli esempi, più questa Form API diventerà facile e chiara per te. E non preoccuparti che sia così grande, usa solo la parte che ti serve ora.
Validate
Vediamo ora come usare le funzioni di validazione tramite la Form API. Controlliamo il campo della chiave API affinché inizi con la parola "google", ad esempio google-KEY123a3sa
. Se avessimo scritto il codice per il nostro modulo inizialmente, avremmo potuto inserire il metodo validateForm()
e fare tutti i controlli al suo interno:
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
}
Ma spesso i moduli con cui lavoriamo si trovano nei moduli contribuiti ed è meglio scrivere il codice per tali moduli nei moduli personalizzati. Quindi aggiungiamo una nuova funzione di validazione al modulo:
['#validate'][] = 'drupalbook_settings_validate';
Nel array #validate
memorizziamo tutte le funzioni di callback e di validazione. Il callback è una chiamata alla funzione per nome, cioè aggiungeremo l'array ['callback_function1', 'callback_function2']
e Drupal chiamerà queste funzioni. In questo caso, Drupal chiamerà queste funzioni per verificare il nostro modulo. Ora dobbiamo creare la funzione drupalbook_settings_validate
nel file drupalbook.module
. In questa funzione avremo i parametri $form
, $form_state
:
/**
* Funzione di validazione personalizzata.
*/
function drupalbook_settings_validate(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
}
Ora aggiungiamo il controllo per il campo della chiave API:
/**
* Funzione di validazione personalizzata.
*/
function drupalbook_settings_validate(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
if (strpos($form_state->getValue('drupalbook_api_key'), 'google') === FALSE) {
$form_state->setErrorByName('drupalbook_api_key', t('La chiave API deve iniziare con "google".'));
}
}
Usiamo l'operatore di confronto rigoroso ===
, perché se "google" è all'inizio della stringa, strpos()
restituisce 0 e per PHP (0 == FALSE) restituirà TRUE, poiché in PHP '', 0, NULL, FALSE
sono tutti valori vuoti e sono uguali in un confronto semplice con ==
.
Ora ogni volta che salviamo il modulo delle impostazioni, verrà eseguito un controllo e, se il controllo non è superato, Drupal genererà un errore e le impostazioni non verranno salvate:
Submit
Dopo che tutte le funzioni di validazione hanno lavorato e non si sono verificati errori, Drupal chiama le funzioni di submit, che vengono eseguite dopo l'invio dei dati dal modulo. Hai già visto il metodo submitForm()
nella lezione precedente, dove salviamo i dati nelle configurazioni. Ma possiamo eseguire altre azioni durante il submit, come modificare i dati o salvare alcuni dati in altre entità. Facciamo un'altra funzione di validazione che mostrerà un messaggio aggiuntivo su come usare la chiave API. In hook_form_alter()
aggiungeremo il nome della funzione:
['#submit'][] = 'drupalbook_settings_submit';
Ora nella funzione drupalbook_settings_settings_submit()
, dove passiamo anche $form
, $form_state
nei parametri, visualizzeremo il messaggio.
/**
* Funzione di submit personalizzata.
*/
function drupalbook_settings_submit(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
\Drupal::messenger()->addStatus(
t(htmlentities('Inserisci la chiave API nel tuo tag: .'))
);
}
Usiamo la funzione htmlentities()
per assicurarci che tutti i caratteri speciali che usiamo per visualizzare i tag "", "/", ">" non vengano eliminati da Drupal. Tutto il testo HTML viene tagliato dalla funzione t()
, in modo che non possa essere incollato nel testo, ad esempio, se tale codice contiene un reindirizzamento javascript verso un altro sito, verrebbe eseguito al momento della visualizzazione dei messaggi. Ecco perché usiamo la funzione htmlentities
per visualizzare i tag.
Il messaggio non verrà visualizzato se le funzioni di validazione falliscono, solo quando non ci sono errori nel modulo vedremo il messaggio.
In precedenza, la funzione drupal_set_message
veniva utilizzata in Drupal per visualizzare i messaggi:
(t('Si è verificato un errore e l'elaborazione non è stata completata.'));
Ma ora tutti cercano di uniformare e portare all'uso dell'OOP ovunque.
Sotto trovi il codice completo del file drupalbook.module
:
/**
* Implementa hook_form_alter().
*/
function drupalbook_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
if ($form_id == 'drupalbook_admin_settings') {
$form['drupalbook_api_key']['#attributes']['placeholder'] = 'API key';
$form['drupalbook_api_client_id']['#attributes']['placeholder'] = 'API client ID';
$form['#validate'][] = 'drupalbook_settings_validate';
$form['#submit'][] = 'drupalbook_settings_submit';
}
}
/**
* Funzione di validazione personalizzata.
*/
function drupalbook_settings_validate(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
if (strpos($form_state->getValue('drupalbook_api_key'), 'google') === FALSE) {
$form_state->setErrorByName('drupalbook_api_key', t('La chiave API deve iniziare con "google".'));
}
}
/**
* Funzione di submit personalizzata.
*/
function drupalbook_settings_submit(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
// drupal_set_message è deprecato
// drupal_set_message(t('Si è verificato un errore e l'elaborazione non è stata completata.'));
\Drupal::messenger()->addStatus(
t(htmlentities('Inserisci la chiave API nel tuo tag: .'))
);
}
Questo conclude la nostra lezione sulla Form API, ma non finisce lo studio della Form API, ci imbatteremo ancora nelle funzioni di validazione, submit e vari campi. Capiremo anche in una delle lezioni come usare AJAX e form_state
tramite la Form API.
Esempi di codice sono disponibili su GitHub:
https://github.com/levmyshkin/drupalbook8