laravel 中间件记录日志

前提

我希望通过中间件记录用户的请求数据、我的返回数据,如果出现异常捕获异常。

代码

路由文件:追加中间件api-logging,用于记录日志

php 复制代码
Route::prefix('api')->middleware(['api', 'api-logging'])->group(function () {
    ...路由内容
});
php 复制代码
namespace App\Http;
class Kernel extends HttpKernel
{
	 ...其他内容
	protected $routeMiddleware = [
		... 其他中间件
        'api-logging' => \App\Http\Middleware\ApiLoggingMiddleware::class,
    ];
}

重点:中间件的编写

php 复制代码
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use App\Models\GameThirdPartyCallback;

class ApiLoggingMiddleware
{
    public function handle(Request $request, Closure $next)
    {
        $requestHeaders = $request->header();
        $requestData = $request->all();
        $source = $request->header('referer') ?? $request->ip();

        try {
            // 执行请求并获取响应
            $response = $next($request);
            $responseStatus = $response->status();
            $responseContent = $response->getContent();
        } catch (\Exception $exception) {
            // 记录异常信息
            GameThirdPartyCallback::create([
                'request_headers' => json_encode($requestHeaders),
                'callback_data' => json_encode($requestData),
                'response_status' => 500, // 或其他适当的错误状态码
                'response_content' => 'An error occurred: ' . $exception->getMessage(),
                'sources' => $source
            ]);

            // 重新抛出异常,交由Laravel处理
            throw $exception;
        }

        // 记录正常的响应数据
        GameThirdPartyCallback::create([
            'request_headers' => json_encode($requestHeaders),
            'callback_data' => json_encode($requestData),
            'response_status' => $responseStatus,
            'response_content' => $responseContent,
            'sources' => $source
        ]);

        return $response;
    }
}

我希望在,下面这段可以当 n e x t ( next( next(request); 出现异常被捕获

php 复制代码
try {
            // 执行请求并获取响应
            $response = $next($request);
        } catch (\Exception $exception) {
            
            // 重新抛出异常,交由Laravel处理
            throw $exception;
        }

然而并不行,如果控制器中出现了异常,会被laravel的全局异常处理机制捕获,$response = $next($request); 会返回捕获后的异常处理的类,也就是异常已经被处理掉了

最终处理方案

在全局异常处理的时候,将异常内容插入到request中,然后在中间件去获取这个自定义的属性

  1. 全局处理文件中,加入下面这段代码
php 复制代码
namespace App\Exceptions;

use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;

class Handler extends ExceptionHandler
{

/**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Throwable  $exception
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function render($request, Throwable $exception)
    {
        // 这里这段的内容是为了让异常内容可以被中间件获取
        // 因为控制器的异常会被laravel全局异常直接捕获,导致中间件获取的内容是异常页面
        $request->attributes->set('exception_message', $exception->getMessage());
        return parent::render($request, $exception);
    }
}

然后中间件中获取exception_message

php 复制代码
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use App\Models\GameThirdPartyCallback;

class ApiLoggingMiddleware
{
    public function handle(Request $request, Closure $next)
    {
        $requestHeaders = $request->header();
        $requestData = $request->all();
        $source = $request->header('referer') ?? $request->ip();

        $response = $next($request);  // 如果这里产生了异常,不会在这里try catch。而是直接返回了response的错误内容
        $responseStatus = $response->status();

        if ($responseStatus >= 400 && $responseStatus < 600) {
            GameThirdPartyCallback::create([
                'request_headers' => json_encode($requestHeaders),
                'callback_data' => json_encode($requestData),
                'response_status' => $responseStatus,
                'response_content' => $request->attributes->get("exception_message"),
                'sources' => $source
            ]);
        } else {
            ...
        }

        return $response;
    }

}
相关推荐
TlSfoward17 小时前
抓包代理链路下的 TLS 指纹变化分析 TLSFOWARD抓包工具
数据库·爬虫·网络协议·搜索引擎·php
—Miss. Z—20 小时前
计算机二级MySQL——简单应用题(存储过程&存储函数)
数据库·oracle·php
故乡de云20 小时前
AWS 添加付款方式失败排查清单:卡片、银行风控与账号状态逐项定位
开发语言·php
梦梦代码精21 小时前
基于ThinkPHP6 + Vue3的家政预约系统全解析:从LBS定位到自动派单的完整实现
java·docker·开源·php·代码规范
郑州光合科技余经理1 天前
家政O2O平台解析:从0搭建上门预约小程序解决方案
android·java·开发语言·前端·小程序·架构·php
lxw18449125141 天前
PHP后端(CI框架方向)面试题库,分为基础必问、MySQL、Redis、工程运维、高阶加分、场景实操六大模块,适配该JD全部考点,附带标准答案
ci/cd·面试·php
郑州光合科技余经理1 天前
家政预约小程序后端源码深度剖析:支付回调实战
java·开发语言·前端·git·小程序·架构·php
索西引擎1 天前
【React】Redux 中间件机制:副作用处理与数据流增强的形式化分析
前端·react.js·中间件
糖果店的幽灵1 天前
【DeepAgents 从入门到精通】Context Management 上下文管理
java·人工智能·后端·spring·中间件·langgraph·deepagents
weixin_408099672 天前
2026 图片去水印 API 接口完全指南:一键去除图片水印(附 Python/Java/PHP/C# 示例)
java·python·php·图片处理·api调用·图片去水印·石榴智能