[分享] 开源一个 PHP 框架 Awheel

项目地址: Awheel
当前版本: v1.5.0
PHP要求: >=5.4.0

介绍

基本功能: 路由/中间件/控制器/控制台/组件/配置加载/输入&输出.

框架最初是为了满足公司业务需求一步步造出来的, 但是从一开始就很独立的没有柔任何业务代码进去, 只保留了基本功能, 除此以外的功能全部需要自行扩展, 因为我觉得框架提供的功能越多学习和推广的成本就越高, 出现 Bug 的几率也就越高, 反倒不如都拆分成组件, 而且 Composer 那么好用, 扩展起来分分钟的事.

所以没有自带模板引擎, 需要使用组件功能自行扩展, 只需要继承并实现 Component 接口的 getAccessorregister 方法就可以使用, 目前我提供了 Smarty, Blade, SPA 三种模板扩展.

也没有自带 ORM 组件, 但是这里提供一个扩展 medoo-model 这是一个轻量级的数据库访问封装, 不管是名字还是功能我都非常喜欢😍, 也可自行扩展 Eloquent ORMDoctrine ORM 稍后我会给出一个 Eloquent ORM的封装扩展给喜欢的人使用

未来

1.4 之前一直是在公司内部使用和维护, 最近利用业余时间整理整理并开源到 Github 上了, 并且改名 Awheel, 然后注册awheel.org域名, 注册 Gayhub ORG

当时想破了头也找不到好名字, 后来偶然看到 wheel 这个单词, 前面加个 A 就拍板定下来了😁 非常贴切的名字有木有

公司目前使用两个 php 版本: 5.4 和 7.1, 所以目前是在 5.4的基础上开发出来的, 后来新项目都是7.1, 所以适配 7.1 但是框架层面并没有使用 >5.4 以后的新特性, 后面会逐步使用, 然后提高依赖版本.

开源后 1.5 版本把 Request 和 Response 替换为 Symfony/http-foundation 也算是风险转移吧, 坚信开源的力量, 所以核心会更稳定.

然后最重要的是需要把配套的文档和官网做出来, 努力中~

初衷

其实最初并没有造框架的打算, 因为现有的框架重量级的比如 Symfony, Laravel 轻量级的比如 Slim, Silex, Lumen 都能满足使用.

我个人是比较喜欢 Laravel 的, 所以有很深入的研究过它的源码, 的确是很优雅的框架, 抛开性能问题还是还完美的框架的, 性能并不是我选择(喜欢)一个框架的主要因素, 因为有太多的方式去提高性能了.

还是回到这个框架的来源吧, 最初公司决定做一个直播平台 亮了网, 这名字... 其实最初叫虎扑Tv, 后来因为一些原因改了名字和业务方向.

过程

当时由另外一位同事从另外一个项目复制并初始化了仓库, 这套代码比较简单, 只有基本的自动加载(扫描几个预定义好的目录), 路由是以映射的方式来, 如 /user/info 映射到 UserControllerinfo 方法, 这本身并没有什么问题, 不过当碰到 /live/10897 这样的 url 的时候, 就傻眼了, 尤其是 live 是后台可控的还有其他url并没有那么规则的时候... 当时是做特殊处理, 但是太痛苦.

所以当时想加一个自定义路由, 取代路径映射的方式, 当时完全完全没想过自己写路由组件, 我坚信要相信开源的力量, 然后随 Lumen 的大流用了 FastRoute 这是一个很简介但是全功能的路由组件.

选定类库后, 决定再把自动加载改为比较规范的 Composer, 都说程序员就是喜欢折腾..., 到这里已经相当于对整个项目大改了

改完路由, 用上 Composer, 顺势把 Monolog 也加上了, 在这之前使用 error_log 外面套了层皮..., 再然后加上命名空间, 明明都 php 5.4 了嘛对吧不能当5.2去写.

加命名空间没那么简单啊, 在那个时候路由已经做到了支持定义: GET, POST, PUT, DELETE, OPTIONS, HEAD 请求方式, 支持路由分组, 分组前缀, 分组命名空间, 所以上面提到的痛苦的事情已经不存在了, 可所有的文件要全部修改一遍来适配, 而且当时已经做了很多东西了, 这是其中一条 Gitlab 的提交记录 Showing 292 changed files with 27795 additions and 93 deletions

