22

I will try my best to explain this.

I have an application that show the 50+ projects in my view page. The user can click the individual project and go to the update page to update the project information. Everything works fine except that after user finish updating the individual project information and hit 'back' button on the browser to the previous view page. The old project information (before update) is still there. The user has to hit refresh to see the updated information. It not that bad, but I wish to provide better user experience. Any idea to fix this? Thanks a lot.

FlyingCat
  • 14,036
  • 36
  • 119
  • 198

13 Answers13

21

I use these four lines of PHP code:

// any valid date in the past
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
// always modified right now
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
// HTTP/1.1
header("Cache-Control: private, no-store, max-age=0, no-cache, must-revalidate, post-check=0, pre-check=0");
// HTTP/1.0
header("Pragma: no-cache");

The key is using the "no-store" clause of the Cache-Control header.

tobias_k
  • 81,265
  • 12
  • 120
  • 179
phper
  • 355
  • 2
  • 8
  • 1
    This worked for me. I think using the browser (via PHP) is the safest option, especially if JavaScript is turned off. – Ben Sinclair Nov 19 '14 at 01:39
  • this didn't work for me with Safari 9, but it did work with Chrome – tam5 Mar 06 '16 at 22:55
  • 2
    Note: `if both post-check and pre-check are specified and set to 0, both are entirely ignored.` As well as: `If you want to prevent caching, do not include the post-check and pre-check directives. Doing so is completely unnecessary and results in wasted bandwidth and HTTP header processing cycles.` Source: https://blogs.msdn.microsoft.com/ieinternals/2009/07/20/internet-explorers-cache-control-extensions/ – Jan Żankowski Jan 23 '19 at 12:05
17

The "fb-cache" can be really annoying. Here is a simple javascript way around it:

window.onpageshow = function(evt) {
    // If persisted then it is in the page cache, force a reload of the page.
    if (evt.persisted) {
        document.body.style.display = "none";
        location.reload();
    }
};

Tested in Safari 6 and IE10.

abriggs
  • 744
  • 7
  • 16
  • Actually this works, but in iOs it works only once, if you try to click forward forward back back, you'll notice that event fired only once. – Rantiev Sep 03 '14 at 13:35
  • @Rantiev is this for Safari on iOS? – abriggs Sep 03 '14 at 15:04
  • Sorry guys - this was tested in the summer of 2013 on Safari 6 and IE10. If you are having issues with this solution and find alternative solutions or tweaks to this solution - help others out by providing them. I'm also more than happy to update the answer with any of your findings. Thanks. – abriggs Jan 11 '16 at 20:52
6

I think you must work with JS to make this work, since there is no way for PHP to know what browser controlls the user has access to...

Maybe this will help: http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript

Loupax
  • 4,728
  • 6
  • 41
  • 68
4

Fortunately, we don't have to support browsers below IE10, so if you're willing or privileged enough to support only browsers that are HTML5 capable, the following should work:

/*
 * The following is intentional, to force Firefox to run 
 * this JS snippet after a history invoked back/forward navigation.
 */
window.onunload = function(){};    

function formatTime(t) {
    return t.getHours() + ':' + t.getMinutes() + ':' + t.getSeconds();
}

if (window.history.state != null && window.history.state.hasOwnProperty('historic')) {
    if (window.history.state.historic == true) {
        document.body.style.display = 'none';
        console.log('I was here before at ' + formatTime(window.history.state.last_visit));
        window.history.replaceState({historic: false}, '');
        window.location.reload();
    } else {
        console.log('I was forced to reload, but WELCOME BACK!');
        window.history.replaceState({
            historic  : true,
            last_visit: new Date()
        }, '');
    }
} else {
    console.log('This is my first visit to ' + window.location.pathname);
    window.history.replaceState({
        historic  : true,
        last_visit: new Date()
    }, '');
}

Well, here's the code without comments and flab:

window.onunload = function(){};

if (window.history.state != null && window.history.state.hasOwnProperty('historic')) {
    if (window.history.state.historic == true) {
        document.body.style.display = 'none';
        window.history.replaceState({historic: false}, '');
        window.location.reload();
    } else {
        window.history.replaceState({historic  : true}, '');
    }
} else {
    window.history.replaceState({historic  : true}, '');
}

Stick that just before your closing body tag, and you'll have a fairly clean solution.

This will work with any combination of back/forward being clicked, and the moment the user lands on a new page, no forced reloading will occur.

Read more about the History object on MDN:

MDN - The History Object

MDN - Manupulating the Browser History

josef.van.niekerk
  • 11,941
  • 20
  • 97
  • 157
3
 if (window.name == "reloader") {
            window.name = "";
            location.reload();
        }

window.onbeforeunload = function() {
                window.name = "reloader"; 
            }

Add this two functions in every pages

Rohit
  • 31
  • 1
2

None of the above solutions worked for me. This simple solution posted here worked ...

