资讯专栏INFORMATION COLUMN

模仿KOA,用php来写一个极简的开发框架

LiangJ / 3269人阅读

摘要:欢迎感兴趣的去了解和提出建议,也欢迎地址期望用法先来看看我要怎么用这个框架基本上跟类似,先一个对象,使用方法添加中间件,支持闭包或外部文件。

nodejs的koa可以说是非常受欢迎的,特别是其“洋葱模型”应该用过的人印象都比较深,下面就尝试用php来实现一个。

注:本文是PHPec框架的最原始思路版本。PHPec是在此基础上完善编写出来的一个极简的轻量级开发框架,除了提供中间件调用模式外,同时提供了常见的自动路由功能,目前 已在github上发布了最初版本。欢迎感兴趣的去了解和提出建议,也欢迎star. 地址:https://github.com/tim1020/PHPec
期望用法

先来看看我要怎么用“这个框架”?

require "app.php";
$app = new App();

$app -> use(function($ctx){
    $ctx -> body.= ">m1";
    $ctx -> next();
    $ctx -> body .= ">m1 end";
});

$app -> use("Middleware2");

$app -> run();

基本上跟koa类似,先new一个app对象,使用use方法添加中间件,支持闭包或外部文件。

$ctx支持注入所需的各种参数,方便各中间件共用。

完整代码
//app.php
class App{
    private $m = array();
    private $ctx = array();
    function next(){
        $f = $this -> c -> current();
        if(!$f) return;
        $this -> c -> next();
        $f($this);
    }
    function run(){
        $this -> c = $this -> _gen();
        $this -> next();
    }
    private function _gen(){
        foreach($this -> m as $v){
            yield $v;
        }
    }
    private function _add($m){
        if(!empty($this->m) && $this -> m[count($this->m) -1] === false) return;
        if(!$m){
            $this -> m[] = false;
        }elseif(($m instanceof Closure)){
            $this -> m[] = $m;
        }else{
            $m = $this -> _load($m);
            if(!function_exists($m)){
               throw new Exception("middleware error");
            }
            else $this -> m[] = $m;
        }
    }
    //处理文件加载,返回执行函数(如需要,可加入命名空间处理)
    private function _load($m){
        $f = "./middleware/".$m.".php";
        if(!file_exists($f)) throw new Exception("middleware error");
        require $f;
        return $m;
    }
    function __call($m,$v){
        if("use" == $m){
            $p = isset($v[0]) ? $v[0] : "";
            $this -> _add($p);
        }else{
            throw new Exception("method not exists");
        }
    }
    function __set($k,$v){
        $this -> ctx[$k] = $v;
    }
    function __get($k){
        return isset($this -> ctx[$k]) ? $this -> ctx[$k] : NULL;
    }
}

没错,这就是全部的代码。

代码讲解 use方法

use可以加入闭包或外部文件,且php5不支持use作为方法名,这里用__call来实现重载,当调用use时由__call来调用私有的_add方法。

_add对传进来的参数作判断,如果是字符串,表示外部加载,则去判断文件和处理函数是否存在和有效,然后将处理函数加到中间件队列。

这里面如果use()传递空参数,表示忽略后面的中间件。
run方法

添加完中间件后,执行$app -> run()方法运行,来看看是怎么执行的:

调用私有的_gen来生成一个生成器,该生成器可以迭代返回队列中的中间件处理函数。

调用next方法执行下一个中间件(这里即第一个入口)

2.1 调用生成器的current方法获得当前的处理函数

2.2 执行该函数(传递$this作为参数,即$ctx),并调用生成器的next方法后移到下一个处理函数

直到生成器没有返回时结束。

中间件中需调用$ctx-> next()将控制权交到下一个中间件,从而迭代完所有的中间件。
__get和__set方法

提供了__get和__set方法,是方便在中间件中使用$ctx直接设置和访问未经定义的值。如:

$ctx -> body = "hello";
$ctx -> tplName = "a.tpl";
That is all

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

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

相关文章

  • 一个简的基于swoole常驻内存框架

    摘要:于是打算做一个拥有非常好用的路由和又非常简单的框架。但也有一些自己的特色,例如支持自动化缓存自动化读写刷新保持与数据库同步,对外使用无感知。例如协议服务器地址远程的类不设置默认为当前类名其中类在框架里。 背景 在用过laravel框架,发现它的路由和数据库ORM确实非常好用,但是整体确实有点慢,执行到控制器大于需要耗时60ms左右。于是打算做一个拥有非常好用的路由和orm又非常简单的框...

    Steve_Wang_ 评论0 收藏0
  • 简的Restful框架推荐->Resty

    摘要:源码链接开发文档如果你还不是很了解,或者认为只是一种规范不具有实际意义,推荐一篇两年前的文章设计最佳实践和的一篇极其理论的文章理解本真的架构风格虽然有点老,介绍的也很简单,大家权当了解,的更多好处,还请拥有一样的的简洁设计,使用更简单的框架 源码链接:Resty 开发文档 如果你还不是很了解restful,或者认为restful只是一种规范不具有实际意义,推荐一篇osc两年...

    JerryC 评论0 收藏0
  • React组件设计实践总结05 - 状态管理

    摘要:要求通过要求数据变更函数使用装饰或放在函数中,目的就是让状态的变更根据可预测性单向数据流。同一份数据需要响应到多个视图,且被多个视图进行变更需要维护全局状态,并在他们变动时响应到视图数据流变得复杂,组件本身已经无法驾驭。今天是 520,这是本系列最后一篇文章,主要涵盖 React 状态管理的相关方案。 前几篇文章在掘金首发基本石沉大海, 没什么阅读量. 可能是文章篇幅太长了?掘金值太低了? ...

    ideaa 评论0 收藏0
  • VuePress来搭建一个简的静态网站

    摘要:馨客栈前端导航享受的开发体验,在中使用组件,同时可以使用来开发自定义主题。馨客栈每日分享为每个页面预渲染生成静态的,同时在页面被加载的时候,将作为运行。 VuePress学习 全局安装前我们需要Git和node这两个软件,关于怎么安装可以我之前hexo的视频教程 假如这两个都没有安装好,那么下面就不需要看了哈,栈友们 全局安装 首先我们先全局安装一下 npm stall -g vuep...

    BetaRabbit 评论0 收藏0
  • VuePress来搭建一个简的静态网站

    摘要:馨客栈前端导航享受的开发体验,在中使用组件,同时可以使用来开发自定义主题。馨客栈每日分享为每个页面预渲染生成静态的,同时在页面被加载的时候,将作为运行。 VuePress学习 全局安装前我们需要Git和node这两个软件,关于怎么安装可以我之前hexo的视频教程 假如这两个都没有安装好,那么下面就不需要看了哈,栈友们 全局安装 首先我们先全局安装一下 npm stall -g vuep...

    charles_paul 评论0 收藏0

发表评论

0条评论

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