这里面当然也包括 Composer 引入的文件啦 😁

改完了这些东西, 整理下代码, 把之前的文件, 没有变动的都挪到一个叫 legace 目录下看下 gitlab 日志 Showing 175 changed files with 125 additions and 65 deletions 也是蛮多的, 真佩服自己的折腾劲啊, 当时这类一堆文件变动的提交非常多, 还好系统访问量还不大...

轮子来了

伴随着加路由还做了几件事情:

  • 第一件是改变了一个配置加载, 之前是 config_prod.php, config_test.php 根据不同环境使用不同的配置, 但是配置需要写4份, 我们有4个环境: 开发/测试/预发布/生成, 未来我能预测到它会和另外一个项目一样又几千行的配置, 所以参考(抄袭) Laravel 4.2 的方式做了目录切换, 低环境覆盖高环境配置的方式加载配置, 然后根据业务切分成多个文件, 所以配置看起来类似这样:

    .
    ├── app.php
    ├── chat.php
    ├── database.php
    ├── dev
    │   ├── app.php
    │   ├── chat.php
    │   ├── database.php
    │   ├── redis.php
    │   └── task.php
    ├── frontend.php
    ├── redis.php
    ├── stg
    │   ├── app.php
    │   ├── chat.php
    │   └── soa.php
    ├── task.php
    └── third.php
    
    > 这里为了演示我只保留了 prod 和 dev 还有 stg 的配置
    
    每个php 文件返回的都是数组, 框架提供 `configGet('filname.key')` 的方式来读取配置, 如`configGet('app.name')` 也算变相的实现了按需加载, 然后 `dev` 下的 `app.php` 会覆盖 最外层的 `app.php` 内容, 所以不需要变动的配置不需要写到 `dev/app.php` 内, 预发布和生产环境很多配置一直, 所以看到文件很少.
    
    > 参考: `https://github.com/awheel/awheel/tree/master/config`
    > Laravel 5.0 以后已经把配置改为 dotenv 方式了, 不过这并不合适我们.
    
  • 第二件是把数据读取抽象(封装)成 Request, 代替之前的 $_GET, $_POST 包皮, 然后控制器 echo 改为返回数据, 由框架封装成 Response, 到这里整个项目其实已经翻天覆地的变化了, 也有一个框架的雏形了, 所以当时依照 Composer 的设想: 类库和业务分类, 单独放了一个目录叫 light, 代表轻量级的意思, 然后这个名字伴随了我很久.
  • 第三件是用 Symfony/Console 封了了一个命令行, 用来跑定时和特殊任务.
  • 第四件是在路由和控制器之间加了一层东西, 这里我也把它加做中间件吧(大言不惭), 之前是通过在每次调用控制器前执行控制器定义的 before/after, 太局限
  • 第五件是用 Medoo 代替现有的数据库读写, 简单才能灵活.

到这里 light 框架已经可以称之为框架了, 虽然还是很简陋, 拥有的功能: 容器(单例), RESTful 路由, 路由分组, 中间件, 命令行, 控制器层, Request, Response, Model 层, View 层(Smarty, SPA)

到了这里还不算完善, 所以后面做新需求的时候提交日志一直是这样的: 添加/修改xxxx功能, 框架 xxx 优化, 又或者是补全注释, 代码整理这类.

总结

项目进度到达 1.2 后就把框架单独拎出来维护, 再然后随着做(我插手)的项目越来越多, 在公司又多了一些使用这个框架的项目, 然后框架也接近成熟核心已经稳定, 变动不是那么多了, 总结起来就是, 一开始痛苦的时候为啥不直接用 Laravel...

其实这也跟公司想使用自己控制的框架有关, 可以根据自己的需求来定制, 不过目前的成果是造了一个瑞士军刀, 使框架不那么局限再选择合适的扩展来支持一整个项目

撒花~~~

标签: php, composer, awheel, framework, light

添加新评论