资讯专栏INFORMATION COLUMN

php管道模式手测

zzir / 1153人阅读

摘要:所以管道模式大致需要三个角色管道,阀门和载荷流水。模仿返回处理后的结果输出结语上面的代码并没有达到中间件的真正执行部分,例子中只是用到了管道模式的一部分。

一直在用Laravel框架,很喜欢laravel框架的中间件。在请求到结果之前,如果我们想要对路由或请求进行额外的处理,简单的加个Midleware中间件就行了,很简单,很方便是不是。
最近几天看了下它的中间件的实现方式,把自己的心得感悟写下来分享给大家。

了解管道模式

laravel的中间件用的是管道模式,我们先知道管道模式是什么:

所谓管道(Pipeline)设计模式就是将会数据传递到一个任务序列中,管道扮演者流水线的角色,数据在这里被处理然后传递到下一个步骤

管道,顾名思义,就是一个长长的流水管道,只不过加了许多阀门。所以管道模式大致需要三个角色:管道,阀门和载荷(流水)。如下图:

管道模式UML模型图

开始代码之前,我们必须先了解管道模式的模型图

简单的实现

根据上面的模型图,我们来实现自己所理解的管道模式的代码:

/**
 * PipelineBuilder 接口 即管道
 * @method pipe 存入多个阀门
 * @method process 输出
 */
interface PipelineBuilderInterface
{
    public function __construct($payload);
    public function pipe(StageBuilderInterface $stage);
    public function process();
}
// 具体的管道类
class Pipeline implements PipelineBuilderInterface
{
    protected $payload;
    protected $pipes = [];
    public function __construct($payload)
    {
        $this->payload = $payload;
    }

    public function pipe(StageBuilderInterface $stage)
    {
        $this->pipes[] = $stage;

        return $this;
    }

    public function process()
    {
        foreach ($this->pipes as $pipe) {
            call_user_func([$pipe, "handle"], $this->payload);
        }
    }
}
// 阀门接口
interface StageBuilderInterface
{
    public function handle($payload);
}
// 具体的阀门类
class StageOneBuilder implements StageBuilderInterface
{
    public function handle($payload)
    {
        echo $payload ." 真是个";
    }
}
// 具体的阀门类
class StageTwoBuilder implements StageBuilderInterface
{
    public function handle($payload)
    {
        echo "帅气的男人";
    }
}
// 输出:我真是个帅气的男人
$pipeline = new Pipeline("我");
$pipeline->pipe(new StageOneBuilder)
    ->pipe(new StageTwoBuilder)
    ->process();
底层源码

先来看看它的底层源码:

return (new Pipeline($this->container))
            ->send($request)
            ->through($middleware)
            ->then(function ($request) use ($route) {
                return $this->prepareResponse(
                    $request, $route->run()
                );
            });

上面的代码是处理request请求的一部分代码,send()获取待处理的数据,through()获取中间件,then()传递闭包函数。
基本上,使用laravel pipelines你可以将一个实例对象(object)在多个类之间传递,就像流水顺着管道依次流淌一般,最终呢,层层传递,你就得到了从头至尾一系列执行操作的“最终”结果。

模仿laravel pipeline
interface PipelineInterface
{
    public function send($traveler);
    public function through($stops);
    public function via($method);
    public function process();
}

interface StageInterface
{
    public function handle($payload);
}

class StageOne implements StageInterface
{
    public function handle($payload) 
    {
        echo $payload . " am really an ";
    }
} 

class StageTwo implements StageInterface
{
    public function handle($payload) {
        echo "awesome man";
    }
} 

class Pipe implements PipelineInterface
{
    protected $container;
    protected $passable;
    protected $pipes = [];
    protected $via = "handle";

    public function __construct($container)
    {
        $this->container = $container;
    }

    public function send($passable)
    {
        $this->passable = $passable;

        return $this;
    }

    public function through($pipes)
    {
        $this->pipes = is_array($pipes) ? $pipes : func_get_args();

        return $this;
    }

    public function via($method)
    {
        $this->via = $method;

        return $this;
    }

    public function process()
    {
        foreach ($this->pipes as $pipe) {
            // 返回处理后的结果
            $this->passable = call_user_func([$pipe, $this->via], $this->passable);
        }
    }
}
$container = "a";
$payload = "wa";
$pipe = new Pipe($container);

// 输出:I am really an awesome man
$pipe->send($payload)->through([(new StageOne), (new StageTwo)])->process();
结语

上面的代码并没有达到laravel中间件的真正执行部分,例子中只是用到了管道模式的一部分。像then()方法中还用了array_reducearray_reverse函数来处理请求,这一部分有时间会进一步研究。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/31352.html

相关文章

  • 从0到1优雅的实现PHP多进程管理

    摘要:目的综上所述,我的目标就是实现基于模式实现的多进程管理工具。备注下文中,父进程统称为子进程统称为。最后我们通过下图来简单的总结和描述这个多进程实现的过程控制上面实现了多进程和多进程的常驻内存,那如何去管理呢答案多进程通信。 _ | | _ __ __ _ _ __...

    lakeside 评论0 收藏0
  • PHP 命令行方式实现异步多进程模式的任务处理

    摘要:定义任务处理方法。读取来自命令行的参数,开始执行任务。该函数有两个参数和,是引用类型,用来存储子进程的状态,有两个可选常量,分别表示不等待子进程结束立即返回和等待子进程结束。 用PHP来实现异步任务一直是个难题,现有的解决方案中:PHP知名的异步框架有 swoole 和 Workerman,但都是无法在 web 环境中直接使用的,即便强行搭建 web 环境,异步调用也是使用多进程模式实...

    Invoker 评论0 收藏0
  • 【云端App自动化测试系列一】如何做投资回报率高的自动化测试

    摘要:通过不断标记,逐渐形成用户期望的基线,让自动测试逐步稳定下来。 场景1线上App出现一个严重bug急需修复 => 开发迅速定位到bug并fix之 => 移交测试 => Tester将之前写的上百个用例进行回归,以确认修改没有引入新的bug,Tester加班加点跑完所有用例,新版本终于上线了。 场景2某公司搭建了自动化测试平台用于App自动化测试,然而App几乎每周都会发布新版本,不断出...

    未东兴 评论0 收藏0
  • PHP 进程的实现与管理

    摘要:运行模式实现进程前,需了解常见的的运行模式通用网关接口模式模式命令行模式模块模式作为服务器模块而进程则是使用命令行模式运行的基本实现中提供了一个扩展,可以利用操作系统的调用来实现多进程。 应用场景 一些耗时任务: 大数据表分表后的统计信息功能 分批发送短信或邮件功能 其他可分目标的任务功能(很多种) 所以我们就需要一个常驻内存的任务管理工具,为了保证实时性,一方面我们让它一直执行任...

    MockingBird 评论0 收藏0
  • PHP 进程的实现与管理

    摘要:运行模式实现进程前,需了解常见的的运行模式通用网关接口模式模式命令行模式模块模式作为服务器模块而进程则是使用命令行模式运行的基本实现中提供了一个扩展,可以利用操作系统的调用来实现多进程。 应用场景 一些耗时任务: 大数据表分表后的统计信息功能 分批发送短信或邮件功能 其他可分目标的任务功能(很多种) 所以我们就需要一个常驻内存的任务管理工具,为了保证实时性,一方面我们让它一直执行任...

    testbird 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<