Pergunta

Eu tenho um x.php página web (em uma área protegida por senha do meu web site), que tem uma forma e um botão que utiliza o método POST para enviar os dados do formulário e abre x.php#abc. Isso funciona muito bem.

No entanto, se os usuários decide voltar navegar no Internet Explorer 7, todos os campos no x.php originais são eliminadas e tudo deve ser digitado em novamente. Eu não posso salvar as informações postadas em uma sessão e eu estou tentando compreender como posso obter IE7 para se comportar da maneira que eu quero.

Eu procurei na web e encontrei respostas que sugerem que o cabeçalho HTTP deve conter informações caching explícito. Atualmente, eu tentei isso:

session_name("FOO");
session_start();
header("Pragma: public");
header("Expires: Fri, 7 Nov 2008 23:00:00 GMT");
header("Cache-Control: public, max-age=3600, must-revalidate");
header("Last-Modified: Thu, 30 Oct 2008 17:00:00 GMT");

e suas variações. Sem sucesso. Olhando para os cabeçalhos retornados com uma ferramenta como WireShark me mostra que o Apache é realmente honrar meus cabeçalhos.

Então, minha pergunta é: o que estou fazendo de errado

Foi útil?

Solução

IE irá reter conteúdo do formulário em um botão de volta clique automaticamente, desde que:

  • você não tenha quebrado cacheing com um pragma no-cache ou similar
  • os campos do formulário em questão não foram criadas dinamicamente pelo script

Você parece ter o cacheing na mão, então eu estou supondo que estes últimos podem ser aplicadas. (Como mkoeller diz, Firefox evita este problema se a página estiver nos últimos cliques de volta, mantendo a própria página vivo por mais do que está na tela. No entanto, este é opcional, e Firefox irá reverter para o mesmo comportamento que o IE e outros navegadores Depois de ter navegado algumas páginas adiante e que expirou o antigo.)

Se você estiver criando seus próprios campos do formulário de onload roteiro, em seguida, o navegador tem nenhuma maneira de saber que o novo controle de entrada é 'o mesmo' como o velho exemplo, por isso não pode preenchê-lo com o anteriormente valor -submitted. Neste caso, se você quer jogar bem com o botão de volta você tem que começar a armazenar dados no cliente.

Em seguida, você tem que usar algum tipo de modo que cada conjunto de dados está vinculado a exatamente uma instância da página, caso contrário, passando por várias instâncias do mesmo formulário ou ter dois navegadores abas abertas no formulário ao mesmo tempo digitando estado irá confundir gravemente o seu script.

e então você está começando a coletar uma grande quantidade de dados se eles são grandes formas, e se o mecanismo de armazenamento do lado do cliente que você está usando é cookies que você pode começar a perder dados, como bem como o envio de uma carga do absurdo estado desnecessário com cada solicitação HTTP. Outros mecanismos de armazenamento do lado do cliente estão disponíveis, mas eles específica navegador está.

Em suma: fazer formas geradas dinamicamente bem é uma dor enorme e provavelmente o melhor é evitado se você puder. Tendo forma escondida na página que um script torna visível, permitindo assim que os navegadores para fazer o seu-lembrando campo-magic em vez de dar-lhe a tarefa, é tipicamente muito mais fácil.

Outras dicas

