本文目录导读:

Mezzio(原名 Expressive)是一个基于 PSR-7/PSR-15 标准的 PHP 微框架,中间件架构是其核心,下面是 Mezzio 中间件架构的详细解析:
核心概念
PSR-15 标准
// PSR-15 中间件接口
interface MiddlewareInterface
{
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface;
}
中间件管道
管道创建
// config/pipeline.php
use Mezzio\Middleware\ErrorResponseGenerator;
return function (Application $app, MiddlewareFactory $factory, ContainerInterface $container) : void {
// 全局管道
$app->pipe(ErrorMiddleware::class);
$app->pipe(ServerUrlMiddleware::class);
// 路由中间件
$app->pipe(RoutingMiddleware::class);
// 分发中间件(包含路由匹配后的管道)
$app->pipe(DispatchMiddleware::class);
// 隐式 HEAD/OPTIONS 支持
$app->pipe(ImplicitHeadMiddleware::class);
$app->pipe(ImplicitOptionsMiddleware::class);
// 路由结果处理
$app->pipe(UrlHelperMiddleware::class);
};
中间件类型
1 应用级中间件
// src/App/Middleware/AuthenticationMiddleware.php
namespace App\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class AuthenticationMiddleware implements MiddlewareInterface
{
public function __construct(
private SessionManager $sessionManager,
private ResponseFactory $responseFactory
) {}
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface {
$session = $this->sessionManager->getSession($request);
if (!$session->has('user')) {
$response = $this->responseFactory->createResponse(302);
return $response->withHeader('Location', '/login');
}
// 将用户信息添加到请求属性中
$request = $request->withAttribute('user', $session->get('user'));
return $handler->handle($request);
}
}
2 路由级中间件
// config/routes.php
use App\Middleware\ValidationMiddleware;
use App\Handler\CreateUserHandler;
$app->post('/api/users', [
ValidationMiddleware::class,
CreateUserHandler::class
], 'api.users.create');
// 或者分组
$app->group('/admin', function (RouteCollectorProxy $group) {
$group->get('/dashboard', AdminDashboardHandler::class, 'admin.dashboard');
$group->get('/settings', AdminSettingsHandler::class, 'admin.settings');
})->add(AuthenticationMiddleware::class)
->add(AdminRoleMiddleware::class);
3 装饰器中间件
// src/App/Middleware/CacheMiddleware.php
namespace App\Middleware;
class CacheMiddleware implements MiddlewareInterface
{
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface {
$response = $handler->handle($request);
// 添加缓存头
return $response
->withHeader('Cache-Control', 'private, max-age=600')
->withHeader('Expires', gmdate(DATE_RFC1123, time() + 600));
}
}
高级中间件模式
1 双向中间件
// src/App/Middleware/RequestLoggerMiddleware.php
use Psr\Log\LoggerInterface;
class RequestLoggerMiddleware implements MiddlewareInterface
{
public function __construct(private LoggerInterface $logger) {}
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface {
$start = microtime(true);
$method = $request->getMethod();
$uri = $request->getUri()->__toString();
$this->logger->info("Request started: $method $uri");
try {
$response = $handler->handle($request);
$duration = microtime(true) - $start;
$this->logger->info(
"Request completed: $method $uri - " . $response->getStatusCode() . " ({$duration}s)"
);
return $response;
} catch (\Throwable $e) {
$this->logger->error("Request failed: $method $uri - " . $e->getMessage());
throw $e;
}
}
}
2 依赖注入中间件
// config/autoload/middleware.global.php
return [
'dependencies' => [
'factories' => [
AuthenticationMiddleware::class =>
AuthenticationMiddlewareFactory::class,
ValidationMiddleware::class =>
ValidationMiddlewareFactory::class,
],
'invokables' => [
SecurityHeadersMiddleware::class,
],
],
'middleware' => [
'pipeline' => [
'always' => [
SecurityHeadersMiddleware::class,
ContentSecurityPolicyMiddleware::class,
],
'protected' => [
AuthenticationMiddleware::class,
AuthorizationMiddleware::class,
],
],
],
];
3 条件中间件
// src/App/Middleware/MaintenanceMiddleware.php
class MaintenanceMiddleware implements MiddlewareInterface
{
public function __construct(
private bool $maintenanceMode,
private string $maintenanceIp
) {}
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface {
$clientIp = $request->getServerParams()['REMOTE_ADDR'] ?? '';
if ($this->maintenanceMode && $clientIp !== $this->maintenanceIp) {
return new TextResponse('Maintenance mode', 503);
}
return $handler->handle($request);
}
}
配置驱动的管道管理
// config/pipeline.php
use Laminas\Stratigility\Middleware\ErrorHandler;
use Mezzio\Application;
return function (Application $app, MiddlewareFactory $factory, ContainerInterface $container) : void {
// 注册错误处理器
$app->pipe(ErrorHandler::class);
// 加载配置
$config = $container->get('config')['pipeline'] ?? [];
if (isset($config['always'])) {
foreach ($config['always'] as $middleware) {
$app->pipe($middleware);
}
}
// 路由中间件
$app->pipeRoutingMiddleware();
// 动态路由
if (isset($config['before_routing'])) {
foreach ($config['before_routing'] as $middleware) {
$app->pipeBeforeRouting($middleware);
}
}
// 管线注册
$app->pipeDispatchMiddleware();
};
中间件工厂模式
// src/App/Factory/MiddlewareFactory.php
namespace App\Factory;
use Psr\Container\ContainerInterface;
class AuthenticationMiddlewareFactory
{
public function __invoke(ContainerInterface $container): AuthenticationMiddleware
{
$config = $container->get('config')['auth'] ?? [];
return new AuthenticationMiddleware(
sessionManager: $container->get(SessionManager::class),
responseFactory: $container->get(ResponseFactoryInterface::class),
userRepository: $container->get(UserRepository::class),
config: $config
);
}
}
管道优先级示例
// 完整的管道示例
public function bootstrap(Application $app) : void
{
// 第1层:基础错误处理
$app->pipe(ErrorHandler::class);
// 第2层:请求日志
$app->pipe(RequestLoggerMiddleware::class);
// 第3层:安全头
$app->pipe(SecurityHeadersMiddleware::class);
// 第4层:维护模式检查
$app->pipe(MaintenanceMiddleware::class);
// 第5层:Session
$app->pipe(SessionMiddleware::class);
// 第6层:认证
$app->pipe(AuthenticationMiddleware::class);
// 第7层:加载路由
$app->pipe(RoutingMiddleware::class);
// 第8层:路由匹配后执行
$app->pipe(DispatchMiddleware::class);
}
最佳实践
- 中间件顺序很重要 - 管道顺序影响执行结果
- 保持中间件职责单一 - 每个中间件只做一件事
- 使用依赖注入 - 避免在中间件中直接实例化服务
- 处理异常 - 在中间件中使用 try-catch 时要小心
- 性能考虑 - 简单操作放在管道前面
这种架构模式让 Mezzio 非常灵活且可扩展,适合构建从简单API到复杂的企业级应用。