7

ATTENTION: This was not a cache problem, nor a server misconfiguration, nor a browser issue. After careful investigation, I've found the problem was due to a problem in my code: Stupidly enough, my select query that populates the fields preceded my update query, causing the form to always show the values before the update. After reloading, of course the newly updated values would appear, causing me to look in the wrong direction.

This question however shows a nice overview of all the possible solutions when facing a caching problem.


I'm building an application on which there are forms, populated by values from a database. The user can change the input values of the form. After submitting (not via AJAX), the new values are saved to the database AND the same form is displayed again, this time containing the new values, loaded straight from the database. However: my browser (Chrome v27.0.1453.116m on Windows 7) caches the old values. The new values are only shown when I navigate to my page again.

<form id="edit_form" class="form" action="http://the.same.url/" method="post">
  <input type="text" name="example" value="<?php echo $value_from_database; ?>" />
</form>  

I have come across several solutions, none of which quite solve the issue:

  • Setting an attribute autocomplete="off" on the form tag: this does not seem to have effect.
  • Setting an attribute autocomplete="off" on the individual input tags: this also does not yield results, even in combination with the above solution
  • Resetting the form with JavaScript on page load: this gives some results, but apparently does not affect radio buttons and others.
  • Preventing caching of pages via meta-tags, as suggested here: Using <meta> tags to turn off caching in all browsers? Also, preventing caching via .htaccess or php headers does not have effect.
  • Trying to cache-bust by adding a random number to the action-url, as suggested by comment below by Miro Markarian

Here is an overview with proposed solutions: Make page to tell browser not to cache/preserve input values

What are my options? If possible, I would like to avoid posting my form asynchronously. It starts to look as if I have no other choice. Any input is appreciated.

Please note that this behavior also appears in other browsers, such as IE10.

My page title is the same as the value of one of the inputs in my form and also does not change upon submitting a new value, imho we can determine this to be a caching issue.

Google Chromes' Web Developer plugin shows me the following headers:

Pragma: no-cache
Date: Sun, 30 Jun 2013 09:44:12 GMT
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Apache
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection: Keep-Alive
Keep-Alive: timeout=15, max=100
Expires: Thu, 19 Nov 1981 08:52:00 GMT

200 OK
Community
  • 1
  • 1
chocolata
  • 3,258
  • 5
  • 31
  • 60
  • 1
    A possible solution can be returning to url with a random value appended to the end of the url... like `?nocache=875138` which can be achieved with the `rand()` function in php.. – Miro Markaravanes Jun 27 '13 at 17:41
  • Thanks, I will investigate it immediately. – chocolata Jun 27 '13 at 17:43
  • After investigating, it does not seem to have any effect. Thanks, though. Do you have any other ideas? – chocolata Jun 27 '13 at 17:48
  • 1
    Are you sure it is the browser and not the server that is caching the page? Does your application send a `not-modified` header? – Sumurai8 Jun 29 '13 at 20:10
  • 1
    This is very odd. My view would be if a form is at http://example.com/myform.php and you submit to http://example.com/myform.php?rnd=23215234 that there shoudl be no browser caching of the page. I think you have a misconfigured server in there somewhere. – Toby Allen Jun 30 '13 at 10:48
  • 1
    Add the following code to your php file: `` and inspect the page before and after submitting. If this comment changes, then it is -no- caching problem, but a problem with your code itself. – Sumurai8 Jun 30 '13 at 15:31
  • Thanks! There is a difference between the echoed date before and after submit. Very strange! My values are correctly being passed through post and correctly saved to the database. The problem only appears after POST. Reloading the page afterwards gets the correct values. Could this be browser functionality? – chocolata Jun 30 '13 at 18:29

5 Answers5

2

You could change the name attributes of the inputs by some random string and store them in a hidden input.

<form id="edit_form" class="form" action="http://the.same.url/" method="post">
  <input type="text" name="saejfb27982" value="..." />
  <input type="text" name="iuqde37we83" value="..." />
  <input type="hidden" name="associativeArray" value='{"example":"saejfb27982","example2":"iuqde37we83"}'>
</form>  

