やりたいこと
flashメソッドやwithメソッドを使ってフラッシュメッセージを表示させる際、
「当該ページでフラッシュメッセージを表示」→「他のページに移動」→「ブラウザの戻るボタンで元のページに戻る」
上記を行うと同じフラッシュメッセージが再表示されてしまう。これを防ぎたい。
実装方法
以下コードのように、phpで作成したユニーク値をJavaScriptを使用してブラウザのストレージに保存し「一度目の表示かどうか」を判定する。具体的なコードの説明は本記事の最下部に載せています。
<div id="FlashMessage">
<p class="FlashMessage_Text">
{{session('message')}}
</p>
</div>
<script>
if( "{{session('message')}}" ){
const messageIdValue = "{{ uniqid() }}";
if (sessionStorage) {
if (sessionStorage.getItem('messageId') === messageIdValue) {
document.getElementById('FlashMessage').style.display = "none";
}else{
sessionStorage.setItem('messageId', messageIdValue);
}
}
}
</script>
そもそもフラッシュメッセージの仕組みは?
サーバのSessionデータにメッセージを保存し、それを呼び出している。
通常であればSessionデータに保存した値は特定の条件が満たされるまで保持される。
しかし、flashメソッドやwithメソッドを使用した場合は、Sessionに値を保存した後、1回目のリクエスト(ページ遷移)が終了するとその値が削除される。
なので、特定の操作(記事投稿やログインなど)のあとに1度だけフラッシュメッセージを表示することができる。
Sessionってなんだっけ?という場合は下記の記事様がわかりやく解説してくださってます。
なぜブラウザの戻るボタンだと再表示される?
ブラウザのキャッシュでページを表示しているから。
通常、ブラウザの戻るボタンは、元のページ宛に改めてリクエストを送っているわけではなく、ブラウザのキャッシュによりページを表示している。つまりサーバとは通信していない。なのでSessionデータに保存したメッセージがサーバ側で消えていても関係ない。
コードの説明
<div id="FlashMessage">
<p class="FlashMessage_Text">
{{session('message')}}
</p>
</div>
<script>
//Sessionデータにメッセージが有るかどうかを確認
if( "{{session('message')}}" ){
//phpのuniqid関数でユニーク値をセット
const messageIdValue = "{{ uniqid() }}";
//主要ブラウザはsessionStorageに対応しているが、念のため確認
if (sessionStorage) {
//messageIdの値が同じだったら、フラッシュメッセージをdisplay:none;する
if (sessionStorage.getItem('messageId') === messageIdValue) {
document.getElementById('FlashMessage').style.display = "none";
}else{
//messageIdがない場合は新しくセット。
//messageIdは有るが値が違う場合は上書き。
sessionStorage.setItem('messageId', messageIdValue);
}
}
}
</script>
ユニーク値はphpで作っているので、ブラウザの戻るボタンを押して同じページに戻った場合、messageIdValueの値は1度目の表示時と同じになります(前述の通りキャッシュでページを表示しているため)。
なので、このmessageIdValueをsessionStorageに保存→照合することにより1度目の表示なのかどうかが判定できます(ちなみにsessionStorageはブラウザのストレージなのでサーバ側のSessionデータとは異なるものです)。