Inertia 需手动将 session flash 数据注入响应 props 才能显示,因 XHR 跳转不触发 Blade 渲染;应在 HandleInertiaRequests 中间件 share() 方法中统一注入,Vue 组件需安全读取并及时清理。

Inertia 本身不提供内置的 Flash 消息机制,Laravel 的 with() 闪存数据默认只对 Blade 视图生效;要让 Inertia 页面收到 Flash 消息,必须手动把 session 中的 flash 数据注入到 Inertia 响应的 props 里——这是唯一可靠方式。
为什么 redirect()->with() 在 Inertia 页面里不显示 Flash
Laravel 的 redirect()->with('message', 'ok') 是把数据写进 session,等待下一次请求时由 SessionStore::get() 提取并清空。但 Inertia 页面跳转(如点击 InertiaLink 或调用 inertia.visit())是 XHR 请求,服务端返回的是 JSON 格式的页面组件 + props,**不会自动触发 Blade 的 flash 渲染逻辑**,也不会自动把 session flash 注入 props。
常见错误现象:
- 控制器写了
return redirect('/dashboard')->with('success', 'Saved!'),但 Dashboard.vue 里props.flash是undefined - 页面刷新后 flash 才出现(因为强制整页跳转触发了 Blade 渲染)
- 控制台没报错,但消息“凭空消失”
在 HandleInertiaRequests 中间件里注入 flash props
最稳妥的做法是统一在 app/Http/Middleware/HandleInertiaRequests.php 的 share() 方法中提取 session flash 并塞进共享 props,这样所有 Inertia 页面都能访问 props.flash。
修改该中间件的 share() 方法,加入:
use Illuminate\Support\Facades\Session;
// ...
public function share(Request $request)
{
return array_merge(parent::share($request), [
'flash' => [
'message' => Session::get('message'),
'success' => Session::get('success'),
'error' => Session::get('error'),
'warning' => Session::get('warning'),
],
]);
}
说明:
- 不要在控制器里每次手动
->with('flash', [...]),那样重复、易漏、且破坏 Inertia 的数据流一致性 - 这里用
Session::get()而非Session::pull(),因为pull()会立即删除,导致后续中间件或日志逻辑拿不到原始值;Inertia 响应完成后,Laravel 默认仍会在视图渲染阶段调用pull()清理,所以安全 - 字段名(
success、error)需与你实际with()时用的 key 一致;可按需扩展,比如加toast或duration
Vue 组件里安全读取和消费 flash
在 Vue 3 组件中,不能直接解构 props.flash 然后立刻用,因为首次加载时它可能是 null 或空对象,且 Inertia 可能尚未完成 props 注入。
推荐写法:
const props = defineProps({
flash: {
type: Object,
default: () => ({}),
},
});
// 用 onMounted + nextTick 避免挂载时 props 未就绪
onMounted(() => {
if (props.flash?.success) {
showNotification(props.flash.success, 'success');
}
if (props.flash?.error) {
showNotification(props.flash.error, 'error');
}
});
关键点:
- 必须给
flashprop 设置default: () => ({}),否则 SSR 或服务端直出时会报错 - 不要在
setup()顶层直接读props.flash.success,此时 props 还未解析完毕 - Flash 消息是一次性的,显示后建议手动清除(比如在 notification 关闭回调里
router.visit(router.page.url, { preserveState: true })),避免用户反复刷新看到同一消息
避免和 Laravel Jetstream / Fortify 冲突
如果你用了 Jetstream 或 Fortify,它们内部也注册了 HandleInertiaRequests,但可能覆盖或干扰你自定义的 flash 注入逻辑。
检查点:
- 确认你修改的是
app/Http/Middleware/HandleInertiaRequests.php,不是 vendor 里的副本 - Jetstream 的
HandleInertiaRequests默认已注入auth和jetstreamConfig,你的 flash 注入要放在array_merge(parent::share(...), [...])里,确保不覆盖原有共享项 - Fortify 的登录失败提示走的是
withErrors(),它注入的是errors对象,不是flash,别混用;errors会自动出现在props.errors,无需额外处理
真正容易被忽略的是:flash 数据在 Inertia 响应中是明文 JSON,没有任何加密或签名,如果业务涉及敏感提示(比如“密码重置链接已发至邮箱 xxx@***.com”),应先脱敏再注入 props —— 否则前端源码里就能看到完整邮箱。











