skip to content

In Laravel, how long does session flash data live, and what do reflash(), keep() and now() change about it?

level: middleimportance: must knowfreq 52%

answer

  1. _flash.new and _flash.old lists
  2. aged when the session is saved
  3. this request plus the next one
  4. reflash() keeps all for one more
  5. now() lives for this request only

basics

~20 s

flash() data is readable for the rest of the current request and during the next one, then deleted. reflash() extends all of it by one request, keep() does so for named keys, and now() stores a value for this request only.

solid answer

~40 s

`flash($key, $value)` puts the value and lists the key in `_flash.new`. When the session is saved at the end of the request, `ageFlashData()` deletes the keys listed in `_flash.old`, moves `_flash.new` into `_flash.old`, and empties `_flash.new`. So a value flashed in request A survives A and the next request B, and is removed when B's session is saved. `reflash()` moves every old key back into the new list, extending all of them by one request; `keep(['status'])` does that for the named keys only. `now($key, $value)` puts the value and lists it straight in `_flash.old`, so it is removed at the end of the current request. Any request with the session counts, including AJAX calls and intermediate redirects.

code

php · 25 lines
php
<?php

use Illuminate\Http\Request;

public function saveVehicle(Request $request)
{
    // ... persist the vehicle step
    $request->session()->flash('status', 'Vehicle details saved');

    return redirect('/quote/next');          // this hop is "the next request"
}

public function next(Request $request)
{
    $request->session()->keep(['status']);   // survive one more request

    return redirect('/quote/drivers');
}

public function reprice(Request $request)
{
    $request->session()->now('status', 'Premium recalculated'); // this response only

    return view('quote.summary');
}

go deeper

for a junior

Remember that flashed data is there for the next request only, and that reflash(), keep() and now() adjust that lifetime.

for a middle

Explain the _flash.new and _flash.old lists, how ageFlashData() runs on save, and which modifier fits an intermediate redirect versus a direct render.

for a senior

Diagnose vanished or doubled messages from redirect chains and background requests, and keep polling endpoints from consuming flash data.

for a principal

Decide how status feedback travels in the product, server flash, client state or both, so multi-request flows stay predictable.

## Flash data in one sentence **Flash data** is session data that removes itself: a value stored for "the next request", typically a status message shown after a redirect. Laravel implements it with two bookkeeping lists inside the session itself, and knowing them explains every timing question an interviewer can ask. ## The mechanism The store keeps two arrays of key names: **`_flash.new`** and **`_flash.old`**. 1. `flash('status', 'Vehicle details saved')` calls `put('status', ...)`, pushes `status` onto `_flash.new`, and removes it from `_flash.old` if it was there. 2. At the end of the request, `save()` calls **`ageFlashData()`**, which: - forgets every key listed in `_flash.old`; - copies `_flash.new` into `_flash.old`; - resets `_flash.new` to an empty list. 3. On the next request, `status` is readable because it is merely listed in `_flash.old`. 4. At the end of that request, `ageFlashData()` forgets it. So flashed data is available **immediately**, for the rest of the current request, and **during the subsequent request**, then it is gone. ## The three modifiers | Method | Effect on the lists | Resulting lifetime | |---|---|---| | `reflash()` | merges all of `_flash.old` into `_flash.new`, empties `_flash.old` | every current flash value survives one more request | | `keep(['status'])` | adds the named keys to `_flash.new`, removes them from `_flash.old` | only those keys survive one more request | | `now('status', $value)` | puts the value and lists it in `_flash.old` | removed at the end of this request | `flashInput()`, used for old input, is simply `flash('_old_input', $input)`, so old form values follow exactly the same timing. ## The quote wizard in practice The wizard's vehicle step posts, flashes "Vehicle details saved", and redirects to the drivers step. Three situations change the outcome: - **An intermediate redirect.** If `/quote/next` itself redirects to `/quote/drivers`, the first redirect's request is "the next request". The message is aged out there and never reaches the drivers page. Fix: redirect straight to the final URL, or call `reflash()` (or `keep('status')`) in the intermediate controller. - **A request in between.** If the vehicle step is submitted by JavaScript, and the script calls a session-enabled endpoint, say a premium estimate, before navigating to the drivers page, that estimate call is "the next request": it consumes the message and the drivers page renders without it. Navigate first, or keep such endpoints out of the session. - **No redirect at all.** When a controller renders a view directly after an action, `flash()` would make the message appear on this page **and** the next one. `now()` is correct here: the message shows once and is dropped when the response is sent. ## Reading flash data Flash values are ordinary session keys while they live: `session('status')` in Blade, or `$request->session()->get('status')`. Redirects that call `->with('status', ...)` flash through the same mechanism. ## Common misconceptions - Flash data does **not** wait for a page that "displays" it; the next request of any kind consumes it. - `reflash()` does **not** make data permanent; it buys exactly one more request each time it is called. - Flashing the same key again restarts its lifetime, because `flash()` removes it from `_flash.old`. - Aging happens in `save()`, so a request that starts the session but dies before saving it does not consume the flash data. ## A timeline to recite For a status message flashed in request A: 1. **Request A** (the POST): `flash()` stores the value; `_flash.new = [status]`. At save: nothing old to forget; `_flash.old = [status]`, `_flash.new = []`. 2. **Request B** (the redirect target): the value is readable. At save: `status` is forgotten; the lists move on. 3. **Request C**: the value is gone, unless B called `reflash()` or `keep('status')`, in which case C sees it and it disappears at the end of C. Being able to walk through this timeline, list by list, is what separates a memorised answer from an understood one.

  • A controller calls flash('status', ...) and then returns a view directly instead of redirecting. What does the user see?
    The message appears on this page, because flashed values are readable immediately, and again on the next page the user opens, because the key stays listed for one more request. Use `now('status', ...)` in this case: it lists the key as already old, so it is removed when this response's session is saved.
  • Does calling reflash() on every request make a flash value permanent?
    In effect it keeps extending it, one request at a time, which is why doing that blindly is a bug rather than a feature. `reflash()` moves all old flash keys back to the new list, so each call buys exactly one more request. For data that should persist, use `put()`, and remove it with `forget()` when done.

Flash data is a note left on a colleague's desk for the next shift: that shift can read it, and it goes in the bin when that shift ends, read or not. reflash() tapes every note back up for one more shift; now() is a note meant only for the shift writing it.

saying these in an interview costs you the question

  • Flash data lasts until the page that displays it is rendered
  • reflash() keeps flash data for the rest of the session
  • now() makes the value available on the next request
  • AJAX requests do not count toward flash data expiry
  • Flashed values cannot be read in the request that flashed them