pogo
pogo

Reputation: 2307

Can I stop Drupal re-creating a form when it's submitted?

I have a booking form that's built using options that are retrieved via a third party API and because of the need to have up to date information the results from the API can't be cached (at least not for very long).

The problem I'm having is I've noticed when the form is submitted Drupal is re-calling my _form function which is triggering the API calls again and I'd like to stop it doing that to try and reduce the number of API calls that are made.

Obviously if the validation fails it needs to re-draw the form and the API calls will need to be made again but I'm wondering if there's a way to stop it doing this when the form validates so I can stop it making lots of unnecessary calls to the API.

Thanks for any help.

Upvotes: 7

Views: 2103

Answers (4)

Coomie
Coomie

Reputation: 4868

Drupal can't do this? "Can't" isn't in my vocabulary!

I had this same problem, but I couldn't let it beat me. Here's how I got over it:

In the processing form, after I insert the details into the database (or email or whatever), I set 2 drupal status messages like this

function process_form($form){
  $success = do_email($form);
  if ($success){
    drupal_set_message("Success");
    drupal_set_message("Your form worked!");
  }
}

And in the form generator I read and clear the messages, clear the form and output the status message as markup:

function form_generator($form_state,$parameters){
  $form = array();
   ...// This is where I make the regular form
  $messages = drupal_get_messages(); // this gets the messages and clears them
  if (isset($messages["status"])){
    if (isset($messages['status'][0]) && isset($messages['status'][1])){
      if ($messages['status'][0]=="Success"){
        $form = array(); // This clears the form I've just made
        $form['final_message']= array(
          '#type' => 'markup',
          '#markup' => $messages['status'][1],
        );
      }
    }
  }
}

This doesn't clear the form the first time it's shown because $messages isn't set and when you encounter validation errors they will still appear.

Drupal magic bars our way, but the will of PHP coder is stronger.

Upvotes: 0

Henrik Opel
Henrik Opel

Reputation: 19441

You can not avoid the re-creation of the form, if the form is to be processed by Drupal. It is a central part of Drupals form processing workflow: Every form is at least build twice, once for initial output, and at least once again when the post from the client comes in. It can even be more than that, depending on what the form does afterwards, e.g. on redisplay when any validation errors occurs (Usually a cached version gets used by then, but that depends on the specific form).

What you should do is follow Simons suggestion - on the first call to your form builder function, make your API calls and store the results in $form_state['storage']['yourIdentifier'] ('yourIdentifier' being some string not used by standard form processing - usually starting with your modules name). On every call to your form builder function, you check if that results are already in $form_state['storage']. If they are, you just use those, skipping the API calls.

This will avoid the duplicate API calls, and gives you more control on how/when to do them (e.g. you can also clear those results during validation, if a special condition calls for a refetching from the external API).

Upvotes: 4

googletorp
googletorp

Reputation: 33275

First thing, If validation fails, Drupal has a copy of the form, so your form function won't actually be called.

Now to the solution.

  • You can redirect to a new page in your form submit, go avoid the recalling og the form.
  • Instead of calling your form directly in your menu definition make a callback that calls the form. You can then test if the form has been submitted or not and only call your form function when needed.

If you are this worried about the API calls you could also cache it for 5-10 mins which would make my two suggestions obsolete.

Upvotes: 0

Simon
Simon

Reputation: 37978

Could you store/cache the return values from the API in the $form_state['storage'], so at least if _form gets called every time you can first check storage before making the API calls again.

Upvotes: 3

Related Questions