本文目录导读:

在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);
}
}
最佳实践总结
✅ 应该做的
- 单一职责原则:每个中间件只做一件事
// 错误示例 - 太多职责 class EverythingMiddleware { // 日志、认证、缓存... }
// 正确示例 class AuthMiddleware {} class LogMiddleware {} class CacheMiddleware {}
2. **使用中间件分组**:按功能域分组
```php
'api' => ['throttle', 'cors', 'auth:api']
'web' => ['csrf', 'session', 'cookies']
- 优先使用框架内置功能:避免重复造轮子
❌ 避免做的
- 在中间件中处理业务逻辑 - 应该放在控制器中
- 在中间件中进行数据库查询 - 除非是验证必须
- 中间件顺序混乱 - 考虑依赖关系
🚀 生产环境建议
// 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中间件接口实现更好的解耦。