Impedisci invii di più moduli (lato server)


9

Sto riscontrando un problema in cui un utente può inviare più volte qualsiasi modulo creato dall'API del modulo (un clic rapido che genera più richieste).

Ho inserito la soluzione di base lato client (javascript) per disabilitare il pulsante, ma sono curioso di sapere quale sia l'approccio migliore per prevenire questa situazione sul lato server.

Esiste un modo consigliato per utilizzare il sistema di token di modulo di Drupal per gestirlo? Soprattutto una soluzione di modulo globale (ovvero, l'aggiunta di un validatore personalizzato a ogni modulo utilizzando hook_form_alter ()).

Finora il mio approccio è stato qualcosa del genere:

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  $form['#validate'][] = 'mymodule_form_validate';
}

function mymodule_form_validate(&$form, &$form_state){
  //initialize form array
  if (!isset($_SESSION['submitted_forms'])){
    $_SESSION['submitted_forms'] = array();
  }

  $form_token = $form_state['values']['form_token'];
  if ( isset($_SESSION['submitted_forms'][$form_token]) && $_SESSION['submitted_forms'][$form_token] = TRUE ){
    form_set_error('name]', 'This form has already been submitted');
  }
  else{
    $_SESSION['submitted_forms'][$form_token] = TRUE;
  }
}

Sto incontrando problemi in cui il form_token non è univoco per il modulo - sembra rimanere lo stesso, qualunque cosa accada. Probabilmente sto fraintendendo quale sia il token nel grande schema della forma api.

Qualsiasi intuizione è apprezzata!


Come follow-up, ho iniziato a usare $ form_state ['form_build_id'] invece del token. Se invio lo stesso modulo build id due volte, da qualche parte lungo la strada il modulo viene ricostruito ed elaborato comunque.
PrairieHippo,

Risposte:


8

Ho avuto lo stesso identico problema e sono riuscito a risolverlo utilizzando i meccanismi di blocco di Drupal

Nella funzione di convalida ho usato:

function mymodule_custom_form_validate($form, &$form_state){
  if (lock_acquire('your_custom_lock_name')) {
    // long operations here
  } else {
    form_set_error("", t("You submitted this form already."));
  }
}

E nella funzione di invio ho rilasciato il blocco:

function mymodule_custom_form_submit($form, &$form_state){
  // submit code
  lock_release('your_custom_lock_name');
}

1

Qui dovresti considerare il peso del modulo:

  1. Un modulo (let first_module) che dovrebbe avere il peso del modulo negativo valore_massimo (può essere -2000) qui dovrebbe implementare hook_form_alter () con il seguente codice. Ora dovresti verificare se il modulo è già stato inviato o meno dal tuo codice.
   function first_module_form_alter(&$form, &$form_state, $form_id)
    {
      $form['#validate'][] = 'mymodule_form_validate';
    }
function mymodule_form_validate(&$form, &$form_state){
  //a($form_state);
  //initialize form array
  if (!isset($_SESSION['submitted_forms'])){
    $_SESSION['submitted_forms'] = array();
  }

  $form_token = $form_state['values']['form_id'];
  if ( isset($_SESSION['submitted_forms'][$form_token]) && $_SESSION['submitted_forms'][$form_token] = TRUE ){
    form_set_error('name]', 'This form has already been submitted');
  }
  else{
    $_SESSION['submitted_forms'][$form_token] = TRUE;
  }
}
  1. Il secondo_modulo che ha il peso del valore possitivo più alto. Dovresti disinserire la sessione aggiungendo il callback di invio a un modulo

funzione second_module_form_alter (& $ form, & $ form_state, $ form_id) {$ form ['# submit'] [] = 'mymodule_form_submit'; }

function mymodule_form_submit(&$form, &$form_state){

  $form_token = $form_state['values']['form_id'];
  unset($_SESSION['submitted_forms'][$form_token]);

}

1

Se vuoi questa funzionalità su tutti i moduli e un maggiore controllo senza codifica dai un'occhiata al modulo Nascondi pulsante di invio.

Caratteristiche:

  1. Nasconde o disabilita il pulsante di invio dopo aver fatto clic
  2. Visualizza un messaggio e / o un'immagine durante l'attesa

5
Il modulo Nascondi pulsante di invio non è una soluzione lato server. Dalla descrizione del modulo: "Per i browser con Javascript disabilitato questo modulo non avrà alcun effetto". drupal.org/project/hide_submit
Blake Frederick l'

0
$form['submit'] = array(
  '#type' => 'submit',
  '#value' => t('Save'),
  '#attributes' => array(
    'onclick' => 'javascript:var s=this;setTimeout(function(){s.value="Saving...";s.disabled=true;},1);',
  ),
);

spero che questo possa aiutare ..

oppure puoi fare riferimento Prevenire più clic del pulsante di invio e drupal ha un modulo Nascondi pulsante di invio

Alcuni utenti fanno accidentalmente clic sul pulsante di invio più di una volta mentre attendono che il loro post venga salvato. In alcuni casi ciò può comportare registrazioni duplicate o duplicati di ordini e-commerce.


-1

Questo era il mio problema anche prima. La mia soluzione a questo è disabilitare il pulsante tramite JS.

.modulo:

/**
 * Implementation of hook_init().
 */
function myModule_init(){
if (arg(0) == 'node' && (arg(2) == 'edit' || arg(1) == 'add')) {
    //hide btn when clicked on article nodes
    drupal_add_js(drupal_get_path('module', myModule') . '/js/disable-submit.js');
}

JS:

Drupal.behaviors.module_disable_submit = function (context) {

/* 
 * Disable keypress on form fields.
 * Prevent browser to reload when pressing enter in input fields 
 */


$('.buttons input:submit').click(function() {
  $('.buttons input:submit').hide();
  $('#node-form .buttons').prepend('<input type="submit" style="margin:1px 0; box-shadow:0 1px 1px #DDDDDD; border-radius:3px 3px 3px 3px; background:url(/sites/all/themes/rubik/images/bleeds.png) repeat-x scroll 0 -41px #F4F4F4; border-color:#DDDDDD #DDDDDD #CCCCCC; border-style:solid; border-width:1px; color:#B8A98F; cursor:default; font-weight:normal; padding:2px 10px; text-align:center;" value="Saving..." name="op" onclick="return false;" />');
  if ('.buttons input:submit') {
    $('.buttons input:submit').keypress(function() {
      $('.buttons input:submit').parents("form").submit();
      $('.buttons input:submit').hide();
    });
  }
});
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.