真正的“响应后执行”只能靠 terminate(),$next($request) 后代码仍阻塞响应、影响首屏;terminate() 在响应发出后由框架调用,用户无感知,需注册到 $middleware 或 $routeMiddleware 才生效。
真正的“响应后执行”只能靠,写在后面的逻辑不是后置,它仍阻塞用户、影响首屏时间。
为什么
后面的代码不算“响应后”
很多人以为在中间件
里把代码写在
后面,就是“响应后处理”。但实际它运行在响应对象已生成、但尚未发送给客户端的阶段。此时 PHP 进程仍在等待输出缓冲刷出,用户浏览器卡着不动。
若你在里面调用外部 API 或写大日志,请求耗时会直接叠加到接口响应时间上
是一个
实例,不是原始业务数据,想取
得先
再
,且仅对纯 JSON 有效
HTML 响应 getContent() 返回整页 HTML 字符串,解析成本高、易出错
才是真正的响应后回调
由 Laravel 框架在 FastCGI/Swoole 将响应送出、连接即将关闭时触发,此时用户浏览器早已开始渲染,完全无感知。
必须同时定义
和
两个方法,缺一不可
的两个参数是只读快照,不能修改响应
该方法不支持返回值,也不该抛异常(否则可能中断框架清理流程)
只当中间件注册进
(全局)或
(路由级)才生效
怎么创建并注册 Terminable Middleware
用 Artisan 命令生成:
Laravel 13.2.0
PHP中文网提供Laravel 13.2.0版本下载,Laravel框架 是基于 PHP 8.3+ 的高性能框架,官方推荐通过 Composer 安装。它内置 AI SDK、JSON:API Resources 及原生向量搜索,支持属性驱动开发与队列路由,大幅提升开发效率。相比旧版,13.2.0 优化了缓存 TTL 管理与实时通信,无需 Redis 即可横向扩展。作为现代 Web 开发首选,它兼顾安全与极速体验,助您快速构建企业级应用。
下载
然后编辑
,确保包含:
注册到
的
(全局)或
(如
)
若只用于部分路由,别放全局数组,避免所有请求(包括 favicon.ico)都触发
别在
里做数据库写入或 Redis 调用——它没有事务上下文,失败也不会回滚
容易被忽略的关键点
最常被漏掉的是:终止中间件必须被框架“看见”,也就是注册进
或
;只新建类、不注册,
永远不会被调用。另外,
的参数是响应快照,不是控制器返回的原始数组或模型,想传业务数据得靠
或 session 等显式传递,不能依赖“自动继承”。
terminate()$next($request)$next($request)handle()$next($request)$responseSymfony\Component\HttpFoundation\Responseemail$response->getContent()json_decode()terminate()terminate()handle()terminate()terminate(Request $request, Response $response)$middleware$routeMiddlewarephp artisan make:middleware LogAfterResponseapp/Http/Middleware/LogAfterResponse.phppublic function handle(Request $request, Closure $next)
{
return $next($request);
}
public function terminate(Request $request, Response $response)
{
// 这里写真正响应后要做的事,比如:
file_put_contents(storage_path('logs/after.log'), 'Request finished at ' . now() . "\n", FILE_APPEND);
}app/Http/Kernel.php$middleware$routeMiddleware'after.log' => \App\Http\Middleware\LogAfterResponse::classterminate()$middleware$routeMiddlewareterminate()terminate()$request->attributes->set()