I've tried to force a page to be downloaded again by browser when user clicks back button, but nothing worked. I appears that modern browsers have separate cache for pages, which stores complete state of a page (including JavaScript generated DOM elements), so when users presses back button, previous page is shown instantly in state the user has left it. If you want to force browser to reload page on back button, add onunload="" to your (X)HTML body element:

<body onunload="">

This disables special cache and forces page reload when user presses back button. Think twice before you use it. Fact of needing such solution is a hint your site navigation concept is flawed.

jahackbeth
  • 529
  • 8
  • 17
2

after days of searching on the net to find a solution, i finally figure it out, add after:

<script>
 window.onbeforeunload = function(){window.location.reload();}
</script>

this will work like a charm you will thank me

this code will reload the page whenever you visit it.

Adam
  • 873
  • 7
  • 33
mhd
  • 21
  • 1
  • This is exactly what I needed, thanks! I tried many other solutions that were supposed to detect visiting the page via the "back" button, but none of them worked. I think the problem with the other approaches I tried may have been related to the "bfcache", since apparently setting `window.onbeforeunload` implicitly invalidates the "bfcache". – ntc2 Aug 23 '21 at 12:40
1

This is the solution I have used:

<?php
session_start();
if (!$_SESSION['reloaded']) {$_SESSION['reloaded'] = time();}
else if ($_SESSION['reloaded'] && $_SESSION['reloaded'] == time()) { ?> 
<script> 
location.reload(); 
</script> 
<?php } ?>
1

Well, you could either provide a built-in back button on the update page that will send them to it new (like a link <a href="<?= $_SERVER['HTTP_REFERRER']; ?>">BACK</a> or put some script on the page that will force it to pull data every time the page is hit, whether it's a new impression, or if the back button was used.

James
  • 3,765
  • 4
  • 48
  • 79
  • I have a 'back to main' button on my update page, but I can't be sure that the user won't hit the back button in the browser. Also, I have several project types in my view page. I can't simply add script to force page to refresh data from the database because it's hard to know what type of projects the user picked last time. +1 though. Thanks. – FlyingCat Jan 30 '12 at 23:30
1

here's a solution that ive used in some of my pages. add this to pages that changes are made at.

window.onbeforeunload = function() {
     window.name = "reloader"; 
        }

this triggers when you leave those pages. you can also trigger it if there were changes made. so that it wont unnecessarily reload the page that needs reloading. then on pages that you want to get reloaded on after a the browser "back" use.

if (window.name == "reloader")
      {
        window.name = "no";
        reloadPage(); 
      }

this will trigger a reload on the page you need reloading to... hope this helps :) oh btw this is in js.

gekong
  • 125
  • 7
0

make a hidden checkbox and use below code(coffeescript)

window.location.reload()  if $("#refreshCheck")[0].checked
  $("#refreshCheck")[0].checked = true
Caner
  • 1,448
  • 23
  • 38
-1

I use a jquery and a php script to force reload on backbutton. The window.unload part is only needed in firefox. The outcommented timeout 1 second and body append part is only for illustration of functionality. window.location.reload(true) will give the same result as window.location.href = window.location.href;

jquery:

<script>
    $(window).unload(function() {});


        $.get('h.php',function(data){
            if($.trim(data)=='first'){
               // $('body').append(data)
               // setTimeout(function(){
               window.location.href = window.location.href;
               // },1000)
            }
            else {
                // $('body').append(data)
            }
        });

</script>

h.php:

<?php session_start(); ?>
<?php 
if(!$_SESSION['reloaded']){
    echo 'first';   

    $_SESSION['reloaded']=1;
}
else {
    echo 'second';
    unset($_SESSION['reloaded']);   
}
?>
Jens
  • 1
  • 1
-4

You can send HTTP headers on your view page which tell the browser that the page cannot be cached. This means that the browser will need to request the page from the server every single time it is accessed - meaning it always show up to date information.

Headers need to be sent before any other content, so put the following right at the top of your view page.

header("Cache-Control: no-cache, must-revalidate");
cb1
  • 930
  • 7
  • 16
  • Thanks cb1. I tried but it still showed the information before updated. This is what I put on the top of the view page. ...+1 though – FlyingCat Jan 30 '12 at 23:22
  • That's a strange one @Jerry - it's worked every time for me before. Also, it wouldn't hurt to put in `header("Pragma: no-cache");` underneath the Cache-Control header - and yeah, that's right to put it at the top of the view page. I take it you cleared your browser's cache before re-testing? – cb1 Jan 30 '12 at 23:36
  • I did clear the cache and try firefox and chrome. I added your second code as well and still not working. Thanks though. :( – FlyingCat Jan 31 '12 at 00:11
  • I have the exact problem as Jerry – Strawberry Mar 22 '12 at 10:14
  • 2
    This doesn't work for the back button - only for other navigation actions to that page. – nfm Aug 07 '12 at 02:50