Hi,

I have a form that is being cached that is causing me all sorts of problems. Basically I am pre-populating the form with data based on some runtime information, but because it is being cached, the pre-populating data is incorrect when rendering a cached form.

So how can I make it so that this one form absolutely does not get cached ever? When I turn off caching in Site Configuration the form behaves like it should. Obviously I do not want this to be my long term solution.

I have tried:

$form['#cache'] = FALSE;

But this doesn't seem to work and I can't find much documentation on this.

Please help. Thanks.

Comments

cayenne’s picture

Have you tried the cache-exclude module?
http://drupal.org/project/cacheexclude

:)

KingMoore’s picture

Cayenne,

Thanks for the link. I have not tried that. Looking at it I don't know if it would work to not cache forms. Maybe though.

It seems like this ability should be available in core. I have found various references to different ways to do this, but no firm documentation. Here is what I have tried so far and my results:

With Caching set to 'Normal' in the admin/settings/performance, here were my results:

$form['#cache'] = FALSE; - does not prevent my form from being cached
$form['#no_cache'] = TRUE; - does not prevent my form from being cached
$form_state['cache'] = FALSE; - does not prevent my form from being cached

jaypan’s picture

All forms created using the form API are cached - it's how Drupal deals with forms. This is a security measure. Drupal checks the returned values against the original values, and if there are any discrepancies, it throws an error.

But the forms are cached at run time, so turning off caching doesn't really make sense.

Why don't you show us your code and the specific problem?

Contact me to contract me for D7 -> D10/11 migrations.

KingMoore’s picture

Thanks for the info.

I have found numerous references to the $form['#cache'] property...

Anyways, my specific problem is that I have a form and I am setting the #default_value of several of the fields at runtime... IE the default values of the form change. However, if we have a cached version of the form, a user comes to the form and gets an old version of the form with incorrect default values of the fields.

Forcing the form to not be cached would solve this problem, but I can't figure any way to do it besides turning off all drupal caching.

jaypan’s picture

I've done exactly what you are speaking of (set the default based on runtime environment) without any problems many times in the past.

Contact me to contract me for D7 -> D10/11 migrations.

KingMoore’s picture

Here's some more details, but I think I have isolated down to the form being cached and I want it to not be cached.

All users are anonymous
When a user comes to my form, the form reads a session variable for the user and sets default values accordingly (from the session variable).

I can do the following:

- Turn off drupal caching
- go to form
- form renders correctly every time
- Turn on "Normal Caching"
- clear my browser cookie and cache (clears my session)
- go to form
- form is rendered correctly
- clear my browser cookie and cache
- go to form
- form displays information identical to what it displayed last time
- clear all drupal cache
- clear my browser cookie and cache
- go to form
- form is rendered correctly (only one time is it rendered correctly after cache is cleared, subsequent times it shows data from previous form rendering)

jaypan’s picture

Lets see your form code.

Contact me to contract me for D7 -> D10/11 migrations.

KingMoore’s picture

Here's the form. It checks to see if the user has a USERNAME stored in the session, meaning they are logged in to a 3rd party system I am integrated with. If so it loads all the user information and uses it as default_values in the form.

Thanks for taking the time to help by the way. This has me stumped. If forms are always cached as you say, then I don't understand how your forms could display different #default_values based on run-time info. I can even put a die() call at the top of my form function and nothing happens.

Also, just to be clear, I am on Drupal 6.16.

function ff_users_info_form(&$form_state) {

  $form = array();

  $form['#tree'] = TRUE;
  
  //turn off form caching
  $form_state['no_cache'] = TRUE;

    
  //if we have a current user coming to the form show their info in the form
  if($username = $_SESSION['USERNAME']) {
    $user = ff_users_get_user_info($username);
  }
 
  $form['account_details'] = array(
    '#type' => 'fieldset', 
    '#title' => t('Account Details'), 
  );  
  
  $form['account_details']['first_name'] = array(
    '#type' => 'textfield', 
    '#title' => t('First Name'), 
    '#size' => 36,
    '#default_value' => ($user['first_name']) ? $user['first_name'] : '',    
    '#required' => TRUE,
  );  
  
  $form['account_details']['last_name'] = array(
    '#type' => 'textfield', 
    '#title' => t('Last Name'), 
    '#size' => 36,
    '#default_value' => ($user['last_name']) ? $user['last_name'] : '',    
    '#required' => TRUE,
  );  
  
  $form['account_details']['email'] = array(
    '#type' => 'textfield', 
    '#title' => t('E-Mail Address'),
    '#size' => 36,
    '#default_value' => ($user['email']) ? $user['email'] : '',    
    '#required' => TRUE,
  );      
  
  $form['account_details']['address'] = array(
    '#type' => 'textfield', 
    '#title' => t('Address'), 
    '#size' => 36,
    '#default_value' => ($user['address1']) ? $user['address1'] : '',    
    '#required' => TRUE,
  ); 

  $form['account_details']['address2'] = array(
    '#type' => 'textfield', 
    '#title' => t('Address 2'),
    '#size' => 36,
    '#default_value' => ($user['address2']) ? $user['address2'] : '',
    '#description' => '(if needed)', 
    '#required' => FALSE,
  );  

  $form['account_details']['city'] = array(
    '#type' => 'textfield', 
    '#title' => t('City'),
    '#size' => 36,
    '#default_value' => ($user['city']) ? $user['city'] : '',    
    '#required' => TRUE,
  );    
  
  $form['account_details']['state'] = array(
    '#type' => 'textfield', 
    '#size' => 10,    
    '#title' => t('State or Province'),
    '#default_value' => ($user['state']) ? $user['state'] : '',    
    '#required' => TRUE,
  );      
  
  $form['account_details']['zip'] = array(
    '#type' => 'textfield', 
    '#size' => 10,    
    '#title' => t('Postal Zip Code'),
    '#default_value' => ($user['zip']) ? $user['zip'] : '',    
    '#required' => TRUE,
  );   

  $form['account_details']['country'] = array(
    '#type' => 'textfield', 
    '#title' => t('Country'),
    '#size' => 36,
    '#default_value' => ($user['country']) ? $user['country'] : 'USA',    
    '#required' => TRUE,
  ); 
  
  $form['account_details']['phone'] = array(
    '#type' => 'textfield', 
    '#title' => t('Telephone Number'),
    '#description' => '(area code first)',
    '#size' => 36,
    '#default_value' => ($user['phone']) ? $user['phone'] : '',    
    '#required' => FALSE,
  );   

  return $form;
}

