Laravel降级响应怎么返回

wen PHP项目 5

本文目录导读:

Laravel降级响应怎么返回

  1. 使用中间件进行降级处理
  2. 在控制器中返回降级响应
  3. 使用异常处理进行全局降级
  4. 使用门面或辅助函数
  5. 降级响应格式化器
  6. 结合缓存和配置管理
  7. 完整的降级响应示例
  8. 路由级别的降级控制

在Laravel中进行降级响应(Degraded Response)通常有以下几种实现方式:

使用中间件进行降级处理

// app/Http/Middleware/DegradeResponse.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class DegradeResponse
{
    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);
        // 检查是否需要降级
        if ($this->shouldDegrade()) {
            // 返回降级后的响应
            return response()->json([
                'status' => 'degraded',
                'message' => '服务暂时降级,请稍后重试',
                'data' => null
            ], 200); // 保持200状态码
        }
        return $response;
    }
    protected function shouldDegrade(): bool
    {
        // 判断逻辑:系统负载、服务可用性等
        return cache()->get('degraded_mode', false);
    }
}

在控制器中返回降级响应

// app/Http/Controllers/ApiController.php
namespace App\Http\Controllers;
use Illuminate\Http\JsonResponse;
class ApiController extends Controller
{
    public function getUserData($id): JsonResponse
    {
        // 检测是否需要降级
        if ($this->isSystemDegraded()) {
            return $this->degradedResponse('用户服务暂时不可用');
        }
        try {
            $user = User::findOrFail($id);
            return response()->json([
                'status' => 'success',
                'data' => $user
            ]);
        } catch (\Exception $e) {
            return $this->degradedResponse('查询用户信息失败');
        }
    }
    protected function degradedResponse(string $message): JsonResponse
    {
        return response()->json([
            'status' => 'degraded',
            'message' => $message,
            'timestamp' => now()->timestamp
        ], 200);
    }
    protected function isSystemDegraded(): bool
    {
        // 检查系统负载、第三方服务状态等
        return system_load_average() > 0.8 || 
               app('redis')->exists('system_degraded');
    }
}

使用异常处理进行全局降级

// app/Exceptions/Handler.php
namespace App\Exceptions;
use Throwable;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
class Handler extends ExceptionHandler
{
    public function render($request, Throwable $e)
    {
        // 如果是API请求且系统处于降级模式
        if ($request->expectsJson() && $this->isDegradedMode()) {
            return response()->json([
                'status' => 'degraded',
                'message' => '系统正在降级运行',
                'error' => $e->getMessage()
            ], 200);
        }
        return parent::render($request, $e);
    }
    protected function isDegradedMode(): bool
    {
        return config('app.degraded_mode', false) || 
               app()->runningInConsole() === false;
    }
}

使用门面或辅助函数

创建一个全局辅助函数:

// app/helpers.php (记得在composer.json中autoload)
if (!function_exists('degraded_response')) {
    function degraded_response($message = '服务降级', $data = null, $status = 200)
    {
        return response()->json([
            'status' => 'degraded',
            'message' => $message,
            'data' => $data,
            'timestamp' => now()->toIso8601String()
        ], $status);
    }
}

使用:

// 在任何控制器或路由中
return degraded_response('数据库连接超时');

降级响应格式化器

// app/Services/DegradedResponse.php
namespace App\Services;
use Illuminate\Http\JsonResponse;
class DegradedResponse
{
    protected array $config;
    public function __construct()
    {
        $this->config = config('degraded');
    }
    public function respond(string $reason = '', array $data = []): JsonResponse
    {
        $response = [
            'status' => 'degraded',
            'code' => $this->config['code'] ?? 200,
            'message' => $reason ?: ($this->config['message'] ?? 'Service temporarily unavailable'),
            'timestamp' => now()->timestamp,
            'data' => $data
        ];
        return response()->json($response, $this->config['http_status'] ?? 200);
    }
}

注册为服务:

// app/Providers/AppServiceProvider.php
public function register()
{
    $this->app->singleton('degraded', function ($app) {
        return new \App\Services\DegradedResponse();
    });
}

结合缓存和配置管理

// config/degraded.php
return [
    'enabled' => env('DEGRADED_MODE', false),
    'message' => '系统正在降级运行,部分功能可能不可用',
    'http_status' => 200,
    'code' => 200,
];
// 在服务提供者中动态控制
use Illuminate\Support\Facades\Cache;
public function boot()
{
    // 监听配置变更
    Cache::macro('degradedMode', function () {
        return Cache::remember('degraded_mode', 60, function () {
            return config('degraded.enabled');
        });
    });
}

完整的降级响应示例

// app/Http/Controllers/ProductController.php
namespace App\Http\Controllers;
use App\Services\DegradedResponse;
use Illuminate\Http\JsonResponse;
class ProductController extends Controller
{
    public function __construct(
        protected DegradedResponse $degradedResponse
    ) {}
    public function index(): JsonResponse
    {
        // 检查数据库连接
        if (!app('db')->connection()->getPdo()) {
            return $this->degradedResponse->respond('数据库连接异常');
        }
        // 检查Redis缓存
        if (!app('redis')->ping()) {
            return $this->degradedResponse->respond('缓存服务异常');
        }
        // 正常业务逻辑
        try {
            $products = Product::paginate(20);
            return response()->json([
                'status' => 'success',
                'data' => $products
            ]);
        } catch (\Exception $e) {
            // 数据库降级:从备份或缓存返回数据
            $products = Cache::get('products_cache', []);
            return $this->degradedResponse->respond('使用备用数据', $products);
        }
    }
}

路由级别的降级控制

// routes/api.php
use Illuminate\Support\Facades\Route;
Route::middleware(['degraded'])->group(function () {
    Route::get('/users', 'UserController@index');
    Route::get('/products', 'ProductController@index');
});
// 或者在全局中间件中
Route::middleware(['api', 'degraded'])->group(function () {
    require base_path('routes/api.php');
});

降级响应最佳实践:

  1. 保持HTTP状态码200:降级不代表错误,保持客户端正常接收
  2. 明确的状态标识:让客户端知道这是降级响应
  3. 合理的时间戳:帮助调试和监控
  4. 详细的原因说明:提供降级原因供开发者定位问题
  5. 备用数据:尽可能提供备用的缓存数据

抱歉,评论功能暂时关闭!