Skip to content

中间件扩展系统

中间件扩展系统提供轻量级、可扩展的钩子机制,允许你在请求生命周期的不同阶段注入自定义逻辑。

快速开始

启用扩展系统

app/useApp.php 中配置:

php
'extensions' => [
    'enabled' => true,
],

插件自动注册中间件

在插件的 Index.php 中添加 registerMiddleware() 方法:

php
<?php
class Anon_Plugin_HelloWorld
{
    public static function registerMiddleware()
    {
        Anon_System_Extension::register(
            'customHeader',
            [self::class, 'handle'],
            10,
            [
                'hooks' => ['response.before_send'],
            ]
        );
    }
    
    public static function handle($data)
    {
        header('X-Powered-By: Anon Framework');
        return $data;
    }
}

当插件加载时,会自动调用 registerMiddleware() 方法注册中间件。

配置结构

扩展系统配置项

参数类型默认值说明
enabledbooltrue是否启用扩展系统

中间件注册方法

插件通过 registerMiddleware() 方法注册中间件,该方法在插件加载时自动调用。

php
class Anon_Plugin_MyPlugin
{
    public static function registerMiddleware()
    {
        // 注册多个中间件
        Anon_System_Extension::register(
            'myMiddleware',
            [self::class, 'handle'],
            10,
            ['hooks' => ['request.start']]
        );
    }
}

## Handler 处理器类型

支持三种处理器类型:

### 1. 匿名函数

