web-dev-qa-db-fra.com

Formulaire non valide POST data - ajax for Authenticated users

J'ai un formulaire Drupal utilisant ajax. Lorsque je soumets le formulaire, je reçois les informations suivantes:

enter image description here

Lorsque je vérifie le journal Drupal, j'ai l'entrée suivante.

enter image description here

J'ai googlé l'erreur et trouvé this post mais cela s'applique aux utilisateurs anonymes. Je l'utilise uniquement avec des utilisateurs authentifiés.

La recherche de l'erreur dans le code renvoie la fonction ajax_get_form() dans ajax.inc

 $form_state = form_state_defaults();

  $form_build_id = $_POST['form_build_id'];

  // Get the form from the cache.
  $form = form_get_cache($form_build_id, $form_state);
  if (!$form) {
    // If $form cannot be loaded from the cache, the form_build_id in $_POST
    // must be invalid, which means that someone performed a POST request onto
    // system/ajax without actually viewing the concerned form in the browser.
    // This is likely a hacking attempt as it never happens under normal
    // circumstances, so we just do nothing.
    watchdog('ajax', 'Invalid form POST data.', array(), WATCHDOG_WARNING);
    drupal_exit();
  }

$form N'est pas un objet. Je ne suis pas sûr pourquoi.

Dans la fonction ajax_get_form() je fais un dd() de $form_build_id. Cela me renvoie quelque chose comme form-ymw-BN0Zhp9j2CZf82mZzslbUBiLo8kZbreXhB1y8kE.

Si j'exécute le SQL suivant dans la base de données, j'obtiens un résultat.

select *  from cache_form where cid like '%form-ymw-BN0Zhp9j2CZf82mZzslbUBiLo8kZbreXhB1y8kE%';

Le cid dans cet exemple est form_state_form-ymw-BN0Zhp9j2CZf82mZzslbUBiLo8kZbreXhB1y8kE.

Dans form_get_cache (), le code est le suivant:

function form_get_cache($form_build_id, &$form_state) {
  if ($cached = cache_get('form_' . $form_build_id, 'cache_form')) {
     //code missing
  }
}

Dans cache_get(), nous recherchons form_form-ymw-BN0Zhp9j2CZf82mZzslbUBiLo8kZbreXhB1y8kE Mais ce que nous avons stocké dans la base de données est form_state_form-ymw-BN0Zhp9j2CZf82mZzslbUBiLo8kZbreXhB1y8kE. Bien sûr, nous ne correspondons pas, donc rien n'est retourné.

Je ne sais pas pourquoi cela se produit.

Mon code de formulaire est le suivant

  $form['welcome'] = array(
    '#markup' => //some html markup,
  );


  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Test'),
    '#ajax' => array(
      'callback' => 'myform_js',
      'wrapper' => 'message_container',
      'method' => 'replace',
      'effect' => 'fade',
      'event' => 'click',
    ),
  );

  $form['result'] = array(
    '#prefix' => '<div id="message_container">',
    '#suffix' => '</div>',
    '#type' => 'fieldset',
  );

La fonction myform_js() n'est pas atteinte car lorsque dd () est ajouté en haut, elle n'est pas appelée. Je ne vois rien de mal à l'évidence, donc je ne sais pas s'il y a des problèmes environnementaux qui pourraient causer le problème.

J'ai également essayé de changer le type de $form['submit'] En button.

Il semble que la partie qui échoue est l'appel à cache_set(). Je ne sais pas pourquoi pour le moment.

6
Rodney

OK pense que je l'ai.

Comme form_form-ymw-BN0Zhp9j2CZf82mZzslbUBiLo8kZbreXhB1y8kE N'était pas défini, j'ai regardé form_set_cache().

/**
 * Stores a form in the cache.
 */
