PHP项目Mezzio中间件架构

wen PHP项目 5

本文目录导读:

PHP项目Mezzio中间件架构

  1. 核心概念
  2. 中间件管道
  3. 中间件类型
  4. 高级中间件模式
  5. 配置驱动的管道管理
  6. 中间件工厂模式
  7. 管道优先级示例
  8. 最佳实践

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);
}

最佳实践

  1. 中间件顺序很重要 - 管道顺序影响执行结果
  2. 保持中间件职责单一 - 每个中间件只做一件事
  3. 使用依赖注入 - 避免在中间件中直接实例化服务
  4. 处理异常 - 在中间件中使用 try-catch 时要小心
  5. 性能考虑 - 简单操作放在管道前面

这种架构模式让 Mezzio 非常灵活且可扩展,适合构建从简单API到复杂的企业级应用。

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