中间件配置
最后更新: 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',
],
],
],
];