Mehrere Formularübermittlungen verhindern (Serverseite)


9

Ich habe ein Problem, bei dem ein Benutzer jedes von der Formular-API erstellte Formular mehrmals senden kann (schnelles Klicken führt zu mehreren Anforderungen).

Ich habe die grundlegende clientseitige (Javascript) Lösung zum Deaktivieren der Schaltfläche eingeführt, bin aber gespannt, wie diese Situation am besten auf der Serverseite verhindert werden kann.

Gibt es eine empfohlene Möglichkeit, das Formular-Token-System von Drupal zu verwenden, um dies zu handhaben? Insbesondere eine globale Formularlösung (dh Hinzufügen eines benutzerdefinierten Validators zu jedem Formular mithilfe von hook_form_alter ()).

Mein bisheriger Ansatz war ungefähr so:

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;
  }
}

Ich habe Probleme, wenn das form_token nicht nur für das Formular gilt - es scheint gleich zu bleiben, egal was passiert. Ich verstehe wahrscheinlich falsch, was das Token im großen Schema der Form API ist.

Jeder Einblick wird geschätzt!


Als Folge habe ich angefangen, $ form_state ['form_build_id'] anstelle des Tokens zu verwenden. Wenn ich dieselbe Formularerstellungs-ID zweimal sende, wird das Formular irgendwo auf dem Weg trotzdem neu erstellt und verarbeitet.
PrairieHippo

Antworten:


8

Ich hatte genau das gleiche Problem und konnte es mithilfe der Sperrmechanismen von Drupal beheben

In der Validierungsfunktion habe ich verwendet:

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."));
  }
}

Und in der Submit-Funktion habe ich die Sperre aufgehoben:

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

1

Hier sollten Sie das Modulgewicht berücksichtigen:

  1. Ein Modul (let first_module), dessen Modulgewicht einen negativen Maximalwert (möglicherweise -2000) haben sollte, sollte hook_form_alter () mit dem folgenden Code implementieren. Jetzt sollten Sie überprüfen, ob das Formular bereits von Ihrem Code gesendet wurde oder nicht.
   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. Das zweite Modul, dessen Gewicht einen möglicherweise höheren Wert hat. Hier sollten Sie die Sitzung deaktivieren, indem Sie den Submit-Rückruf einem Modul hinzufügen

Funktion 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

Wenn Sie diese Funktionalität für alle Formulare und mehr Kontrolle ohne Codierung wünschen, schauen Sie sich das Modul Hide Submit Button an .

Eigenschaften:

  1. Blenden Sie die Senden-Schaltfläche aus oder deaktivieren Sie sie, nachdem Sie darauf geklickt haben
  2. Zeigen Sie während des Wartens eine Nachricht und / oder ein Bild an

5
Das Hide Submt Button-Modul ist keine serverseitige Lösung. Aus der Beschreibung des Moduls: "Für Browser mit deaktiviertem Javascript hat dieses Modul überhaupt keine Auswirkungen." drupal.org/project/hide_submit
Blake Frederick

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);',
  ),
);

hoffe das wird helfen ..

oder Sie können verweisen Verhindern mehrere Klicks von Submit - Button & Drupal hat ein Modul ausblenden Absenden - Button

Einige Benutzer klicken versehentlich mehrmals auf die Schaltfläche "Senden", während sie darauf warten, dass ihr Beitrag gespeichert wird. In einigen Fällen kann dies zu doppelten Buchungen oder doppelten E-Commerce-Bestellungen führen.


-1

Das war auch vorher mein Problem. Meine Lösung besteht darin, die Schaltfläche über JS zu deaktivieren.

.Modul:

/**
 * 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();
    });
  }
});
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.