jaypan’s picture

Hmm, looks mostly ok to me.

Try changing this:

if($username = $_SESSION['USERNAME']) {
    $user = ff_users_get_user_info($username);
  }

to this:

$user = array();
if($username = $_SESSION['USERNAME']) {
    $user = ff_users_get_user_info($username);
  }

As for how forms are cached - they are cached at runtime each time the form is loaded. It's different from other caching on the site. The process with forms is this:

1) The form is built from the form API declaration
2) The form is saved to the cache table
3) The form is sent to the user
4) The user fills out the form and submits the form
5) Drupal compares the submitted values to the cached values, and makes sure that all values were legit. If they weren't, an error is thrown.
* If the user loads the form from scratch (ie - doesn't refresh the page, but rather reloads it), the process starts at step one again

This is how form caching works, and why it shouldn't matter that forms are cached.

Let me know how the code above works, and if it doesn't, we can take it from there.

Contact me to contract me for D7 -> D10/11 migrations.

KingMoore’s picture

No help unfortunately.

So what you are saying is that forms are cached... but not like a page cache where drupal will keep serving out the cached page to new users...

Because that what is happening. It's like the form is built once with the data and saved into the cache table. Then anyone who comes to the page gets the cached version of the form, exactly like it was built the first time, with someone elses runtime info in there.

To further prove this point, I view the page with the form on it. The I can add a die(); statement as the first line of my form function and refresh the page and it looks the same (ie does not die). This seems to prove that my form function is not being called each time the page with the form on it is rendered, but rather a fully cached version of the form is being loaded and displayed.

joshi.rohit100’s picture

I don't see anything related with cache as you are just trying to populate default value of the form fields. Also in earlier comment you said that users are anonymous. If that's the case then you will never have the session variable. Also just simple create form array (just remove that cache part and call by reference form_state from argument).

KingMoore’s picture

also, there is evidence of a $form_state['cache'] variable here, in it's request to be documented issue:

http://drupal.org/node/689084

and of $form['#cache']

http://drupal.org/node/299672

andy inman’s picture

I can't see how to *stop* a form from being cached, but you can delete it from the cache. I needed to clear a cached form during an AHAH update so that the form would be regenerated with new values, and this worked:

  cache_clear_all('form_'. $_POST['form_build_id'], 'cache_form');

In other situations you may get form_build_id from $form_state['values'] or $form_state['storage'].

spelcheck’s picture

cache_exclude module worked for me on a webform with some dynamic content built into its theme. Thanks!

TheBarnacle’s picture

Did you ever solve this? I have the same problem, and cacheexclude doesn't seem to fix it. In the database I can see caching at three levels:

  1. cache_form
  2. cache_block
  3. cache_page - cacheexclude seems only to target this one

Anybody know how I stop the form from caching? The reason is that drupal_process_states() seems not to get called from the cached form, if the $_GET params are different. This leads to the form showing elements it's not supposed to show.

MantasK’s picture

you can try using #after_build

$form['#after_build'] = array('your_function')

and then

   function your_function($form, &$form_state)

in after build function you can reset your default values. I haven't tested it for this case, but it worked for me when I wanted to escape validation after form cache was expired.
not exactly what you want, but it could be workaround

pierre521’s picture

I try to disable cache form because there are many users use my form in the same time and my table cache_form is too big even if cron is often run to clear the table.

So for the moment I use this code for truncate my table on my form function... It work but it's not very clean ...

$result = db_truncate('cache_form')->execute();
watchdog('cache_form truncate', $result);

Is not possible to simply disable form caching ? I looked everywhere but could not find a solution ..

Sorry for my broken English I'm french ..

divined’s picture

$form['#cache'] = [
      'max-age' => 0
    ];

it is work for D8.