中间件配置

最后更新: 2026-01-27 11:02:47

中间件配置

Unicode Framework 提供了灵活的中间件配置系统,允许你通过配置文件管理中间件别名、中间件组和自定义中间件。

概述

中间件配置系统提供了以下功能:

  • 中间件别名:为中间件类创建简短的别名,方便在路由中使用
  • 中间件组:将多个中间件组合成一个组,可以批量应用到路由
  • 自定义中间件配置:配置自定义中间件的构造函数参数,支持从配置文件读取参数值
  • 配置文件

    中间件配置位于 config/middleware.php 文件中。如果该文件不存在,框架会使用默认配置。

    配置文件结构

    <?php
    declare(strict_types=1);
    

    return [ // 中间件别名配置 'aliases' => [ 'auth' => \Unicode\Framework\Auth\Middleware\JwtMiddleware::class, ],

    // 中间件组配置 'groups' => [ 'api' => ['auth', 'throttle'], 'web' => ['session', 'csrf'], ],

    // 自定义中间件配置 'custom' => [ \App\Middleware\CustomMiddleware::class => [ 'class' => \App\Middleware\CustomMiddleware::class, 'params' => [ 'apiKey' => 'your-api-key', 'timeout' => 30, ], 'singleton' => false, ], ], ];

    中间件别名

    中间件别名允许你为中间件类创建简短的名称,方便在路由中使用。

    配置别名

    config/middleware.php 文件中配置别名:

    return [
        'aliases' => [
            'auth' => \Unicode\Framework\Auth\Middleware\JwtMiddleware::class,
            'throttle' => \App\Middleware\ThrottleMiddleware::class,
        ],
    ];
    

    使用别名

    在路由中使用别名:

    use Unicode\Framework\Route\Route;
    

    // 使用别名 Route::middleware(['auth'], function() { Route::get('/api/user', [UserController::class, 'show']); });

    // 别名和类名可以混用 Route::middleware(['auth', \App\Middleware\CustomMiddleware::class], function() { Route::get('/api/profile', [ProfileController::class, 'show']); });

    中间件组

    中间件组允许你将多个中间件组合成一个组,方便批量应用到路由。

    配置中间件组

    config/middleware.php 文件中配置中间件组:

    return [
        'aliases' => [
            'auth' => \Unicode\Framework\Auth\Middleware\JwtMiddleware::class,
            'throttle' => \App\Middleware\ThrottleMiddleware::class,
            'cors' => \App\Middleware\CorsMiddleware::class,
        ],
    

    'groups' => [ // API 中间件组:包含认证和限流 'api' => ['auth', 'throttle'],

    // Web 中间件组:包含会话和 CSRF 保护 'web' => ['session', 'csrf'],

    // 复合中间件组:可以包含其他组 'api-secure' => ['api', 'cors'], ], ];

    使用中间件组

    在路由中使用中间件组:

    use Unicode\Framework\Route\Route;
    

    // 使用中间件组 Route::middleware(['api'], function() { Route::get('/api/users', [UserController::class, 'index']); Route::post('/api/users', [UserController::class, 'store']); });

    // 中间件组和单个中间件可以混用 Route::middleware(['api', \App\Middleware\LoggingMiddleware::class], function() { Route::get('/api/logs', [LogController::class, 'index']); });

    自定义中间件配置

    自定义中间件配置允许你为中间件配置构造函数参数,支持从配置文件读取参数值。

    创建自定义中间件

    首先,创建一个实现 MiddlewareInterface 的中间件类:

    <?php
    declare(strict_types=1);
    

    namespace App\Middleware;

    use Unicode\Framework\Http\Request; use Unicode\Framework\Http\Response; use Unicode\Framework\Interfaces\MiddlewareInterface;

    class CustomMiddleware implements MiddlewareInterface { public function __construct( private readonly string $apiKey, private readonly int $timeout = 30, ) {}

    public function process(Request $request, callable $next): Response { // 中间件逻辑 // 例如:验证 API Key if ($request->header('X-API-Key') !== $this->apiKey) { return Response::json(['error' => 'Invalid API Key'], 401); }

    return $next($request); } }

    配置自定义中间件

    config/middleware.php 文件中配置自定义中间件:

    return [
        'custom' => [
            \App\Middleware\CustomMiddleware::class => [
                'class' => \App\Middleware\CustomMiddleware::class,
                'params' => [
                    'apiKey' => getenv('CUSTOM_API_KEY') ?: 'default-key',
                    'timeout' => 60,
                ],
                'singleton' => false,  // 是否注册为单例
            ],
        ],
    ];
    

    从配置文件读取参数

    你可以使用点号语法从其他配置文件读取参数值:

    // config/app.php
    return [
        'api_key' => 'your-api-key',
        'timeout' => 30,
    ];
    

    // config/middleware.php return [ 'custom' => [ \App\Middleware\CustomMiddleware::class => [ 'class' => \App\Middleware\CustomMiddleware::class, 'params' => [ 'apiKey' => 'app.api_key', // 从 app.php 读取 'timeout' => 'app.timeout', // 从 app.php 读取 ], ], ], ];

    单例模式

    如果 singleton 设置为 true,中间件会被注册为单例,每次从容器获取时都会返回同一个实例:

    return [
        'custom' => [
            \App\Middleware\CustomMiddleware::class => [
                'class' => \App\Middleware\CustomMiddleware::class,
                'params' => [
                    'apiKey' => 'your-api-key',
                ],
                'singleton' => true,  // 单例模式
            ],
        ],
    ];
    

    依赖注入

    如果中间件构造函数需要其他服务(如容器中的其他服务),框架会自动从容器中注入:

    <?php
    declare(strict_types=1);
    

    namespace App\Middleware;

    use Unicode\Framework\Config\Config; use Unicode\Framework\Http\Request; use Unicode\Framework\Http\Response; use Unicode\Framework\Interfaces\MiddlewareInterface;

    class ConfigurableMiddleware implements MiddlewareInterface { public function __construct( private readonly Config $config, // 自动从容器注入 private readonly string $apiKey, ) {}

    public function process(Request $request, callable $next): Response { // 使用注入的服务 $debug = $this->config->get('app.debug', false);

    return $next($request); } }

    配置时只需要提供非服务类型的参数:

    return [
        'custom' => [
            \App\Middleware\ConfigurableMiddleware::class => [
                'class' => \App\Middleware\ConfigurableMiddleware::class,
                'params' => [
                    'apiKey' => 'your-api-key',
                    // Config 会自动从容器注入,不需要配置
                ],
            ],
        ],
    ];
    

    使用示例

    示例 1:简单的认证中间件

    // config/middleware.php
    return [
        'aliases' => [
            'auth' => \Unicode\Framework\Auth\Middleware\JwtMiddleware::class,
        ],
    ];
    

    // route.php use Unicode\Framework\Route\Route;

    Route::middleware(['auth'], function() { Route::get('/api/user', [UserController::class, 'show']); Route::put('/api/user', [UserController::class, 'update']); });

    示例 2:API 中间件组

    // config/middleware.php
    return [
        'aliases' => [
            'auth' => \Unicode\Framework\Auth\Middleware\JwtMiddleware::class,
            'throttle' => \App\Middleware\ThrottleMiddleware::class,
        ],
        'groups' => [
            'api' => ['auth', 'throttle'],
        ],
    ];
    

    // route.php use Unicode\Framework\Route\Route;

    Route::middleware(['api'], function() { Route::get('/api/users', [UserController::class, 'index']); Route::post('/api/users', [UserController::class, 'store']); });

    示例 3:自定义中间件配置

    // config/middleware.php
    return [
        'custom' => [
            \App\Middleware\ApiKeyMiddleware::class => [
                'class' => \App\Middleware\ApiKeyMiddleware::class,
                'params' => [
                    'apiKey' => getenv('API_KEY') ?: 'default-key',
                ],
            ],
        ],
        'aliases' => [
            'api-key' => \App\Middleware\ApiKeyMiddleware::class,
        ],
    ];
    

    // route.php use Unicode\Framework\Route\Route;

    Route::middleware(['api-key'], function() { Route::get('/api/data', [DataController::class, 'index']); });

    示例 4:复合中间件组

    // config/middleware.php
    return [
        'aliases' => [
            'auth' => \Unicode\Framework\Auth\Middleware\JwtMiddleware::class,
            'throttle' => \App\Middleware\ThrottleMiddleware::class,
            'cors' => \App\Middleware\CorsMiddleware::class,
            'logging' => \App\Middleware\LoggingMiddleware::class,
        ],
        'groups' => [
            'api' => ['auth', 'throttle'],
            'api-secure' => ['api', 'cors', 'logging'],
        ],
    ];
    

    // route.php use Unicode\Framework\Route\Route;

    Route::middleware(['api-secure'], function() { Route::get('/api/secure-data', [SecureDataController::class, 'index']); });

    最佳实践

    1. 使用别名提高可读性

    使用有意义的别名,而不是直接使用类名:

    // 好的做法
    'aliases' => [
        'auth' => \Unicode\Framework\Auth\Middleware\JwtMiddleware::class,
        'throttle' => \App\Middleware\ThrottleMiddleware::class,
    ],
    

    // 不好的做法 Route::middleware([\Unicode\Framework\Auth\Middleware\JwtMiddleware::class], function() { // ... });

    2. 组织中间件组

    根据应用场景组织中间件组:

    'groups' => [
        'api' => ['auth', 'throttle'],           // API 路由
        'web' => ['session', 'csrf'],             // Web 路由
        'admin' => ['auth', 'admin-check'],      // 管理后台
        'public' => ['cors'],                    // 公开 API
    ],
    

    3. 使用环境变量

    敏感信息(如 API Key)应该从环境变量读取:

    'custom' => [
        \App\Middleware\ApiKeyMiddleware::class => [
            'class' => \App\Middleware\ApiKeyMiddleware::class,
            'params' => [
                'apiKey' => getenv('API_KEY') ?: throw new \RuntimeException('API_KEY not set'),
            ],
        ],
    ],
    

    4. 合理使用单例模式

    只有在中间件是无状态的情况下才使用单例模式:

    // 无状态中间件,可以使用单例
    'singleton' => true,
    

    // 有状态中间件,不应该使用单例 'singleton' => false,

    5. 从配置文件读取参数

    对于需要在多个地方使用的配置值,应该从配置文件读取:

    // config/app.php
    return [
        'api' => [
            'key' => 'your-api-key',
            'timeout' => 30,
        ],
    ];
    

    // config/middleware.php return [ 'custom' => [ \App\Middleware\ApiMiddleware::class => [ 'class' => \App\Middleware\ApiMiddleware::class, 'params' => [ 'apiKey' => 'app.api.key', 'timeout' => 'app.api.timeout', ], ], ], ];

    相关文档

  • 路由系统 - 了解如何在路由中使用中间件
  • 认证 - 了解 JWT 认证中间件
  • 依赖注入 - 了解容器和依赖注入