You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Laravel中记录或展示PHP致命错误?

处理Laravel 9中PHP内存耗尽致命错误的方案

针对你遇到的超大请求触发内存耗尽、无法返回自定义响应和日志的问题,可以通过以下两种方式解决:

一、捕获致命错误并返回自定义响应/记录日志

PHP的致命错误(如内存耗尽)会直接终止脚本执行,Laravel默认的Exception Handler无法捕获这类错误,需要通过register_shutdown_function在进程关闭前处理:

修改app/Exceptions/Handler.php的register方法:

public function register()
{
    $this->reportable(function (Throwable $e) {
        // 保留原有常规异常报告逻辑
    });

    // 注册致命错误回调
    register_shutdown_function(function () {
        $lastError = error_get_last();
        
        // 筛选出内存耗尽类的致命错误
        $fatalErrorTypes = [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR];
        if ($lastError && in_array($lastError['type'], $fatalErrorTypes) && str_contains($lastError['message'], 'Allowed memory size')) {
            // 1. 记录自定义日志(示例用Laravel日志系统,也可替换为自定义SQL写入)
            \Illuminate\Support\Facades\Log::error('内存耗尽错误', [
                'message' => $lastError['message'],
                'file' => $lastError['file'],
                'line' => $lastError['line'],
                'request_uri' => $_SERVER['REQUEST_URI'] ?? '',
                'timestamp' => now()->toDateTimeString()
            ]);

            // 2. 返回自定义JSON响应
            header('Content-Type: application/json');
            http_response_code(413); // 413表示请求实体过大,语义更准确
            echo json_encode([
                'status' => 'failed',
                'message' => '请求数据量过大,请使用分页功能或减少单次请求的数据规模'
            ]);
            exit;
        }
    });
}

注意事项:

  • 若要直接写入SQL日志,需确保数据库连接在致命错误发生时仍可用;优先推荐使用Laravel日志系统,稳定性更高。
  • 需手动设置HTTP响应头和状态码,因为此时Laravel的响应生命周期已终止。

二、提前拦截超大请求(从源头避免错误)

在请求进入业务逻辑前,通过中间件检查请求大小,直接拦截超出阈值的请求:

  1. 创建中间件CheckRequestSize:
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class CheckRequestSize
{
    public function handle(Request $request, Closure $next)
    {
        // 设定允许的最大请求大小(示例为10MB)
        $maxAllowedSize = 10 * 1024 * 1024;
        
        // 检查请求头部的Content-Length
        if ($request->hasHeader('Content-Length')) {
            $requestSize = (int)$request->header('Content-Length');
            if ($requestSize > $maxAllowedSize) {
                return response()->json([
                    'status' => 'failed',
                    'message' => '请求实体过大,请使用分页功能'
                ], 413);
            }
        }

        return $next($request);
    }
}
  1. 在app/Http/Kernel.php中注册中间件,并添加到API中间件组:
protected $routeMiddleware = [
    // 其他中间件...
    'check.request.size' => \App\Http\Middleware\CheckRequestSize::class,
];

protected $middlewareGroups = [
    'api' => [
        // 其他中间件...
        'check.request.size',
    ],
];

这种方式能在请求处理初期就拦截风险,避免触发内存耗尽错误,体验更优。

内容的提问来源于stack exchange,提问作者user1829002

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 17:45:44