|
越是简单的东西越是好的,最近在研究PHP的各种框架, 有yaf, phalcon, CI框架,
1、其中Yaf 是PHP国内第一人写的纯C框架, 核心在于路由部分与类的加载功能, 可惜没有数据库ORM操作,极轻量级。 2、phalcon是国外非常火的一个框架,也是一个纯C框架,非常重量级,过于臃肿,文档不太完善。 3、CI也是一个市场占有率非常高的框架,是纯PHP框架,适度轻量级,文档丰富,性能不及 Yaf 的 1/3。 依照上面的原理,我对项目进行了优化升级,在此基础上开发了一个新的轻量级组合框架,命名为 SuperCI: 1、考虑之前做的项目都是CI框架,如果全部推翻,将会有超级多的东西需要修改,所以我将CI引擎替换,但是SuperCI对外提供的调用方式不变, 2、首先我将CI框架的路由部分抽取出来, 替换成Yaf。 3、然后将CI的数据库ORM操作底层引擎替换成Phalcon, 然而这并不是一个全部的Phalcon, 而是将Phalcon所有其它模块全部删除,仅保留DB操作部分,重新编译之后生成的ORM引擎,替换到CI的数据库底层操作,相当于给五菱宏光装上了悍马的发动机,数据库操作性能能提升2倍。 4、代码模块分离,并加入自己写的模块、类库、配置加载类。 5、加入自己的日志记录类 6、替换 PHP 5 到 PHP 7 , 开启代码缓存opcache。 通过以上工作,整体运行性能提升10倍, 线上运行半年,稳定可靠,线上服务器使用减少2/3,框架极度轻量级, 越是简单的东西越是好的。 框架介绍 运行环境: PHP 7 / PHP 5, opcache 依赖扩展: yaf.so , phalcon.so 注意:官网的phalcon, 在PHP7下,由于phalcon的一个数据库绑定导致的 opcache 会和 phalcon冲突,导致两个不能同时用, 两者都是提升性能的利器,尤其 Opcache,能提升1倍性能, 请用我提供的源码中的tool/phalcon的源码重新编译生成 phalcon.so,这里的源码去掉了phalcon除了数据库DB操作以外的所有功能,而且解决了与opcache冲突的问题。 如果是PHP5需要到phalcon官网去下载扩展。 配置文件: superci/conf/application.ini 我们看看路由配置部分: routes.regex.type="regex" routes.regex.match="#^/list/([^/]*)/([^/]*)#" routes.regex.route.controller=Index routes.regex.route.action=action routes.regex.map.1=name routes.regex.map.2=value routes.simple.type="simple" routes.simple.controller=c routes.simple.action=m routes.simple.module=o 控制器有参数c决定,动作有 m 决定。比如如下demo Url: http://localhost/index.php?c=test&m=manUser&name=bigbox&sex=%E7%94%B7&age=51 程序将被路由到superci/application/controllers/Test.php文件的 TestController::manUserAction方法,其它路由细节参考Yaf框架 class TestController extends Core_Controller { public function manUserAction() { } } 入口 superci/index.php 定义目录,加载Yaf_Application $app = new Yaf_Application(APPPATH . "/conf/application.ini"); $app->bootstrap()->run(); Bootstrap启动过程 文件位于superci/application/bootstrap.php, Yaf的初始化逻辑, 每个_init开头的函数都会被顺序执行,用户也可以在这里添加自己的初始化逻辑 public function _initConfig() { $config = Yaf_Application::app()->getConfig(); Yaf_Registry::set("config", $config); } public function _initRoute(Yaf_Dispatcher $dispatcher) { $router = Yaf_Dispatcher::getInstance()->getRouter(); $router->addConfig(Yaf_Registry::get("config")->routes); } public function _initCommon(Yaf_Dispatcher $dispatcher) { //注册插件 require_once(BASEPATH . "/Request.php"); require_once(BASEPATH . "/Loader.php"); require_once(BASEPATH . "/Logger.php"); } public function _initRequest(Yaf_Dispatcher $dispatcher) { //初始化请求 $dispatcher->setRequest(new Request()); } public function _initPlugins(Yaf_Dispatcher $dispatcher) { //注册插件 $dispatcher->registerPlugin(new FilterPlugin()); } public function _initException() { //设置异常回调 include_once(BASEPATH . "/Common.php"); set_error_handler('_exception_handler'); } 过滤器插件 在bootstrap.php 中, 有注册插件 _initPlugins ,我们注册了一个过滤器FilterPlugin,插件定义了6个Hook。 触发顺序 名称 触发时机 说明 1 routerStartup 在路由之前触发 这个是7个事件中, 最早的一个. 但是一些全局自定的工作, 还是应该放在Bootstrap中去完成 2 routerShutdown 路由结束之后触发 此时路由一定正确完成, 否则这个事件不会触发 3 dispatchLoopStartup 分发循环开始之前被触发 4 preDispatch 分发之前触发 如果在一个请求处理过程中, 发生了forward, 则这个事件会被触发多次 5 postDispatch 分发结束之后触发 此时动作已经执行结束, 视图也已经渲染完成. 和preDispatch类似, 此事件也可能触发多次 6 dispatchLoopShutdown 分发循环结束之后触发 此时表示所有的业务逻辑都已经运行完成, 但是响应还没有发送 我们将验签的过程放在路由之前,如果进来的请求,验签失败,则直接报错。 class FilterPlugin extends Yaf_Plugin_Abstract { var $params; //路由之前调用 public function routerStartUp ( Yaf_Request_Abstract $request , Yaf_Response_Abstract $response) { $this->params = & $request->getParams(); $this->_auth(); } //验签过程 protected function _auth() { //$this->response_error(1, "验签失败"); } } 控制层 所有控制器位于:superci/application/controllers 目录,所有控制器继承自Core_Controller方法,里面主要获取GET/POST参数,以及返回数据的处理,Core_Controller继承自 Yaf_Controller_Abstract, init方法会被自动调用,更多细节参考 Yaf 框架控制器。 class TestController extends Core_Controller { public function init() { parent::init(); $this->example_model = Loader::model('ExampleModel'); } public function manUserAction() { $this->logger->LogInfo("manUser: " . createLinkstringUrlencode($this->params)); //数据返回 $res = array(); $res['uid'] = $this->example_model->insert_data($this->params['name'], $this->params['sex'], $this->params['age']); ... $this->response_success($res); } } 模型层 所有的Model层位于 superci/application/models目录, 通过 $this->example_model = Loader::model('ExampleModel'); 加载模型 VIEW层 视图层参考yaf视图渲染那部分, 我没有写案例。 APP应用配置 所有配置位于 superci/application/config目录 通过 $config = Loader::config('config'); 参数为 config里面文件名称, 比如上面加载的就是 config.php | |