Why does my drupal (v6) multistep form reset?
I have a multistep form (6 steps total). If I am on say step 3 and I wait a few minutes (approx 3) before hitting next or previous, the form sends me back to step 1 and all data is lost. Why is this happening and how can I stop it?
Edit: Here is the form code (I took out some parts that aren't relevant, like all the form fields for each step, nothing special there):
function display_job_application_form($form_state, $jobid)
{
$form['#multistep'] = TRUE;
$jobappid = get_job_app_id($jobid);
$last_step = get_application_step($jobappid);
if($last_step >= 7)
{
drupal_set_message("You have already applied for this job.", "error");
}
if (!isset($form_state['storage']['step']))
{
if($last_step >= 0)
{
$form_state['storage']['step'] = ($last_step >= 6) ? $last_step : $last_step + 1;
}
else
{
$form_state['storage']['step'] = $_GET['page']?$_GET['page']:1;
}
}
$db_data = decrypt_data($jobid, "data_step".$form_state['storage']['step']);
$default_value = '';
if (isset($form_state['storage']['values'][$form_state['storage']['step']])) {
$default_value = $form_state['storage']['values'][$form_state['storage']['step']];
}
else if(is_array($db_data) && count($db_data) > 0)
{
$default_value = $db_data;
}
$form['step'] = array(
'#type' => 'hidden',
'#value' => $form_state['storage']['step'] + 1,
);
$form['jobid'] = array(
'#type' => 'hidden',
'#value' => $jobid,
);
switch($form_state['storage']['step']){
case 1:
//page 1 form fields
break;
case 2:
//page 2 form fields
break;
case 3:
//page 3 form fields
break;
case 4:
//page 4 form fields
break;
case 5:
//page 5 form fields
break;
case 6:
//page 6 form fields
break;
}
if ($form_state['storage']['step'] > 1)
{
$form['previous'] = array(
'#type' => 'submit',
'#value' => t('<< Previous'),
);
}
if ($form_state['storage']['step'] != 6)
{
$form['next'] = array(
'#type' => 'submit',
'#value' => t('Continue >>'),
);
}
else {
$form['finish'] = array(
'#type' => 'submit',
'#value' => t('Finish'),
);
}
$form['#theme'] = 'theme_display_job_application_form_form';
return $form;
}
function display_job_application_form_submit($form, &$form_state)
{
global $user;
$form_state['storage']['values'][$form_state['storage']['step']] = $form_s开发者_StackOverflowtate['values'];
$jobid = $form_state['values']['jobid'];
$id = get_job_app_id($jobid);
if($form_state['storage']['step'] == 1 && $id < 0)
{
//INSERT INTO DB
}
else
{
//UPDATE DB FOR EACH STEP
}
if ($form_state['clicked_button']['#id'] == 'edit-previous')
{
$form_state['storage']['step']--;
}
elseif ($form_state['clicked_button']['#id'] == 'edit-next')
{
$form_state['storage']['step']++;
}
elseif ($form_state['clicked_button']['#id'] == 'edit-finish' && $form_state['storage']['values'][6]['checkbox'])
{
//UPDATE DB, SEND EMAIL
unset($form_state['storage']);
$form_state['redirect'] = '';
}
}
Some observations
- In Drupal 6
#multistep
is gone: http://drupal.org/node/144132#multistep - Using
hidden
elements won't protect your values. It's best to use avalue
element. Just don't confusevalue
with#value
. First is a type of form element, the second is the value of an element.
E.g. $form['secret'] = array( '#type' => 'value', '#value' => 123)
When the form is submitted: $form_state['values']['secret'] = 123
- I'm a bit confused of the many condition which determine you're step. Especially since you call an external function and I'm with Henrik on this one. Something could happen there and I'm not sure it's good idea to let the step of the form be determined by another function. You should know on which step you are. So this part of the code should be simpler:
$step = isset($form_state['storage']['step']) ? (int) $form_state['storage']['step'] : 0;
- And then make sure you increment your step number (I wouldn't do this in the submit function, at that point it means the validation was OK and we can move on to the next step/go back, not making decisions):
$form_state['storage']['step'] = $step + 1
(I prefer to avoid incremental operators which could confuse me.)
Give these a try, see if they solve your problem :)
精彩评论