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;
    }

}
相关推荐
BingoGo11 小时前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack11 小时前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack1 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo1 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
BingoGo2 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·laravel
JaguarJack2 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理3 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
QQ5110082853 天前
python+springboot+django/flask的校园资料分享系统
spring boot·python·django·flask·node.js·php
WeiXin_DZbishe3 天前
基于django在线音乐数据采集的设计与实现-计算机毕设 附源码 22647
javascript·spring boot·mysql·django·node.js·php·html5
SunnyRivers3 天前
LangChain中间件详解
中间件·langchain