Ao tentar restringir ainda mais o problema, eu encontrei a causa do meu problema. Eu estava a utilizar URLs que estavam a ser reescritas por Apache (isto é, I sempre acedida meu principal como http://foo.com/page qual é mapeado por Apache para http://foo.com/page.htm). Usando o real URLs resolveu o problema e fez IE7 feliz, enquanto eu especificar o bom cabeçalho HTTP (Cache-Control, Expires, etc.).

Aqui está o que eu faço no código PHP para cabeçalhos de saída que parecem fazer todos os navegadores feliz com o cache:

function emitConditionalGet($timestamp)
{
    // See also http://www.mnot.net/cache_docs/
    // and code sample http://simonwillison.net/2003/Apr/23/conditionalGet/

    $gmdate_exp    = gmdate('D, d M Y H:i:s', time() + 1) . ' GMT';
    $last_modified = gmdate('D, d M Y H:i:s', $timestamp) . ' GMT';
    $etag          = '"'.md5($last_modified).'"';

    // If the client provided any of the if-modified-since or if-none-match
    // infos, take them into account:

    $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
                       ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false;
    $if_none_match     = isset($_SERVER['HTTP_IF_NONE_MATCH'])
                       ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])     : false;

    if (!$if_modified_since && !$if_none_match)
    {
        return;  // the client does not cache anything
    }

    if ($if_none_match && $if_none_match != $etag)
    {
        return;  // ETag mismatch: the page changed!
    }
    if ($if_modified_since && $if_modified_since != $last_modified)
    {
        return;  // if-modified-since mismatch: the page changed!
    }

    // Nothing changed since last time client visited this page.

    header("HTTP/1.0 304 Not Modified");
    header("Last-Modified: $last_modified");
    header("ETag: $etag");
    header("Cache-Control: private, max-age=1, must-revalidate");
    header("Expires: $gmdate_exp");
    header("Pragma: private, cache");
    header("Content-Type: text/html; charset=utf-8");
    exit;
}

function emitDefaultHeaders($timestamp)
{
    $gmdate_exp    = gmdate('D, d M Y H:i:s', time() + 1) . ' GMT';
    $last_modified = gmdate('D, d M Y H:i:s', $timestamp) . ' GMT';
    $etag          = '"'.md5($last_modified).'"';

    header("Last-Modified: $last_modified");
    header("ETag: $etag");
    header("Cache-Control: private, max-age=1, must-revalidate");
    header("Expires: $gmdate_exp");
    header("Pragma: private, cache");
    header("Content-Type: text/html; charset=utf-8");
}

function getTimestamp()
{
    // Find out when this page's contents last changed; in a static system,
    // this would be the file time of the backing HTML/PHP page. Add your
    // own logic here:
    return filemtime($SCRIPT_FILENAME);
}

// ...

$timestamp = getTimestamp();
emitConditionalGet($timestamp);
emitDefaultHeaders($timestamp); //previously, this variable was mistyped as "$timestaml"

O Firefox faz este tipo de cache. Como eu compreendo a sua pergunta, você quer IE7 se comportar da maneira como o Firefox faz. Eu acho que isso não é possível.

O Firefox e IE7 diferem na maneira de interpretar o botão de volta.

O Firefox irá exibir a árvore DOM da página anterior, uma vez que a última exibida antes que a página foi deixado. Ou seja, todos os dados do formulário ainda será contida no campo de entrada do formulário. Mas você não vai ver um evento onload após apertar o botão de volta.

IE7 irá processar a página novamente com base na resposta que recebe do servidor. Assim, a forma é emtpy (a menos que houvesse valores padrão enviados pelo servidor originalmente), mas você verá um evento onload.

Eu picado em torno e isso é um problema difícil. Seu também um grande pé no saco para dinamicamente modificada conteúdo. Você visitar a página, aumenta javascript-lo com sua instrução, você vai para a próxima página e voltar, e javascript esqueceu. E não há nenhuma maneira de simplesmente atualizar do lado do servidor da página, porque a página sai de cache.

Então, eu criei um back-botão-cache-breaker.

Seu mal e mal-for-the-web, mas a torna capaz de páginas para se comportar como as pessoas esperam que eles se comportam em vez de entortar magicamente por todo o lugar.

<script type="text/javascript">//<!-- <![CDATA[
(function(){
    if( document.location.hash === "" )
    {
        document.location.hash="_";
    }
    else
    {
      var l = document.location;
      var myurl = ( l.protocol + "//" + l.hostname + l.pathname + l.search); 
      document.location = myurl;
    }
})();
//]]> --></script>

Isto irá fazer um pouco de magia em que ele detecta se ou não a página que você está / atualmente / visualização foi carregado a partir do cache ou não.

Se você está lá pela primeira vez, ele irá detectar "não de hash", e acrescentar "#_" para o URL da página. se você está lá para o> 1º tempo (isto é: não um link direto para a página), a página já tem o #_ sobre ele, assim que remove-lo e, no processo de removê-lo, desencadeia um recarregamento da página.

Você pode usar autocomplete = "off" em seus campos. Desta forma, os valores não serão armazenados em cache pelo navegador para que os valores não serão preenchidos no formulário quando o usuário clica no botão de volta.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top