function form_set_cache($form_build_id, $form, $form_state) {
  // 6 hours cache life time for forms should be plenty.
  $expire = 21600;

  // Cache form structure.
  if (isset($form)) {
    if ($GLOBALS['user']->uid) {
      $form['#cache_token'] = drupal_get_token();
    }
    cache_set('form_' . $form_build_id, $form, 'cache_form', REQUEST_TIME + $expire);
  }

  // Cache form state.
  if ($data = array_diff_key($form_state, array_flip(form_state_keys_no_cache()))) {
    cache_set('form_state_' . $form_build_id, $data, 'cache_form', REQUEST_TIME + $expire);
  }
}

J'ai creusé dans cache_set()

function cache_set($cid, $data, $bin = 'cache', $expire = CACHE_PERMANENT) {
  return _cache_get_object($bin)->set($cid, $data, $expire);
}

J'ai ensuite examiné set()

  /**
   * Implements DrupalCacheInterface::set().
   */
  function set($cid, $data, $expire = CACHE_PERMANENT) {
    $fields = array(
      'serialized' => 0,
      'created' => REQUEST_TIME,
      'expire' => $expire,
    );
    if (!is_string($data)) {
      $fields['data'] = serialize($data);
      $fields['serialized'] = 1;
    }
    else {
      $fields['data'] = $data;
      $fields['serialized'] = 0;
    }

    try {
      db_merge($this->bin)
        ->key(array('cid' => $cid))
        ->fields($fields)
        ->execute();
    }
    catch (Exception $e) {
      // The database may not be available, so we'll ignore cache_set requests.
    }
  }

Ici, une exception est interceptée et non signalée. J'ai ajouté une dd() dans catch. Recherche dans drupal_debug.txt

[message:protected] => SQLSTATE[08S01]: Communication link failure: 1153 Got a packet bigger than 'max_allowed_packet' bytes

J'ai maintenant augmenté la valeur de max_allowed_packet Dans MySQL. Il a corrigé des choses.

Avec ces informations, j'ai fait plus de recherches sur Google et j'ai trouvé ceci post . Ils ont eu le même problème que moi.

9
Rodney

Après le message de surveillance "Forme non valide POST data"), notez que la fonction ajax_get_form () appelle drupal_exit ().

Votre module personnalisé peut en profiter en se connectant à hook_exit () ... à partir de là, vous pouvez reconstruire le formulaire expiré/non mis en cache et tenter de soumettre à nouveau le formulaire à l'aide du cadre ajax_commands de Drupal.

Voici un exemple de la façon dont j'ai résolu ce problème pour un formulaire de connexion utilisateur "AJAX-ified".

/**
 * Implements hook_exit().
 */
function example_exit($destination = NULL) {
  if (arg(0) == 'system' && arg(1) == 'ajax') {
    $is_user_login_form_submission = isset($_POST) && isset($_POST['name']) && isset($_POST['pass']) && isset($_POST['form_build_id']);

    if ($is_user_login_form_submission) {
      watchdog(__FUNCTION__, 'User login AJAX form submission failed. Trying again...', array(), WATCHDOG_WARNING);

      $form_build_id = $_POST['form_build_id'];
      $form_state = form_state_defaults();
      $form_state['values'] = $_POST; // Important!
      $form = drupal_rebuild_form('user_login', $form_state);
      $form['#build_id_old'] = $form['#build_id']; // Important!

      // Try form submission again after it is rebuilt above
      $commands[] = ajax_command_update_build_id($form);
      $commands[] = ajax_command_invoke('form#user-login', 'trigger', array('submit'));

      print ajax_render($commands);
    }
  }
}
2
Clay

Je sais que cette question a été résolue, mais j'ai rencontré "Forme non valide POST données" et la cause était différente, donc je vais la jeter là-bas pour les personnes qui rencontrent cela.

Fondamentalement, mon coupable était un travail cron qui était particulièrement zélé, effaçant le cache toutes les 5 minutes. Le problème ne concernait pas les limites de mémoire ou l'écriture dans la base de données, mais plutôt que le formulaire était souvent mis en cache, le cache était effacé, puis la tentative d'obtention du formulaire à partir du cache échouait. La commutation du travail cron en horaire le fixe.

1
ognockocaten