Mencegah Banyak Pengajuan Formulir (sisi Server)

9

Saya mengalami masalah di mana pengguna dapat mengirimkan formulir apa pun yang dibangun oleh API Formulir beberapa kali (klik cepat yang menghasilkan banyak permintaan).

Saya telah memasukkan solusi sisi klien dasar (javascript) menonaktifkan tombol, tapi saya ingin tahu apa pendekatan terbaik untuk mencegah situasi ini di sisi server.

Apakah ada cara yang disarankan untuk menggunakan sistem token form Drupal untuk menangani ini? Terutama solusi formulir global (yaitu, menambahkan validator kustom ke setiap formulir menggunakan hook_form_alter ()).

Pendekatan saya sejauh ini adalah seperti ini:

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

Saya mengalami masalah di mana form_token tidak unik pada formulir - sepertinya tetap sama apa pun yang terjadi. Saya mungkin salah paham apa token yang ada dalam skema besar bentuk api.

Wawasan apa pun dihargai!

PrairieHippo
sumber
Sebagai tindak lanjut, saya mulai menggunakan $ form_state ['form_build_id'] alih-alih token. Jika saya mengirimkan id build form yang sama dua kali, di suatu tempat sepanjang form mendapatkan dibangun kembali dan diproses lagi.
PrairieHippo

Jawaban:

8

Saya memiliki masalah yang sama persis dan berhasil memperbaikinya menggunakan mekanisme Penguncian dari Drupal

Dalam fungsi validasi yang saya gunakan:

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

Dan dalam fungsi kirim, saya melepaskan kunci:

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

Di sini Anda harus mempertimbangkan bobot modul:

  1. Satu modul (misalkan first_module) yang seharusnya memiliki bobot modul negatif maksimum_nilai (mungkin -2000) di sini ia harus menerapkan hook_form_alter () dengan kode berikut. Sekarang Anda harus memverifikasi apakah formulir sudah dikirimkan atau belum oleh kode Anda.
   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. Modul kedua yang memiliki bobot memiliki nilai yang lebih tinggi. Di sini Anda harus membatalkan sesi dengan menambahkan ajukan panggilan balik ke modul

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
sumber
1

Jika Anda ingin fungsionalitas ini pada semua formulir dan kontrol lebih banyak tanpa pengkodean lihatlah modul Sembunyikan Tombol Kirim .

Fitur:

  1. Sembunyikan atau nonaktifkan tombol kirim setelah diklik
  2. Tampilkan pesan dan / atau gambar sambil menunggu
Gokul NK
sumber
5
Modul Sembunyikan Submt Tombol bukan solusi sisi server. Dari deskripsi modul: "Untuk browser dengan Javascript dinonaktifkan modul ini tidak akan berpengaruh sama sekali." 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);',
  ),
);

Semoga ini bisa membantu ..

atau Anda dapat merujuk Mencegah beberapa klik tombol kirim & drupal memiliki satu modul Sembunyikan tombol kirim

Beberapa pengguna secara tidak sengaja mengklik tombol kirim lebih dari sekali sambil menunggu posting mereka disimpan. Dalam beberapa kasus, ini dapat menyebabkan pengiriman duplikat atau duplikat pesanan e-commerce.

madhurjya
sumber
-1

Ini juga masalah saya sebelumnya. Solusi saya untuk ini adalah menonaktifkan tombol melalui JS.

.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();
    });
  }
});
}
ninjascorner
sumber