web-dev-qa-db-ja.com

Drupal 7 "フォームは古くなっています。未保存の作業を以下のフォームにコピーしてから、このページを再読み込みしてください。"

私は問題があります。このコードをモジュールに配置すると、チェックボックスはうまく機能しますが、フォームはエラーをスローします。

"The form has become outdated. Copy any unsaved work in the form below and then reload this page."

1つのノード追加フォームに警告します。

function automobil_form_auto_node_form_alter(&$form, &$form_state, $form_id) {

  $form['add_phone'] = array (
    '#type' => 'fieldset',
    '#title' => t('Adauga telefon'),
    '#weight' => 6,
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );

  $form['add_phone']['phone'] = array(
    '#type' => 'phone',
    '#title' => t('Phone Number'),
    '#required' => TRUE,
  );

  $form['add_phone']['phone_submit'] = array (
    '#type' => 'button',
    '#value' => 'Add',
    '#prefix' => '<div class="col-md-6 text-left">',
    '#suffix' => '</div>',
    '#ajax' => array(
      'callback' => 'automobil_add_phone_callback',
      'wrapper' => 'add-new-phone',
      'effect' => 'fade',
    ),
  );

  if(isset($form_state['values']['phone']['prefix'])) {
    $upload_users_phone = _upload_users_phone($form, $form_state, 'add');
  } else {
    $upload_users_phone = _upload_users_phone($form, $form_state, '');
  }

  $form['field_temporary_phone'] = array(
    '#prefix' => '<div id="add-new-phone">',
    '#suffix' => '</div>',
    '#title' => t('Telefon'),
    '#type' => 'checkboxes',
    '#weight' => 5,
    '#options' => $upload_users_phone,
  );
}

Ajaxコールバック

function automobil_add_phone_callback(&$form, &$form_state) {
  return $form;
}

ユーザープロファイルに格納されているuser_phoneのリストを返す関数。ユーザーが新しい電話を追加すると、電話が追加され、更新されたリストが返されます。

    function _upload_users_phone($form, $form_state, $operation, $returns) {
  global $user;
  // load user

  $existingUser = user_load($user->uid);

  if($operation == 'add') {
    $existingUser->field_user_phone['und'][]['value'] = $form_state['values']['phone']['prefix'] . ' ' . $form_state['values']['phone']['number'];
    $user = user_save((object) array('uid'=>$user->uid), (array) $existingUser);
  }
    // edit field-data
  foreach ($existingUser->field_user_phone['und'] as $key => $value) {
    $val_list[] = $value['value'];
    $key_list[] = $key;
  }

  return $val_list;
}

問題とは何ですか(「フォームの古いフォーム」エラーがスローされるのはなぜですか)?

4
user27619

「フォームが古くなっています」と表示される理由。エラーは、トークンが検証に失敗したためです(古い文字列が新しい文字列と一致しないことを意味します)。トークンは、session_id()を含むいくつかのものに対してハッシュを実行することによって決定されます。 user_save()を呼び出すと、セッションが変更/無効化/何でもされます。したがって、次にトークンをテストするとき、session_id()が異なるために別のトークンが生成され、古いフォームを使用していると考えて失敗します。

フォーム処理内からuser_save()を呼び出した後も同じ問題が発生します。私が修正した方法は、かなり大きなハックのように感じられますが、それを回避する明確な方法があることを知りません。フォームのコードは、フォーム(この場合はマルチパートフォーム)の処理中にセッションを変更/無効化することを期待していないようです。

user_saveを呼び出したら、フォームの状態を手動で変更して、更新されたトークンを挿入する必要があります。次に、トークンをチェックすると、「session_id()」が更新された後に生成された新しいトークンが一致します。

したがって、結果のコードは次のようになります。 $form_stateの参照によって渡されるように入力要素が変更され、変更が伝達されることに注意してください。

function _upload_users_phone($form, &$form_state, $operation, $returns) {
  global $user;
  // load user

  $existingUser = user_load($user->uid);

  if($operation == 'add') {
    $existingUser->field_user_phone['und'][]['value'] = $form_state['values']['phone']['prefix'] . ' ' . $form_state['values']['phone']['number'];
    $user = user_save((object) array('uid'=>$user->uid), (array) $existingUser);
    $form_state['input']['form_token'] = drupal_get_token($form['#token']);
  }
    // edit field-data
  foreach ($existingUser->field_user_phone['und'] as $key => $value) {
    $val_list[] = $value['value'];
    $key_list[] = $key;
  }

  return $val_list;
}

$form_state['values']['form_token']も設定する必要があるかもしれませんが、それは不必要だと確信しています。繰り返しますが、関数変数&の宣言の前の$form_stateを忘れないでください。そうしないと、値が実際の配列に入れません。

1
geis

「フォームが古くなっています」と表示される理由。エラーは、トークンが検証に失敗したためです(古い文字列が新しい文字列と一致しないことを意味します)。

unset($ form ['#token']);を使用します

これは、何らかの理由で Form API を正しく使用していないために発生します。

回避策としては、フォームにform_tokenを追加してみてください。次に例を示します。

$form ['#token'] = $form_id;
$form ['form_token'] = array(
  '#id' => drupal_html_id('edit-' . $form_id . '-form-token'),
  '#type' => 'token',
  '#default_value' => drupal_get_token($form['#token']),
  '#parents' => array('form_token'),
);
}

それが機能するかどうかを確認します。

参照: 「フォームが古くなりました」エラーの取得

0
kenorb