Reputation: 319
Ok, so I'm currently building a blog at the moment, and on my add post page (the dashboard) I'm flashing a message with Javascript sweetalert and that works fine, but I'm including a link inside that to view the post you just wrote. When you click on it, and press the back button, the flash message shows again. And again. And again forever.
Here's my add post action in the controller:
public function createBlogPost(Post $post, Request $request)
{
$post = new Post;
$post->title = $request->title;
$post->slug = str_slug($post->title, '-');
$post->thumbnail = $request->thumbnail;
$post->content = $request->content;
$post->save();
$mostrecent = DB::table('posts')->orderBy('created_at', 'desc')->first();
$mslug = $mostrecent->slug;
$request->session()->put('mslug', $mslug);
Session::flash('post_success', 'post success');
return redirect('admin/dashboard');
// I have tried Session::forget('post_success');
// Session::pull('post_success');
// Session::flush();
}
I really don't know what the problem is, but I'm fairly sure it must be to do with the redirect, as I can forget the key before redirecting and the message won't be flashed.
Any help would be greatly appreciated
( Ignore the bad PHP, I'm still pretty new to this stuff :P )
EDIT: I'm including flash.blade.php down the bottom of my master file:
@include('templates.flash')
And here is the flash file:
@if (Session::has('post_success'))
<script>
swal({
title: 'Post created!',
html:
'<p>Check it out ' +
'<a href="/blog/{{ Session::get('mslug') }}">here</a>.',
type: 'success'
})
</script>
@endif
EDIT 2: My routes
Route::get('admin/dashboard', [
'as' => 'dashboard',
'uses' => 'AdminController@dashboard'
]);
Route::post('admin/dashboard', [
'as' => 'createblogpost',
'uses' => 'AdminController@createBlogPost'
]);
Upvotes: 4
Views: 3576
Reputation: 3227
Firstly to explain your problem, you should really look here, but the basic gist of your issue has nothing to do with Laravel.
When you press the back button in a browser, the browser itself tries its best to bring you back to the page you were at, and it tries to help you out by caching some data which will allow you to return to exactly where you left off, often this means if you were filling out a form, the form will still be filled out for you when you press the back button.
Thus, in your case it's true that using Laravel's Session::flash
will only persist the message for one request, but that doesn't necessarily mean that your browser won't be caching the data itself. So it is your browser that is flashing back to you the success message when you hit the back button.
Not the most elegant from a user stand point, but probably easiest for you to implement: you could include a link like 'back to dashboard' or something like that, for the user to click which will have him sent back to the dashboard in a way that the page will get reloaded from scratch, instead of using the back button.
You could change your approach and use Ajax to load your flash messages instead of Sessions. This way when you hit the back button the page will be reloaded, but the Ajax will not have been called and you won't see the flash message. This will allow for using the back button, but will force you to do a bit more work in your code.
Another option in this case, though it will require a bit of research and testing, and should be used only if you are sure it won't have negative side effects, would be to actually tell your browser to stop caching data.
There are a few ways to do this third option:
If you include the following:
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: private, no-store, max-age=0, no-cache, must-revalidate, post-check=0, pre-check=0");
header("Pragma: no-cache");
in your controller, or perhaps as a new Middleware ClearBrowserCache
or something like that, then you can accomplish this through PHP which is ideal because it can integrate nicely with Laravel and you won't have to worry about users not having javascript enabled. The only issue is that it while it worked in Chrome, it wasn't working for me just now on Safari 9.
A similar alternative would be to use Javascript to accomplish the same goal, by adding this script to your page:
window.onpageshow = function(evt) {
if (evt.persisted) {
document.body.style.display = "none";
location.reload();
}
};
This script does work with Safari, but it didn't work for Chrome.
So it really will be up to you to do a bit more research if you choose this last option to see what works and test it in whichever browsers you think you need to support, and find a solution, or a combination of solutions for different browsers.
Upvotes: 2