```php
public static function registerMiddleware()
{
    Anon_System_Extension::register(
        'customHeader',
        function ($data) {
            header('X-Custom-Header: Value');
            return $data;
        },
        10,
        ['hooks' => ['response.before_send']]
    );
}

2. 类名(自动调用 handle 方法)

php
class RequestLogger
{
    public static function handle($data)
    {
        Anon_Debug::info('Request received', $_SERVER['REQUEST_URI']);
        return $data;
    }
}

// 在插件中注册
public static function registerMiddleware()
{
    Anon_System_Extension::register(
        'requestLogger',
        RequestLogger::class,
        5
    );
}

3. 类方法数组

php
public static function registerMiddleware()
{
    Anon_System_Extension::register(
        'corsHandler',
        [CorsMiddleware::class, 'handle'],
        1
    );
}

可用钩子

请求生命周期钩子

钩子名称触发时机说明
request.start请求开始时最早执行的钩子,适合 CORS、安全头等
request.pre_handle路由处理前适合权限验证、限流等
request.post_handle路由处理后适合数据修改、日志记录
request.end请求结束时适合性能分析、访问日志
response.before_send响应发送前适合修改响应头、内容压缩
*所有钩子监听所有钩子事件

使用示例

php
'options' => [
    'hooks' => [
        'request.start',      // 请求开始时
        'request.pre_handle', // 路由处理前
        'request.post_handle',// 路由处理后
        'request.end',        // 请求结束时
        'response.before_send',// 响应发送前
        '*',                   // 所有钩子
    ],
],

完整示例

示例 1:CORS 跨域中间件

php
class CorsMiddleware
{
    public static function handle($data)
    {
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
        header('Access-Control-Allow-Headers: Content-Type, Authorization');
        
        if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
            exit(0);
        }
        
        return $data;
    }
}

// 在插件中注册
class Anon_Plugin_Cors
{
    public static function registerMiddleware()
    {
        Anon_System_Extension::register(
            'cors',
            [CorsMiddleware::class, 'handle'],
            1,
            [
                'hooks' => ['request.start'],
            ]
        );
    }
}

示例 2:请求日志中间件

php
class RequestLogger
{
    private static $startTime;
    
    public static function start($data)
    {
        self::$startTime = microtime(true);
        
        Anon_Debug::info('Request started', [
            'method' => $_SERVER['REQUEST_METHOD'],
            'uri' => $_SERVER['REQUEST_URI'],
            'ip' => Anon_Common::GetClientIp(),
        ]);
        
        return $data;
    }
    
    public static function end($data)
    {
        $duration = (microtime(true) - self::$startTime) * 1000;
        
        Anon_Debug::info('Request completed', [
            'duration' => round($duration, 2) . 'ms',
            'memory' => memory_get_usage(true),
        ]);
        
        return $data;
    }
}

// 在插件中注册两个中间件
class Anon_Plugin_Logger
{
    public static function registerMiddleware()
    {
        // 请求开始日志
        Anon_System_Extension::register(
            'loggerStart',
            [RequestLogger::class, 'start'],
            1,
            [
                'hooks' => ['request.start'],
            ]
        );
        
        // 请求结束日志
        Anon_System_Extension::register(
            'loggerEnd',
            [RequestLogger::class, 'end'],
            100,
            [
                'hooks' => ['request.end'],
            ]
        );
    }
}

示例 3:性能分析中间件

php
class Anon_Plugin_Profiler
{
    public static function registerMiddleware()
    {
        Anon_System_Extension::register(
            'profiler',
            function ($data) {
                if (!isset($GLOBALS['__profiler_start'])) {
                    $GLOBALS['__profiler_start'] = microtime(true);
                }
                
                if (defined('ANON_DEBUG') && ANON_DEBUG) {
                    $start = $GLOBALS['__profiler_start'];
                    $duration = (microtime(true) - $start) * 1000;
                    
                    header('X-Request-Duration: ' . round($duration, 2) . 'ms');
                    header('X-Memory-Usage: ' . round(memory_get_peak_usage() / 1024 / 1024, 2) . 'MB');
                }
                
                return $data;
            },
            1,
            [
                'hooks' => ['*'],
            ]
        );
    }
}

示例 4:安全头中间件

php
class SecurityHeaders
{
    public static function handle($data)
    {
        header('X-Content-Type-Options: nosniff');
        header('X-Frame-Options: SAMEORIGIN');
        header('X-XSS-Protection: 1; mode=block');
        header('Referrer-Policy: strict-origin-when-cross-origin');
        
        return $data;
    }
}

class Anon_Plugin_Security
{
    public static function registerMiddleware()
    {
        Anon_System_Extension::register(
            'securityHeaders',
            [SecurityHeaders::class, 'handle'],
            5,
            [
                'hooks' => ['response.before_send'],
            ]
        );
    }
}

优先级控制

数字越小优先级越高,先执行:

php
class Anon_Plugin_PriorityExample
{
    public static function registerMiddleware()
    {
        // 第一个执行
        Anon_System_Extension::register(
            'first',
            fn($d) => dd('First'),
            1
        );
        
        // 第二个执行
        Anon_System_Extension::register(
            'second',
            fn($d) => dd('Second'),
            10
        );
        
        // 最后执行
        Anon_System_Extension::register(
            'third',
            fn($d) => dd('Third'),
            100
        );
    }
}

动态注册中间件

除了插件自动注册,也可以在代码中动态注册:

php
// 在 useCode.php 或插件的 init() 方法中
Anon_System_Extension::register(
    'myCustomMiddleware',
    function ($data) {
        // 自定义逻辑
        return $data;
    },
    10,
    [
        'hooks' => ['request.start'],
    ]
);

注销中间件

php
Anon_System_Extension::unregister('middlewareName');

检查中间件状态

php
// 检查是否已注册
$isRegistered = Anon_System_Extension::isRegistered('middlewareName');

// 获取所有中间件
$all = Anon_System_Extension::getAll();

最佳实践

1. 合理设置优先级

php
class Anon_Plugin_MiddlewareOrder
{
    public static function registerMiddleware()
    {
        // 安全相关优先执行
        Anon_System_Extension::register('security', [...], 1);
        Anon_System_Extension::register('auth', [...], 5);
        
        // 日志中间件
        Anon_System_Extension::register('logging', [...], 10);
        
        // 低优先级:分析等
        Anon_System_Extension::register('analytics', [...], 100);
    }
}

2. 单一职责

每个中间件只负责一个功能:

php
class Anon_Plugin_SeparateMiddleware
{
    public static function registerMiddleware()
    {
        // ✅ 正确:分开独立中间件
        Anon_System_Extension::register('cors', [...]);
        Anon_System_Extension::register('securityHeaders', [...]);
        Anon_System_Extension::register('rateLimit', [...]);
    }
}

// ❌ 错误:一个大而全的中间件
class BadAllInOne
{
    public static function handle($data)
    {
        // CORS + 安全头 + 限流 + 日志...
    }
}

3. 错误处理

中间件内部应该捕获异常,避免影响其他中间件:

php
class SafeMiddleware
{
    public static function handle($data)
    {
        try {
            // 业务逻辑
            return $data;
        } catch (Throwable $e) {
            Anon_Debug::error('Middleware error', ['error' => $e->getMessage()]);
            return $data;
        }
    }
}

class Anon_Plugin_SafeHandler
{
    public static function registerMiddleware()
    {
        Anon_System_Extension::register(
            'safeMiddleware',
            [SafeMiddleware::class, 'handle']
        );
    }
}

4. 性能考虑

避免在高优先级中间件中执行耗时操作:

php
class Anon_Plugin_AsyncAnalytics
{
    public static function registerMiddleware()
    {
        // ✅ 正确:异步或延迟处理
        Anon_System_Extension::register(
            'analytics',
            function ($data) {
                // 记录到队列,稍后处理
                Queue::push('analytics', $data);
                return $data;
            },
            100  // 低优先级
        );
    }
}

与插件系统的关系

中间件扩展系统是插件系统的一部分,由插件自动注册和管理。

特性说明
注册方式插件的 registerMiddleware() 方法自动调用
管理方式由插件系统统一管理
配置位置无需手动配置,代码中注册
执行顺序优先级控制(数字越小越先)
适用场景请求拦截、修改响应、日志记录等

相关文档

Released under the MIT License.