Drupal Form API Gotcha

Doing an upgrade of my app from Drupal 4.7.x to Drupal 5.x. The big difference in Form API in Drupal 5.x vs 4.7.x is on how drupal_get_form (the way form is build) work. In 4.7.x, drupal_get_form work through a push model where we supply the array of form definition to the function call:-

function customer_edit($customer) {
  $form = array();
  $form['customer_name'] = array(
    '#type' => 'textfield',
    '#title' => 'Name',
    '#default_value' => $customer->name
  );
  return drupal_get_form($form, 'customer_edit');
}

The second argument is the form_id. In 5.x however, this has changed to pull model where the form definition need to be build in a dedicated builder function.

function customer_build_form() {
  $form = array();
  $form['customer_name'] = array(
    '#type' => 'textfield',
    '#title' => 'Name',
    '#default_value' => $customer->name
  );
  return $form;
}

function customer_edit($customer) {
  return drupal_get_form('customer_build_form');
}

Now the first argument to drupal_get_form function call is the name of the form builder function. Another way is to implement the new hook introduced hook_forms to do some complex mapping of form_id to builder function.

function customer_forms() {
  $forms = array();
  $forms['customer_edit'] = array(
    'callback' => 'customer_build_form'
  );
  $forms['customer_add'] = array(
    'callback' => 'customer_build_form'
  );
}

function customer_edit($customer) {
  return drupal_get_form('customer_edit');
}

I got some problems when using the hook_forms approach. No errors from PHP process and Nginx just gave an ‘500 server error’. Further checking revealed that the problem was with the form_id which is similar to already defined function name. My guess was some recursive calling occured when drupal_get_form first try to call a function named customer_edit as being used in the form_id. Unfortunately, the calling function was also a customer_edit. So the fix is, never used form_id that is similar to already defined function since drupal_get_form will first look for it instead of relying on the hook_forms if it is implemented.