Some time ago, chx posted a method to do a multi-part form. The problem with the method was that it required a lot of interesting tricks that made the actual flow very difficult to understand and was very frustrating to use.

I have a simpler one. Here is a demo.

<?php
function formtest_menu($may_cache) {
 
$items = array();
  if (
$may_cache) {
   
$items[] = array('path' => 'formtest',
     
'title' => t('custom wizard test'),
     
'callback' => 'formtest_test_page',
     
'access' => 1,
     
'type' => MENU_NORMAL_ITEM,
    );
  }
  return
$items;
}

function
formtest_test_page() {
 
drupal_set_header("CacheControl: no-cache");
 
drupal_set_header("Pragma: no-cache");
 
drupal_set_header("Expires: -1");
 
$form = $_SESSION['formtest_test_form'];
  if (
$form) {
    return
drupal_get_form($form['id'], $form['data']);
  }

 
$status = $_SESSION['formtest_test_status'];

  if (!
$status) {
    return
formtest_form1();
  }

  switch (
$status['next_form']) {
    case
'breakfast':
      return
formtest_form_breakfast();
    case
'lunch':
      return
formtest_form_lunch();
    case
'finish':
      return
formtest_form_finish();
    default:
     
// oops?
     
return formtest_form1();
  }
}

function
formtest_do_form($form_id, $form) {
 
$_SESSION['formtest_test_form']['id'] = $form_id;
 
$_SESSION['formtest_test_form']['data'] = $form;
  return
drupal_get_form($form_id, $form);
}

function
formtest_form1() {
 
$form['which'] = array(
   
'#type' => 'select',
   
'#title' => t('Do you wish to eat breakfast or lunch?'),
   
'#default_value' => 'breakfast',
   
'#options' => array('breakfast' => "Breakfast", 'lunch' => "Lunch"),
  );

 
$form['name'] = array(
   
'#type' => 'textfield',
   
'#title' => t('Your name'),
   
'#required' => true,
  );

 
$form['submit'] = array(
   
'#type' => 'submit',
   
'#value' => "Continue",
  );

  return
formtest_do_form('formtest_form1', $form);
}

function
formtest_form1_submit($form_id, $form) {
 
$_SESSION['formtest_test_status']['next_form'] = $form['which'];
 
$_SESSION['formtest_test_status']['name'] = $form['name'];
  unset(
$_SESSION['formtest_test_form']);
  return
drupal_goto('formtest');
}

function
formtest_form_breakfast() {
 
$form['food'] = array(
   
'#type' => 'select',
   
'#title' => t('Choose your breakfast'),
   
'#default_value' => 'eggs',
   
'#options' => array('eggs' => "Eggs", 'pancakes' => "Pancakes", 'waffles' => "Waffles"),
  );

 
$form['submit'] = array(
   
'#type' => 'submit',
   
'#value' => "Continue",
  );

  return
formtest_do_form('formtest_form_breakfast', $form);
}

function
formtest_form_breakfast_submit($form_id, $form) {
 
$_SESSION['formtest_test_status']['chose'] = 'breakfast';
 
$_SESSION['formtest_test_status']['food'] = $form['food'];
 
$_SESSION['formtest_test_status']['next_form'] = 'finish';
  unset(
$_SESSION['formtest_test_form']);
  return
drupal_goto('formtest');
}

function
formtest_form_lunch() {
 
$form['food'] = array(
   
'#type' => 'select',
   
'#title' => t('Choose your lunch'),
   
'#default_value' => 'sandwich',
   
'#options' => array('sandwich' => "Sandwich", 'burger' => "Burger", 'soup' => "Soup"),
  );

 
$form['submit'] = array(
   
'#type' => 'submit',
   
'#value' => "Continue",
  );

  return
formtest_do_form('formtest_form_lunch', $form);
}

function
formtest_form_lunch_submit($form_id, $form) {
 
$_SESSION['formtest_test_status']['chose'] = 'lunch';
 
$_SESSION['formtest_test_status']['food'] = $form['food'];
 
$_SESSION['formtest_test_status']['next_form'] = 'finish';
  unset(
$_SESSION['formtest_test_form']);
  return
drupal_goto('formtest');
}

function
formtest_form_finish() {
 
$data = $_SESSION['formtest_test_status'];
 
$output = "Here is your $data[food], $data[name]. Enjoy your $data[chose]!";
  unset(
$_SESSION['formtest_test_status']);
  unset(
$_SESSION['formtest_test_form']);
  return
$output;
}
?>

Comments

a recent patch to sessions.inc optimized drupal for the case where anon users are not using sessions. so that optimization gets blown away for techniques like this. if possible use this for logged in users only.

I've been told various things about sessions support in Drupal. Clearly I need to just look this up. Mostly when using forms like this, a login would seem to be necessary, but I can imagine things like surveys or the like that could make it important for anonymous users too. I'll have to look and see if there's a way to force sessions on, at least for the purpose of the form.

Thank you so much for posting this - a fab example!!!

This was clearly posted a little while back when drupal 4.x.x was around and drupal API has moved on a little since then. So, for anyone wishing to do this for drupal 5.x, I believe the calls: "return drupal_get_form" should be replaced as follows:

drupal_process_form($form_id, $form);
return drupal_render_form($form_id, $form);

Add new comment