(Since the name is different each time, the browser won't be able to match it with any form of caching, autocompletion...)

Sami
  • 648
  • 8
  • 25
  • +1 I was about to write the same. A solution like this should be the way to go IMHO – Simone Jun 30 '13 at 12:07
  • Very good suggestion, thanks. Problem is that the form is fairly complex, with all different sorts of inputs and WYSIWYGs... At this moment I think it would almost be impossible to do this with all inputs. – chocolata Jun 30 '13 at 18:31
1

The first answer for this question suggests to add the following headers in order to disable browser caching:

<?php
header("Expires: Tue, 01 Jan 2000 00:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
?>
Community
  • 1
  • 1
seane
  • 589
  • 1
  • 4
  • 15
  • Strangely enough, this also does not solve the problem. At the same time, I tried your solution only with meta tags... Any other ideas? – chocolata Jun 27 '13 at 18:03
  • Please note that I can clearly see from the response headers that these settings are active. – chocolata Jun 29 '13 at 16:10
1

I have the feeling that your server sends 304: Not Modified instead of the data you would normally send. This question might help you if you are using apache.

I think something like this should do (but it is untested). It should delete the If-Modified-Since header for every request that asks for a php-file, forcing the application to send content instead of a Not-Modified status.

<ifModule mod_headers.c>
<FilesMatch \.php$>
RequestHeader unset If-Modified-Since
</FilesMatch>
</ifModule>
Community
  • 1
  • 1
Sumurai8
  • 20,333
  • 11
  • 66
  • 100
  • 1
    @maartenmachiels The 200 OK means that the server sends data to the browser. It sends every header possible to prevent caching, makes the data sent expire somewhere in the past to give the browser an extra reason to invalidate the cache if it is cached. Either there is a bug in the browser that makes it use the cache anyway, a browser extension is messing around or the server is sending the wrong data. The server could have some kind of cache, but it seems strange that it would send any cache if no `If-Modified-Since` header exists. I would be interested to see the relevant php code. – Sumurai8 Jun 30 '13 at 14:36
  • After rebuilding the scenario to put online here, I finally figured out the problem. It was a mear case of order of code execution... My SELECT (to populate the form fields) preceded my UPDATE, causing the form to always display old values. Upon reloading the page, of course the correct values where shown: causing me to believe this was a cache issue! Thanks for pointing me in the right direction! – chocolata Jun 30 '13 at 19:20
0

I believe you just forgot to echo $value_from_database, which, in turn, defaults back to the browser's cached value. You should have the following input element instead:

<input type="text" name="example" value="<?php echo $value_from_database; ?>">

While this should get the correct $value_from_database, I'm not entirely sure why you still weren't able to turn off caching altogether.

seane
  • 589
  • 1
  • 4
  • 15
  • Sorry, this was a mistake in my pseudocode. It also baffles me why my page cache is still loaded. I have been looking for conflicts in my .htaccess file, but haven't found any. Very strange indeed. Hopefully an answer will appear. – chocolata Jun 27 '13 at 18:27
0

Couldn't you take:

<form id="edit_form" class="form" action="http://the.same.url/" method="post">
 <input type="text" name="example" value="<?php echo $value_from_database; ?>" />
</form> 

and change it to:

value="<?php echo if(isset($_POST['example'])):$_POST['example']?$value_from_database; ?>

Which says: See if I have a variable already in the $_POST array after the form was submitted. If I do, use that value, if not, pull from db.

You may need to set session variables ($_SESSION['ex'] = $_POST['example']), and do the tweaks to the code above

Ryan B
  • 3,364
  • 21
  • 35
  • Hi, thanks for your answer. Could you elaborate on your remark concerning ´$_SESSION['ex']´? – chocolata Jun 27 '13 at 18:41
  • Sometimes the `$_POST` array gets mucked up, so taking the POST data, and putting it into a SESSION variable shields it some. – Ryan B Jun 27 '13 at 18:45
  • My page title, that's also pulled from the database (username), also does not change upon changing the value in the respective input. Therefore I tend to think it's a caching issue. – chocolata Jun 27 '13 at 18:49
  • Submit happens via Jquery .submit() Upon submit, the same page is loaded. All pages of my application reside within index.php. There's URL rewriting via .htaccess. – chocolata Jun 27 '13 at 18:55
  • This changes the question completely. It seems like it is an jQuery not PHP. You aren't passing the values correctly via JS – Ryan B Jun 27 '13 at 18:59
  • The values aren't being passed via JS. It's a regular http form post, only the submit is triggered via jQuery. The page refreshes upon submit. Any views on this? – chocolata Jun 27 '13 at 22:28
  • I've just experimented with manual form submit: no change, it seems. – chocolata Jun 27 '13 at 22:44