Запрет на отправку нескольких форм (на стороне сервера)

9

Я сталкиваюсь с проблемой, когда пользователь может отправить любую форму, созданную с помощью API форм, несколько раз (быстрый щелчок приводит к нескольким запросам).

Я включил базовое клиентское (javascript) решение по отключению кнопки, но мне любопытно, как лучше всего предотвратить эту ситуацию на стороне сервера.

Есть ли рекомендуемый способ использовать систему токенов формы Drupal для этого? Особенно глобальное решение для форм (т.е. добавление собственного валидатора к каждой форме с помощью hook_form_alter ()).

Мой подход до сих пор был примерно таким:

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

У меня проблемы с тем, что form_token не уникален для формы - кажется, что он остается неизменным, что бы ни случилось. Я, вероятно, неправильно понимаю, что такое токен в грандиозной схеме вида API.

Любое понимание приветствуется!

PrairieHippo
источник
В качестве продолжения я начал использовать $ form_state ['form_build_id'] вместо токена. Если я отправляю один и тот же идентификатор сборки формы дважды, то где-нибудь по пути форма все равно перестраивается и обрабатывается.
PrairieHippo

Ответы:

8

У меня была точно такая же проблема, и мне удалось исправить ее с помощью механизмов блокировки от Drupal

В функции проверки я использовал:

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

И в функции отправки я снял блокировку:

function mymodule_custom_form_submit($form, &$form_state){
  // submit code
  lock_release('your_custom_lock_name');
}
Мариус Илие
источник
1

Здесь вы должны учитывать вес модуля:

  1. Один модуль (пусть first_module), который должен иметь отрицательный вес модуля Maximum_value (может быть -2000), должен реализовывать hook_form_alter () со следующим кодом. Теперь вы должны проверить, отправлена ​​ли уже форма или нет вашим кодом.
   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. Second_module, который имеет вес возможного более высокого значения. Здесь вы должны сбросить сеанс, добавив обратный вызов submit в модуль.

function 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]);

}
sathishkumar
источник
1

Если вы хотите эту функциональность во всех формах и больше контроля без кодирования, взгляните на модуль Hide Submit Button .

Особенности:

  1. Скрыть или отключить кнопку отправки после нажатия
  2. Показать сообщение и / или изображение во время ожидания
Гокул Н.К.
источник
5
Модуль Hide Submt Button не является решением на стороне сервера. Из описания модуля: «Для браузеров с отключенным Javascript этот модуль вообще не будет работать». drupal.org/project/hide_submit
Блейк Фредерик
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);',
  ),
);

надеюсь, это поможет ..

или вы можете сослаться Предотвращение нескольких нажатий кнопки отправки, а у drupal есть один модуль Скрыть кнопку отправки

Некоторые пользователи случайно нажимают кнопку «Отправить» несколько раз, ожидая сохранения своего сообщения. В некоторых случаях это может привести к дублированию проводок или дублированию заказов электронной торговли.

madhurjya
источник
-1

Это было моей проблемой и раньше. Мое решение этого состоит в том, чтобы отключить кнопку через JS.

.module:

/**
 * 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();
    });
  }
});
}
ninjascorner
источник