PHP中间件机制怎么用最好

wen PHP项目 1

本文目录导读:

PHP中间件机制怎么用最好

  1. 现代框架中的中间件(以Laravel为例)
  2. 手动实现中间件(不依赖框架)
  3. 微服务中的中间件
  4. 性能优化高级技巧
  5. 最佳实践总结

在PHP中,中间件机制的最佳实践取决于你使用的框架(或是否自建),我来分享几种主流场景下的最佳用法:

现代框架中的中间件(以Laravel为例)

最佳实践:责任链模式 + 依赖注入

// 1. 创建中间件
php artisan make:middleware ThrottleRequests
php artisan make:middleware LogRequest
// 2. 中间件实现
class LogRequest
{
    public function handle($request, Closure $next)
    {
        // 前置操作
        Log::info('Request started', ['url' => $request->url()]);
        $response = $next($request);
        // 后置操作
        Log::info('Request completed', ['status' => $response->status()]);
        return $response;
    }
}
class ThrottleRequests
{
    public function handle($request, Closure $next)
    {
        if (Redis::get("throttle:{$request->ip()}") > 100) {
            abort(429, 'Too Many Requests');
        }
        return $next($request);
    }
}
// 3. 注册中间件(最佳方式:分组注册)
protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        MiddlewareGroup::class, // 自定义
    ],
    'api' => [
        'throttle:60,1', // 使用参数
        ThrottleRequests::class,
        LogRequest::class,
    ],
];

手动实现中间件(不依赖框架)

<?php
interface MiddlewareInterface
{
    public function handle(Request $request, callable $next): Response;
}
class MiddlewarePipeline
{
    private array $middlewares = [];
    public function add(MiddlewareInterface $middleware): self
    {
        $this->middlewares[] = $middleware;
        return $this;
    }
    public function process(Request $request): Response
    {
        // 构建中间件链
        $pipeline = array_reduce(
            array_reverse($this->middlewares),
            function ($next, MiddlewareInterface $middleware) {
                return function ($request) use ($middleware, $next) {
                    return $middleware->handle($request, $next);
                };
            },
            function ($request) {
                return $this->handleRequest($request); // 最终处理器
            }
        );
        return $pipeline($request);
    }
}
// 使用示例
class AuthMiddleware implements MiddlewareInterface
{
    public function handle(Request $request, callable $next): Response
    {
        if (!$request->hasHeader('Authorization')) {
            return new Response('Unauthorized', 401);
        }
        return $next($request); // 传递给下一个中间件
    }
}
class CorsMiddleware implements MiddlewareInterface
{
    public function handle(Request $request, callable $next): Response
    {
        $response = $next($request);
        $response->setHeader('Access-Control-Allow-Origin', '*');
        return $response;
    }
}
// 调用
$pipeline = new MiddlewarePipeline();
$pipeline->add(new AuthMiddleware());
$pipeline->add(new CorsMiddleware());
$response = $pipeline->process($request);

微服务中的中间件

// 使用 PhpMiddleware 库(独立)
use PhpMiddleware\Execution\MiddlewareRunner;
$middlewareStack = new MiddlewareRunner([
    function ($request, $next) {
        // 日志记录
        Logger::info('Request', $request->toArray());
        $response = $next($request);
        Logger::info('Response', ['status' => $response->getStatusCode()]);
        return $response;
    },
    function ($request, $next) {
        // 缓存检查
        if ($cached = Cache::get($request->getUri())) {
            return new JsonResponse($cached);
        }
        return $next($request);
    },
    new RequestHandler() // 实际业务处理器
]);
$response = $middlewareStack->handle($request);

性能优化高级技巧

1 中间件缓存

class CacheableMiddleware
{
    private static array $cache = [];
    public function handle($request, Closure $next)
    {
        $key = $this->generateKey($request);
        if (isset(self::$cache[$key])) {
            return self::$cache[$key];
        }
        self::$cache[$key] = $next($request);
        return self::$cache[$key];
    }
    private function generateKey($request): string
    {
        return md5($request->method() . ':' . $request->getRequestUri());
    }
}

2 条件性中间件(避免不必要的处理)

class ConditionalMiddleware
{
    public function handle($request, Closure $next)
    {
        // 只在特定条件下执行
        if ($request->is('api/*')) {
            // 只对API路由执行
        }
        if ($request->method() === 'GET') {
            return $next($request); // GET请求跳过此中间件
        }
        return $next($request);
    }
}

最佳实践总结

✅ 应该做的

  1. 单一职责原则:每个中间件只做一件事
    // 错误示例 - 太多职责
    class EverythingMiddleware {
     // 日志、认证、缓存...
    }

// 正确示例 class AuthMiddleware {} class LogMiddleware {} class CacheMiddleware {}


2. **使用中间件分组**:按功能域分组
```php
'api' => ['throttle', 'cors', 'auth:api']
'web' => ['csrf', 'session', 'cookies']
  1. 优先使用框架内置功能:避免重复造轮子

❌ 避免做的

  1. 在中间件中处理业务逻辑 - 应该放在控制器中
  2. 在中间件中进行数据库查询 - 除非是验证必须
  3. 中间件顺序混乱 - 考虑依赖关系

🚀 生产环境建议

// 1. 使用中间件优先级
protected $middlewarePriority = [
    \App\Http\Middleware\CheckForMaintenanceMode::class,
    \App\Http\Middleware\EncryptCookies::class,
    \App\Http\Middleware\ValidatePostSize::class,
    // 自定义中间件
];
// 2. 终端中间件(响应已生成后执行)
class TerminableMiddleware
{
    public function terminate($request, $response)
    {
        // 日志记录、缓存预热等
        // 此时响应已发送,适合后处理
    }
}

选择合适的中间件策略取决于项目规模和需求,对于小型项目,使用框架内置的就够了;对于大型系统,考虑使用PSR-15中间件接口实现更好的解耦。

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