PHP 管道模式实现中间件

wen PHP项目 2

本文目录导读:

PHP 管道模式实现中间件

  1. 核心管道模式实现
  2. 中间件基础设施
  3. 具体中间件示例
  4. 使用示例
  5. 高级特性:中间件组和配置
  6. 运行示例

我来为你实现PHP管道模式中间件,这是一个优雅的中间件处理方案:

核心管道模式实现

<?php
declare(strict_types=1);
namespace App\Pipeline;
use Closure;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
/**
 * 管道模式中间件处理器
 * 将多个中间件按顺序组织成管道,请求依次通过每个中间件
 */
class Pipeline
{
    /**
     * 中间件集合
     * @var array
     */
    protected $middlewares = [];
    /**
     * 容器实例(用于解析中间件)
     * @var mixed
     */
    protected $container;
    /**
     * 最终的处理逻辑
     * @var Closure
     */
    protected $destination;
    /**
     * 请求实例
     * @var mixed
     */
    protected $request;
    /**
     * 是否已推送请求对象
     * @var bool
     */
    protected $hasPushedRequest = false;
    public function __construct($container = null)
    {
        $this->container = $container;
    }
    /**
     * 设置请求对象
     * @param $request
     * @return $this
     */
    public function withRequest($request): self
    {
        $this->request = $request;
        return $this;
    }
    /**
     * 添加中间件
     * @param array|string|callable $middleware
     * @return $this
     */
    public function pipe($middleware): self
    {
        if (is_array($middleware)) {
            $this->middlewares = array_merge($this->middlewares, $middleware);
        } else {
            $this->middlewares[] = $middleware;
        }
        return $this;
    }
    /**
     * 添加多个中间件
     * @param array $middlewares
     * @return $this
     */
    public function through(array $middlewares): self
    {
        $this->middlewares = $middlewares;
        return $this;
    }
    /**
     * 设置最终处理逻辑
     * @param Closure $destination
     * @return $this
     */
    public function then(Closure $destination): self
    {
        $this->destination = $destination;
        return $this;
    }
    /**
     * 执行管道
     * @param mixed $passable
     * @return mixed
     */
    public function process($passable = null)
    {
        // 如果没有推送请求,使用传入的passable
        if (!$this->hasPushedRequest) {
            $this->request = $passable;
        }
        return ($this->getPipeline())($this->request);
    }
    /**
     * 构建管道执行链
     * @return Closure
     */
    protected function getPipeline(): Closure
    {
        // 默认的最终处理函数
        $defaultDestination = function ($request) {
            // 如果没有设置destination,则直接返回request
            if ($this->destination) {
                return call_user_func($this->destination, $request);
            }
            return $request;
        };
        // 从后往前构建调用链
        return array_reduce(
            array_reverse($this->middlewares),
            $this->carry(),
            $defaultDestination
        );
    }
    /**
     * 创建中间件包装逻辑
     * @return Closure
     */
    protected function carry(): Closure
    {
        return function (Closure $next, $middleware): Closure {
            return function ($request) use ($next, $middleware) {
                // 解析中间件(支持字符串类名或数组)
                [$middleware, $parameters] = $this->parseMiddleware($middleware);
                if ($middleware instanceof Closure) {
                    // Closure中间件
                    return $middleware($request, $next);
                }
                if (is_string($middleware)) {
                    // 类名中间件
                    $instance = $this->resolveMiddleware($middleware);
                    $response = method_exists($instance, 'handle')
                        ? $instance->handle($request, $next)
                        : $instance($request, $next);
                    return $response;
                }
                // 可调用的对象
                return call_user_func_array($middleware, array_merge([$request, $next], $parameters));
            };
        };
    }
    /**
     * 解析中间件配置
     * @param mixed $middleware
     * @return array
     */
    protected function parseMiddleware($middleware): array
    {
        $parameters = [];
        if (is_array($middleware)) {
            $parameters = $middleware;
            $middleware = array_shift($parameters);
        }
        return [$middleware, $parameters];
    }
    /**
     * 解析中间件实例
     * @param string $middleware
     * @return mixed
     */
    protected function resolveMiddleware(string $middleware)
    {
        if ($this->container && method_exists($this->container, 'make')) {
            return $this->container->make($middleware);
        }
        return new $middleware();
    }
}

中间件基础设施

<?php
namespace App\Pipeline;
/**
 * 中间件接口
 */
interface MiddlewareInterface
{
    /**
     * 处理请求
     * @param mixed $request
     * @param callable $next
     * @return mixed
     */
    public function handle($request, callable $next);
}
/**
 * 抽象中间件基类
 */
abstract class AbstractMiddleware implements MiddlewareInterface
{
    /**
     * 中间件参数
     * @var array
     */
    protected $parameters = [];
    public function __construct(...$parameters)
    {
        $this->parameters = $parameters;
    }
    /**
     * 获取中间件参数
     * @return array
     */
    public function getParameters(): array
    {
        return $this->parameters;
    }
}
/**
 * 闭包中间件辅助类
 */
class Middleware
{
    /**
     * 创建一个闭包中间件
     * @param callable $callback
     * @return Closure
     */
    public static function create(callable $callback): \Closure
    {
        return function ($request, $next) use ($callback) {
            return $callback($request, $next);
        };
    }
}

具体中间件示例

<?php
namespace App\Middlewares;
use App\Pipeline\AbstractMiddleware;
use App\Pipeline\MiddlewareInterface;
/**
 * 认证中间件
 */
