防止多次提交表单(服务器端)


9

我遇到了一个问题,用户可以多次提交由Form 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在api宏方案中的含义。

任何见解表示赞赏!


作为后续,我开始使用$ form_state ['form_build_id']代替令牌。如果我两次提交相同的表单构建ID,则无论如何都要重新构建和处理表单。
PrairieHippo 2012年

Answers:


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)的模块权重为负max_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]);

}

1

如果要在所有表单上使用此功能并无需编码即可进行更多控制,请查看“ 隐藏提交按钮”模块。

特征:

  1. 单击后隐藏或禁用提交按钮
  2. 等待时显示消息和/或图像

5
Hide Submt Button模块不是服务器端解决方案。在模块的描述中:“对于禁用Javascript的浏览器,该模块将完全无效。” 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);',
  ),
);

希望这会有所帮助..

或者您可以参考防止多次单击提交按钮和drupal具有一个模块隐藏提交按钮

有些用户在等待保存其帖子时不小心多次单击了提交按钮。在某些情况下,这可能导致重复的过帐或重复的电子商务订单。


-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();
    });
  }
});
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.