Flash data lasts for this request and the next, which is what a Post/Redirect/Get message needs (Redirects and Flash Data). with() flashes a value, and withInput() flashes the input for old():
Route::get('/wish', fn () => redirect('/wishlist')
->with('status', 'Saved to your wishlist.')->withInput());
Route::get('/wishlist', fn () => [
'status' => session('status'), 'note' => old('note')]);curl -si -b jar -c jar "$B/wish?note=gift+wrap" | grep ^Location
sudo mysql -N shop -e 'SELECT payload FROM sessions' | base64 -d | jq -c '{_flash, _old_input}'
curl -s -b jar -c jar $B/wishlist; echo
curl -s -b jar -c jar $B/wishlist; echoOutput
Location: http://127.0.0.1:8316/wishlist
{"_flash":{"old":["status","_old_input"],"new":[]},"_old_input":{"note":"gift wrap"}}
{"status":"Saved to your wishlist.","note":"gift wrap"}
{"status":null,"note":null}Flashing lists a key in _flash.new. Every save deletes the keys in _flash.old and moves new to old, so the stored row already says old, and the next save deletes them. now() flashes for the current request only; reflash() and keep(['status']) carry messages across an extra redirect. A failed validate() flashes input and errors itself (Displaying Errors), but never password, password_confirmation or current_password.