form api

Drupal Form API 'value' element

It’s common to use hidden value in a form to specify certain variable that was meant to logic which would handle the form processing rather than the user facing the form, hence the name ‘hidden’. Drupal Form API provide special element ‘value’ that can be used for the same task except that the value would not be sent together with the form. Let say you need to main a refference to customer_id when user entering their order in order form, the typical way is to used hidden element like this:-

$form['customer_id'] = array('#type' => 'hidden', '#value' => $customer_id);

This would put the value as a hidden form element and sent along other form value when user submit the form. The alternative is to use the ‘value’ element:-

$form['customer_id'] = array('#type' => 'value', '#value' => $customer_id);

No value would be sent to the browser but it’s still available to the form submit handler just like any other element. Neat idea, I think.

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.

Syndicate content