自定义本地化中间件重复执行问题:如何设置单次执行标记
问题描述
我配置了一套自定义Middleware(中间件),用于按优先级设置本地化(localization)。该中间件功能符合预期,但会重复执行。通常遇到需仅执行一次的重复执行场景时,我会通过变量或Session设置标记并检查状态,但在Middleware中无法实现该逻辑,不清楚标记应设置在何处。附上我的尝试代码:
class Localization { public function handle(Request $request, Closure $next): Response { # Set Already Run Flag if ($request->has('hasRun')) { # Return Before Code Runs return $next($request); } # Run Code # Then Set Variable $request->attributes->set('hasRun', true); return $next($request); } }
解决方案
你的思路方向是对的,但$request->has('hasRun')默认检测的是请求的Query/Post参数,而非你设置的请求属性,导致判断逻辑失效。修改为检查请求属性即可解决:
class Localization { public function handle(Request $request, Closure $next): Response { // 检查是否已执行过本地化逻辑 if ($request->attributes->has('hasRun')) { return $next($request); } // 这里替换为你的实际本地化设置代码 // 示例:按优先级获取并设置locale $locale = $request->header('Accept-Language') ?? session('locale') ?? config('app.locale'); app()->setLocale($locale); // 标记已执行 $request->attributes->set('hasRun', true); return $next($request); } }
除此之外,还有两种可选方案:
- 规范中间件注册:确保你的本地化中间件仅在全局中间件列表或目标路由组中注册一次,避免重复挂载导致多次执行。
- 利用服务容器标记:通过Laravel服务容器设置单例标记,不受请求属性限制:
class Localization { public function handle(Request $request, Closure $next): Response { if (app()->has('localization.executed')) { return $next($request); } // 执行本地化逻辑... app()->instance('localization.executed', true); return $next($request); } }
这种方式适用于同一次请求内包含子请求的场景,按需选择即可。
内容的提问来源于stack exchange,提问作者Aerdan
相关产品推荐
相关产品推荐

