ブラウザの戻るボタンで空のフィールドが復元されます
-
06-07-2019 - |
質問
フォームと POST
メソッドを使用して送信するボタンがあるWebページ x.php
を(Webサイトのパスワードで保護された領域に)持っていますフォームデータを開き、 x.php#abc
を開きます。これはかなりうまくいきます。
ただし、ユーザーがInternet Explorer 7に戻ることにした場合、元の x.php
のすべてのフィールドがクリアされ、すべてを再度入力する必要があります。投稿された情報をセッションに保存することはできません。IE7を希望どおりに動作させる方法を理解しようとしています。
Webを検索しましたが、HTTPヘッダーに明示的なキャッシュ情報が含まれていることを示唆する回答が見つかりました。現在、私はこれを試しました:
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");
およびそのバリエーション。成功なし。 WireShark などのツールで返されたヘッダーを見ると、Apacheが実際にヘッダーを尊重していることがわかります。
だから私の質問は:何が間違っているのですか?
解決
IE は、戻るボタンをクリックしてもフォームの内容を自動的に保持します:
- no-cacheプラグマなどでキャッシュを破損していない
- 問題のフォームフィールドは、スクリプトによって動的に作成されたものではありません
キャッシュが手元にあるように見えるので、後者が当てはまると思います。 (mkoellerが言うように、Firefoxはページが最後の数回のバッククリックにある場合、ページ自体を画面上より長く維持することでこの問題を回避します。しかしこれはオプションであり、FirefoxはIEや他の数ページ先のページを閲覧し、古いページが期限切れになったら、ブラウザを使用してください。)
スクリプトonloadから独自のフォームフィールドを作成している場合、ブラウザは新しい入力コントロールが‘同じ’であることを知る方法がありません。古いインスタンスなので、以前に送信された値を入力することはできません。この場合、[戻る]ボタンでうまく再生したい場合は、クライアントにデータの保存を開始する必要があります。
次に、データの各セットがページの1つのインスタンスにのみ結び付けられるように、何らかの種類の状態キーを使用する必要があります。スクリプトを大きく混乱させます。
そして then 大きなフォームの場合、大量のデータを収集し始めており、使用しているクライアント側のストレージメカニズムがCookieである場合、データを失い始める可能性があります。また、HTTPリクエストごとに不必要な状態の無意味な負荷を送信します。他のクライアント側のストレージメカニズムも使用できますが、ブラウザ固有です。
要するに、動的に生成されたフォームをうまく実行することは大きな苦痛であり、可能であればおそらく避けるのが最善です。スクリプトが表示するページに非表示のフォームを配置することにより、ブラウザーがタスクを提供する代わりにフィールドを思い出すマジックを実行できるようにすることは、通常はるかに簡単です。
他のヒント
問題をさらに絞り込もうとすると、問題の原因が見つかりました。 Apacheによって書き換えられたURLを使用していました(つまり、Apacheによって http://foo.comにマップされる
)。適切なHTTPヘッダー( http://foo.com/page
として常にページにアクセスしていました) /page.htm Cache-Control
、 Expires
などを指定する限り、 real URLを使用して問題を解決し、IE7を満足させました。 。)。
すべてのブラウザがキャッシュに満足しているように見えるヘッダーを出力するために、PHPコードで次のようにします:
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(問題をさらに絞り込もうとすると、問題の原因が見つかりました。 Apacheによって書き換えられたURLを使用していました(つまり、Apacheによって http://foo.comにマップされる http://foo.com/page
として常にページにアクセスしていました) /page.htm
)。適切なHTTPヘッダー( Cache-Control
、 Expires
などを指定する限り、 real URLを使用して問題を解決し、IE7を満足させました。 。)。
すべてのブラウザがキャッシュに満足しているように見えるヘッダーを出力するために、PHPコードで次のようにします:
<*>SERVER['HTTP_IF_MODIFIED_SINCE'])
? stripslashes(問題をさらに絞り込もうとすると、問題の原因が見つかりました。 Apacheによって書き換えられたURLを使用していました(つまり、Apacheによって http://foo.comにマップされる http://foo.com/page
として常にページにアクセスしていました) /page.htm
)。適切なHTTPヘッダー( Cache-Control
、 Expires
などを指定する限り、 real URLを使用して問題を解決し、IE7を満足させました。 。)。
すべてのブラウザがキャッシュに満足しているように見えるヘッダーを出力するために、PHPコードで次のようにします:
<*>SERVER['HTTP_IF_MODIFIED_SINCE']) : false;
$if_none_match = isset(問題をさらに絞り込もうとすると、問題の原因が見つかりました。 Apacheによって書き換えられたURLを使用していました(つまり、Apacheによって http://foo.comにマップされる http://foo.com/page
として常にページにアクセスしていました) /page.htm
)。適切なHTTPヘッダー( Cache-Control
、 Expires
などを指定する限り、 real URLを使用して問題を解決し、IE7を満足させました。 。)。
すべてのブラウザがキャッシュに満足しているように見えるヘッダーを出力するために、PHPコードで次のようにします:
<*>SERVER['HTTP_IF_NONE_MATCH'])
? stripslashes(問題をさらに絞り込もうとすると、問題の原因が見つかりました。 Apacheによって書き換えられたURLを使用していました(つまり、Apacheによって http://foo.comにマップされる http://foo.com/page
として常にページにアクセスしていました) /page.htm
)。適切なHTTPヘッダー( Cache-Control
、 Expires
などを指定する限り、 real URLを使用して問題を解決し、IE7を満足させました。 。)。
すべてのブラウザがキャッシュに満足しているように見えるヘッダーを出力するために、PHPコードで次のようにします:
<*>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"
Firefoxはこの種のキャッシングを行います。あなたの質問を理解しているように、あなたはIE7がFirefoxと同じように振る舞うことを望んでいます。それは不可能だと思います。
FirefoxとIE7は、戻るボタンの解釈方法が異なります。
Firefoxは、ページが終了する前に最後に表示されていたように、前のページのDOMツリーを表示します。つまり、すべてのフォームデータがフォームの入力フィールドに含まれます。ただし、戻るボタンを押しても onload
イベントは表示されません。
IE7は、サーバーから受信した応答に基づいてページを再度レンダリングします。したがって、フォームは空です(元々サーバーから送信されたデフォルト値がない限り)が、 onload
イベントが表示されます。
私はいろいろと調べましたが、これは非常に難しい問題です。それはまた、動的に変更されたコンテンツのお尻の大きな痛みです。このページにアクセスすると、javascriptが命令でそれを補強し、次のページに移動して戻ってきますが、javascriptは忘れています。また、ページがキャッシュから出てくるため、ページをサーバー側で単純に更新する方法はありません。
それで、back-button-cache-breakerを考案しました。
これは邪悪でWebに悪いですが、ページ全体が魔法のようにゆがむのではなく、人々が期待する振る舞いをすることができます。
<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>
これは、/現在/表示しているページがキャッシュからロードされたかどうかを検出するという点で、ちょっとした魔法を行います。
初めてアクセスすると、「ハッシュなし」が検出されます。 、および&quot; #_
&quot;を追加します。ページのURLへ。
&gt;初めてアクセスした場合(つまり、ページへの直接リンクではない場合)、ページには既に#_が表示されているため、削除され、削除中にページのリロードがトリガーされます。
autocomplete =&quot; off&quot;を使用できます。あなたの分野で。 この方法では、値がブラウザによってキャッシュされないため、ユーザーが戻るボタンをクリックしたときに値がフォームに入力されません。