如何在基类控制器构造函数中判断当前请求是否返回404?
问题1解答
在基类控制器构造函数的执行阶段,是否有方法可以判断当前请求最终会返回404?
- 没有办法实现。Laravel中控制器构造函数执行时,仅完成了基础路由匹配环节,后续还有路由中间件校验、控制器方法逻辑执行、路由模型绑定、业务自定义异常抛出等多个环节,任意一个环节都可能触发404响应,这些逻辑的执行结果在构造函数阶段完全无法预知。
- 另外如果是路由未匹配直接触发的404,根本不会走到控制器的构造函数,原有方案也会漏掉这部分404请求的记录。
问题2解答
如果上述需求无法实现,有没有更合理的页面访问日志记录方案,可以支持识别404请求?
推荐使用**Laravel终止中间件(Terminable Middleware)**实现,该中间件会在响应完全发送给客户端之后执行,此时可以直接拿到最终的响应状态码,且能覆盖所有请求场景(包括路由未匹配的404)。
具体实现步骤如下:
- 生成中间件文件
执行Artisan命令:php artisan make:middleware LogAccess - 编写中间件逻辑
编辑app/Http/Middleware/LogAccess.php文件,代码如下:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; use Carbon\Carbon; use DB; class LogAccess { public function handle(Request $request, Closure $next): Response { // 前置逻辑不需要处理,直接放行请求 return $next($request); } public function terminate(Request $request, Response $response): void { // 可自定义过滤规则,比如排除静态资源、后台接口等不需要记录的请求 if (!str_starts_with($request->getPathInfo(), '/storage/') && !str_starts_with($request->getPathInfo(), '/admin/')) { DB::table('analytics')->insert([ 'ip' => $request->ip(), 'session_id' => $request->hasSession() ? $request->session()->getId() : '', 'path' => $request->fullUrl(), 'status_code' => $response->getStatusCode(), // 直接记录响应状态码,可精准识别404/500等各类响应 'created_at' => Carbon::now(), ]); } } }
- 注册全局中间件
编辑app/Http/Kernel.php文件,将中间件加入全局中间件数组,确保所有请求都会触发:
protected $middleware = [ // 其他原有全局中间件 \App\Http\Middleware\LogAccess::class, ];
方案优势
- 覆盖所有请求场景,包括路由未匹配的404、模型绑定失败的404、业务代码自定义抛出的404
- 可直接获取到最终响应状态码,除了404外还能识别500、200、301等各类响应状态
- 终止中间件在响应发送后执行,写日志的操作不会影响接口响应速度,也可以进一步改成队列异步写入进一步提升性能
内容的提问来源于stack exchange,提问作者rockstardev
相关产品推荐
相关产品推荐