class AuthMiddleware extends AbstractMiddleware
{
    public function handle($request, callable $next)
    {
        // 认证逻辑
        if (empty($request['user'])) {
            throw new \Exception('未认证用户');
        }
        // 可以修改请求对象
        $request['authenticated'] = true;
        // 调用下一个中间件
        return $next($request);
    }
}
/**
 * 日志中间件
 */
class LogMiddleware extends AbstractMiddleware
{
    public function handle($request, callable $next)
    {
        // 前置处理
        $startTime = microtime(true);
        echo "开始处理请求: " . ($request['path'] ?? '') . "\n";
        // 调用下一个中间件
        $response = $next($request);
        // 后置处理
        $duration = microtime(true) - $startTime;
        echo "请求处理完成,耗时: {$duration}秒\n";
        return $response;
    }
}
/**
 * 缓存中间件
 */
class CacheMiddleware extends AbstractMiddleware
{
    public function handle($request, callable $next)
    {
        echo "尝试读取缓存...\n";
        // 模拟读取缓存
        $cacheKey = md5($request['path'] ?? '');
        $response = $next($request);
        echo "写入缓存...\n";
        return $response;
    }
}
/**
 * CORS中间件
 */
class CorsMiddleware extends AbstractMiddleware
{
    public function handle($request, callable $next)
    {
        // 添加CORS头
        $request['headers']['Access-Control-Allow-Origin'] = '*';
        echo "处理CORS请求...\n";
        return $next($request);
    }
}

使用示例

<?php
// 使用管道模式
require_once 'Pipeline.php';
require_once 'MiddlewareInterface.php';
// 创建管道实例
$pipeline = new Pipeline();
// 设置请求
$request = [
    'path' => '/api/users',
    'method' => 'GET',
    'user' => ['id' => 1, 'name' => '张三'],
];
// 添加中间件
$pipeline->pipe([
    new \App\Middlewares\AuthMiddleware(),
    new \App\Middlewares\LogMiddleware(),
    new \App\Middlewares\CacheMiddleware(),
    new \App\Middlewares\CorsMiddleware(),
]);
// 添加闭包中间件
$pipeline->pipe(function ($request, $next) {
    echo "自定义中间件处理...\n";
    $request['processed'] = true;
    return $next($request);
});
// 设置最终处理逻辑并执行
$response = $pipeline
    ->withRequest($request)
    ->then(function ($request) {
        echo "最终处理逻辑执行...\n";
        echo "处理路径: {$request['path']}\n";
        return [
            'status' => 200,
            'data' => ['message' => '处理成功'],
            'request' => $request,
        ];
    })
    ->process();
print_r($response);

高级特性:中间件组和配置

<?php
namespace App\Pipeline;
/**
 * 管道管理器(支持中间件组)
 */
class PipelineManager
{
    /**
     * 中间件组定义
     * @var array
     */
    protected $middlewareGroups = [];
    /**
     * 单个中间件定义
     * @var array
     */
    protected $middlewares = [];
    /**
     * 已注册的管道
     * @var array
     */
    protected $pipelines = [];
    /**
     * 注册中间件组
     * @param string $name
     * @param array $middlewares
     * @return void
     */
    public function group(string $name, array $middlewares): void
    {
        $this->middlewareGroups[$name] = $middlewares;
    }
    /**
     * 注册单个中间件
     * @param string $name
     * @param string|callable $middleware
     * @return void
     */
    public function alias(string $name, $middleware): void
    {
        $this->middlewares[$name] = $middleware;
    }
    /**
     * 创建管道
     * @return Pipeline
     */
    public function make(): Pipeline
    {
        return new Pipeline();
    }
    /**
     * 通过配置创建管道
     * @param array $config
     * @return Pipeline
     */
    public function fromConfig(array $config): Pipeline
    {
        $pipeline = $this->make();
        foreach ($config as $name) {
            if (isset($this->middlewareGroups[$name])) {
                // 添加中间件组
                foreach ($this->middlewareGroups[$name] as $middleware) {
                    $pipeline->pipe($middleware);
                }
            } elseif (isset($this->middlewares[$name])) {
                // 添加单个中间件
                $pipeline->pipe($this->middlewares[$name]);
            } else {
                // 直接添加类名
                $pipeline->pipe($name);
            }
        }
        return $pipeline;
    }
}

运行示例

<?php
// 测试管道模式
$manager = new App\Pipeline\PipelineManager();
// 注册中间件组
$manager->group('api', [
    App\Middlewares\AuthMiddleware::class,
    App\Middlewares\LogMiddleware::class,
]);
$manager->group('web', [
    App\Middlewares\CorsMiddleware::class,
    App\Middlewares\CacheMiddleware::class,
]);
// 创建管道
$pipeline = $manager->make();
// 使用中间件组和单个中间件
$pipeline->pipe('api');  // 使用API中间件组
$pipeline->pipe(App\Middlewares\CorsMiddleware::class);  // 直接使用类名
// 或者通过配置创建
$pipeline2 = $manager->fromConfig(['api']);
// 执行管道
$response = $pipeline
    ->withRequest(['path' => '/api/data'])
    ->then(function ($request) {
        echo "最终处理完成\n";
        return ['success' => true];
    })
    ->process();
echo "\n执行结果:\n";
print_r($response);

这个管道模式实现提供了:

  1. 灵活的中间件注册方式:支持闭包、类名、对象数组
  2. 链式调用:流畅的API设计
  3. 中间件分组:支持批量添加中间件
  4. 参数传递:支持给中间件传递参数
  5. 前后置处理:支持在调用下一个中间件前后执行逻辑
  6. 容器集成:支持依赖注入容器解析中间件

这种实现模式广泛应用于框架中,如Laravel的路由中间件系统、PSR-15规范等。

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