本文目录导读:

我来为你实现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);
这个管道模式实现提供了:
- 灵活的中间件注册方式:支持闭包、类名、对象数组
- 链式调用:流畅的API设计
- 中间件分组:支持批量添加中间件
- 参数传递:支持给中间件传递参数
- 前后置处理:支持在调用下一个中间件前后执行逻辑
- 容器集成:支持依赖注入容器解析中间件
这种实现模式广泛应用于框架中,如Laravel的路由中间件系统、PSR-15规范等。