从0开始构建一个属于你自己的PHP框架

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 Tair(兼容Redis),内存型 2GB
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介:

如何构建一个自己的PHP框架

为什么我们要去构建一个自己的PHP框架?可能绝大多数的人都会说“市面上已经那么多的框架了,还造什么轮子?”。我的观点“造轮子不是目的,造轮子的过程中汲取到知识才是目的”。

从0开始构建一个属于你自己的PHP框架

那怎样才能构建一个自己的PHP框架呢?大致流程如下:


 
 
  1. 入口文件 ----> 注册自加载函数 
  2.         ----> 注册错误(和异常)处理函数 
  3.         ----> 加载配置文件 
  4.         ----> 请求 
  5.         ----> 路由  
  6.         ---->(控制器 <----> 数据模型) 
  7.         ----> 响应 
  8.         ----> json 
  9.         ----> 视图渲染数据 

除此之外我们还需要单元测试、nosql支持、接口文档支持、一些辅助脚本等。最终我的框架目录如下:

框架目录一览


 
 
  1. app                             [PHP应用目录] 
  2. ├── demo                        [模块目录] 
  3. │   ├── controllers             [控制器目录] 
  4. │   │      └── Index.php        [默认控制器文件,输出json数据] 
  5. │   ├── logics                  [逻辑层,主要写业务逻辑的地方] 
  6. │   │   ├── exceptions          [异常目录] 
  7. │   │   ├── gateway          [一个逻辑层实现的gateway演示] 
  8. │   │   ├── tools               [工具类目录] 
  9. │   │   └── UserDefinedCase.php [注册框架加载到路由前的处理用例] 
  10. │   └── models                  [数据模型目录] 
  11. │       └── TestTable.php       [演示模型文件,定义一一对应的数据模型] 
  12. ├── config                      [配置目录] 
  13. │    ├── demo                   [模块配置目录] 
  14. │    │   ├── config.php         [模块自定义配置] 
  15. │    │   └── route.php          [模块自定义路由] 
  16. │    ├── common.php             [公共配置] 
  17. │    ├── database.php           [数据库配置] 
  18. │    └── nosql.php              [nosql配置] 
  19. docs                            [接口文档目录] 
  20. ├── apib                        [Api Blueprint] 
  21. │    └── demo.apib              [接口文档示例文件] 
  22. ├── swagger                     [swagger] 
  23. framework                       [Easy PHP核心框架目录] 
  24. ├── exceptions                  [异常目录] 
  25. │      ├── CoreHttpException.php[核心http异常] 
  26. ├── handles                     [框架运行时挂载处理机制类目录] 
  27. │      ├── Handle.php           [处理机制接口] 
  28. │      ├── ErrorHandle.php      [错误处理机制类] 
  29. │      ├── ExceptionHandle.php  [未捕获异常处理机制类] 
  30. │      ├── ConfigHandle.php     [配置文件处理机制类] 
  31. │      ├── NosqlHandle.php      [nosql处理机制类] 
  32. │      ├── LogHandle.php        [log机制类] 
  33. │      ├── UserDefinedHandle.php[用户自定义处理机制类] 
  34. │      └── RouterHandle.php     [路由处理机制类] 
  35. ├── orm                         [对象关系模型] 
  36. │      ├── Interpreter.php      [sql解析器] 
  37. │      ├── DB.php               [数据库操作类] 
  38. │      ├── Model.php            [数据模型基类] 
  39. │      └── db                   [数据库类目录] 
  40. │          └── Mysql.php        [mysql实体类] 
  41. ├── nosql                       [nosql类目录] 
  42. │    ├── Memcahed.php           [Memcahed类文件] 
  43. │    ├── MongoDB.php            [MongoDB类文件] 
  44. │    └── Redis.php              [Redis类文件] 
  45. ├── App.php                     [框架类] 
  46. ├── Container.php               [服务容器] 
  47. ├── Helper.php                  [框架助手类] 
  48. ├── Load.php                    [自加载类] 
  49. ├── Request.php                 [请求类] 
  50. ├── Response.php                [响应类] 
  51. ├── run.php                     [框架应用启用脚本] 
  52. frontend                        [前端源码和资源目录] 
  53. ├── src                         [资源目录] 
  54. │    ├── components             [vue组件目录] 
  55. │    ├── views                  [vue视图目录] 
  56. │    ├── images                 [图片] 
  57. │    ├── ... 
  58. ├── app.js                      [根js] 
  59. ├── app.vue                     [根组件] 
  60. ├── index.template.html         [前端入口文件模板] 
  61. ├── store.js                    [vuex store文件] 
  62. public                          [公共资源目录,暴露到万维网] 
  63. ├── dist                        [前端build之后的资源目录,build生成的目录,不是发布分支忽略该目录] 
  64. │    └── ... 
  65. ├── index.html                  [前端入口文件,build生成的文件,不是发布分支忽略该文件] 
  66. ├── index.php                   [后端入口文件] 
  67. runtime                         [临时目录] 
  68. ├── logs                        [日志目录] 
  69. ├── build                       [php打包生成phar文件目录] 
  70. tests                           [单元测试目录] 
  71. ├── demo                        [模块名称] 
  72. │      └── DemoTest.php         [测试演示] 
  73. ├── TestCase.php                [测试用例] 
  74. vendor                          [composer目录] 
  75. .git-hooks                      [git钩子目录] 
  76. ├── pre-commit                  [git pre-commitcommit钩子示例文件] 
  77. ├── commit-msg                  [git commit-msg示例文件] 
  78. .babelrc                        [babel配置文件] 
  79. .env                            [环境变量文件] 
  80. .gitignore                      [git忽略文件配置] 
  81. build                           [php打包脚本] 
  82. cli                             [框架cli模式运行脚本] 
  83. LICENSE                         [lincese文件] 
  84. logo.png                        [框架logo图片] 
  85. composer.json                   [composer配置文件] 
  86. composer.lock                   [composer lock文件] 
  87. package.json                    [前端依赖配置文件] 
  88. phpunit.xml                     [phpunit配置文件] 
  89. README-CN.md                    [中文版readme文件] 
  90. README.md                       [readme文件] 
  91. webpack.config.js               [webpack配置文件] 
  92. yarn.lock                       [yarn lock文件] 

框架模块说明:

入口文件

定义一个统一的入口文件,对外提供统一的访问文件。对外隐藏了内部的复杂性,类似企业服务总线的思想。


 
 
  1. // 载入框架运行文件  
  2. require('../framework/run.php'); 

[ file: public/index.php ]

自加载模块

使用spl_autoload_register函数注册自加载函数到__autoload队列中,配合使用命名空间,当使用一个类的时候可以自动载入(require)类文件。注册完成自加载逻辑后,我们就可以使用use和配合命名空间申明对某个类文件的依赖。

[ file: framework/Load.php ]

错误和异常模块

脚本运行期间:

  • 错误:

通过函数set_error_handler注册用户自定义错误处理方法,但是set_error_handler不能处理以下级别错误,E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,和在 调用 set_error_handler() 函数所在文件中产生的大多数 E_STRICT。所以我们需要使用register_shutdown_function配合error_get_last获取脚本终止执行的最后错误,目的是对于不同错误级别和致命错误进行自定义处理,例如返回友好的提示的错误信息。

[ file: framework/hanles/ErrorHandle.php ]

异常:

通过函数set_exception_handler注册未捕获异常处理方法,目的捕获未捕获的异常,例如返回友好的提示和异常信息。

[ file: framework/hanles/ExceptionHandle.php ]

配置文件模块

加载框架自定义和用户自定义的配置文件。

[ file: framework/hanles/ConfigHandle.php ]

输入和输出

  • 定义请求对象:包含所有的请求信息
  • 定义响应对象:申明响应相关信息

框架中所有的异常输出和控制器输出都是json格式,因为我认为在前后端完全分离的今天,这是很友善的,目前我们不需要再去考虑别的东西。

[ file: framework/Request.php ]

[ file: framework/Response.php ]

路由模块

通过用户访问的url信息,通过路由规则执行目标控制器类的的成员方法。我在这里把路由大致分成了四类:

传统路由


 
 
  1. domain/index.php?module=Demo&contoller=Index&action=test&username=test 

pathinfo路由


 
 
  1. domain/demo/index/modelExample 

用户自定义路由


 
 
  1. // 定义在config/moduleName/route.php文件中,这个的this指向RouterHandle实例 
  2. $this->get('v1/user/info'function (Framework\App $app) { 
  3.     return 'Hello Get Router'
  4. }); 

微单体路由

我在这里详细说下这里所谓的微单体路由,面向SOA和微服务架构大行其道的今天,有很多的团队都在向服务化迈进,但是服务化过程中很多问题的复杂度都是指数级的增长,例如分布式的事务,服务部署,跨服务问题追踪等等。这导致对于小的团队从单体架构走向服务架构难免困难重重,所以有人提出来了微单体架构,按照我的理解就是在一个单体架构的SOA过程,我们把微服务中的的各个服务还是以模块的方式放在同一个单体中,比如:


 
 
  1. app 
  2. ├── UserService     [用户服务模块] 
  3. ├── ContentService  [内容服务模块] 
  4. ├── OrderService    [订单服务模块] 
  5. ├── CartService     [购物车服务模块] 
  6. ├── PayService      [支付服务模块] 
  7. ├── GoodsService    [商品服务模块] 
  8. └── CustomService   [客服服务模块] 

如上,我们简单的在一个单体里构建了各个服务模块,但是这些模块怎么通信呢?如下:


 
 
  1. App::$app->get('demo/index/hello', [ 
  2.     'user' => 'TIGERB' 
  3. ]); 

通过上面的方式我们就可以松耦合的方式进行单体下各个模块的通信和依赖了。与此同时,业务的发展是难以预估的,未来当我们向SOA的架构迁移时,很简单,我们只需要把以往的模块独立成各个项目,然后把App实例get方法的实现转变为RPC或者REST的策略即可,我们可以通过配置文件去调整对应的策略或者把自己的,第三方的实现注册进去即可。

[ file: framework/hanles/RouterHandle.php ]

传统的MVC模式提倡为MCL模式

传统的MVC模式包含model-view-controller层,绝大多时候我们会把业务逻辑写到controller层或model层,但是慢慢的我们会发现代码难以阅读、维护、扩展,所以我在这里强制增加了一个logics层。至于,逻辑层里怎么写代码怎么,完全由你自己定义,你可以在里面实现一个工具类,你也可以在里面再新建子文件夹并在里面构建你的业务逻辑代码,你甚至可以实现一个基于责任连模式的网关(我会提供具体的示例)。这样看来,我们的最终结构是这样的:

  • M: models, 职责只涉及数据模型相关操作
  • C: controllers, 职责对外暴露资源,前后端分离架构下controllers其实就相当于json格式的视图
  • L: logics, 职责灵活实现所有业务逻辑的地方

logics逻辑层

逻辑层实现网关示例:

我们在logics层目录下增加了一个gateway目录,然后我们就可以灵活的在这个目录下编写逻辑了。gateway的结构如下:


 
 
  1. gateway                     [Logics层目录下gateway逻辑目录] 
  2.   ├── Check.php             [接口] 
  3.   ├── CheckAppkey.php       [检验app key
  4.   ├── CheckArguments.php    [校验必传参数] 
  5.   ├── CheckAuthority.php    [校验访问权限] 
  6.   ├── CheckFrequent.php     [校验访问频率] 
  7.   ├── CheckRouter.php       [网关路由] 
  8.   ├── CheckSign.php         [校验签名] 
  9.   └── Entrance.php          [网关入口文件] 

网关入口类主要负责网关的初始化,代码如下:


 
 
  1. // 初始化一个:必传参数校验的check 
  2. $checkArguments   =  new CheckArguments(); 
  3. // 初始化一个:app key check 
  4. $checkAppkey      =  new CheckAppkey(); 
  5. // 初始化一个:访问频次校验的check 
  6. $checkFrequent    =  new CheckFrequent(); 
  7. // 初始化一个:签名校验的check 
  8. $checkSign        =  new CheckSign(); 
  9. // 初始化一个:访问权限校验的check 
  10. $checkAuthority   =  new CheckAuthority(); 
  11. // 初始化一个:网关路由规则 
  12. $checkRouter      =  new CheckRouter(); 
  13.  
  14. // 构成对象链 
  15. $checkArguments->setNext($checkAppkey) 
  16.                ->setNext($checkFrequent) 
  17.                ->setNext($checkSign) 
  18.                ->setNext($checkAuthority) 
  19.                ->setNext($checkRouter); 
  20.  
  21. // 启动网关 
  22. $checkArguments->start( 
  23.     APP::$container->getSingle('request'
  24. ); 

实现完成这个gateway之后,我们如何在框架中去使用呢?在logic层目录中我提供了一个user-defined的实体类,我们把gateway的入口类注册到UserDefinedCase这个类中,示例如下:


 
 
  1. /** 
  2.  * 注册用户自定义执行的类 
  3.  * 
  4.  * @var array 
  5.  */ 
  6. private $map = [ 
  7.     // 演示 加载自定义网关 
  8.     'App\Demo\Logics\Gateway\Entrance' 
  9. ]; 

这样这个gateway就可以工作了。接着说说这个UserDefinedCase类,UserDefinedCase会在框架加载到路由机制之前被执行,这样我们就可以灵活的实现一些自定义的处理了。这个gateway只是个演示,你完全可以天马行空的组织你的逻辑~

视图View去哪了?由于选择了完全的前后端分离和SPA(单页应用), 所以传统的视图层也因此去掉了,详细的介绍看下面。

[ file: app/* ]

使用Vue作为视图

源码目录

完全的前后端分离,数据双向绑定,模块化等等的大势所趋。这里我把我自己开源的vue前端项目结构 easy-vue 移植到了这个项目里,作为视图层。我们把前端的源码文件都放在frontend目录里,详细如下,你也可以自己定义:


 
 
  1. frontend                        [前端源码和资源目录,这里存放我们整个前端的源码文件] 
  2. ├── src                         [资源目录] 
  3. │    ├── components             [编写我们的前端组件] 
  4. │    ├── views                  [组装我们的视图] 
  5. │    ├── images                 [图片] 
  6. │    ├── ... 
  7. ├── app.js                      [根js] 
  8. ├── app.vue                     [根组件] 
  9. ├── index.template.html         [前端入口文件模板] 
  10. └── store.js                    [状态管理,这里只是个演示,你可以很灵活的编写文件和目录] 

build步骤


 
 
  1. yarn install  
  2. DOMAIN=http://你的域名 npm run dev 

编译后

build成功之后会生成dist目录和入口文件index.html在public目录中。非发布分支.gitignore文件会忽略这些文件,发布分支去除忽略即可。


 
 
  1. public [公共资源目录,暴露到万维网]  
  2. ├── dist [前端build之后的资源目录,build生成的目录,不是发布分支忽略该目录] 
  3. │ └── ...  
  4. ├── index.html [前端入口文件,build生成的文件,不是发布分支忽略该文件] 

[ file: frontend/* ]

数据库对象关系映射

数据库对象关系映射ORM(Object Relation Map)是什么?按照我目前的理解:顾名思义是建立对象和抽象事物的关联关系,在数据库建模中model实体类其实就是具体的表,对表的操作其实就是对model实例的操作。可能绝大多数的人都要问“为什么要这样做,直接sql语句操作不好吗?搞得这么麻烦!”,我的答案:直接sql语句当然可以,一切都是灵活的,但是从一个项目的 可复用,可维护, 可扩展 出发,采用ORM思想处理数据操作是理所当然的,想想如果若干一段时间你看见代码里大段的难以阅读且无从复用的sql语句,你是什么样的心情。

市面上对于ORM的具体实现有thinkphp系列框架的Active Record,yii系列框架的Active Record,laravel系列框架的Eloquent(据说是最优雅的),那我们这里言简意赅就叫ORM了。接着为ORM建模,首先是ORM客户端实体DB:通过配置文件初始化不同的db策略,并封装了操作数据库的所有行为,最终我们通过DB实体就可以直接操作数据库了,这里的db策略目前我只实现了mysql(负责建立连接和db的底层操作)。接着我们把DB实体的sql解析功能独立成一个可复用的sql解析器的trait,具体作用:把对象的链式操作解析成具体的sql语句。最后,建立我们的模型基类model,model直接继承DB即可。最后的结构如下:


 
 
  1. ├── orm                         [对象关系模型] 
  2. │      ├── Interpreter.php      [sql解析器] 
  3. │      ├── DB.php               [数据库操作类] 
  4. │      ├── Model.php            [数据模型基类] 
  5. │      └── db                   [数据库类目录] 
  6. │          └── Mysql.php        [mysql实体类] 

DB类使用示例


 
 
  1. /** 
  2.  * DB操作示例 
  3.  * 
  4.  * findAll 
  5.  * 
  6.  * @return void 
  7.  */ 
  8. public function dbFindAllDemo() 
  9.     $where = [ 
  10.         'id'   => ['>=', 2], 
  11.     ]; 
  12.     $instance = DB::table('user'); 
  13.     $res      = $instance->where($where
  14.                          ->orderBy('id asc'
  15.                          ->limit(5) 
  16.                          ->findAll(['id','create_at']); 
  17.     $sql      = $instance->sql; 
  18.  
  19.     return $res; 

Model类使用示例


 
 
  1. // controller 代码 
  2. /** 
  3.  * model example 
  4.  * 
  5.  * @return mixed 
  6.  */ 
  7. public function modelExample() 
  8.     try {  
  9.         DB::beginTransaction(); 
  10.         $testTableModel = new TestTable(); 
  11.  
  12.         // find one data 
  13.         $testTableModel->modelFindOneDemo(); 
  14.         // find all data 
  15.         $testTableModel->modelFindAllDemo(); 
  16.         // save data 
  17.         $testTableModel->modelSaveDemo(); 
  18.         // delete data 
  19.         $testTableModel->modelDeleteDemo(); 
  20.         // update data 
  21.         $testTableModel->modelUpdateDemo([ 
  22.                'nickname' => 'easy-php' 
  23.             ]); 
  24.         // count data 
  25.         $testTableModel->modelCountDemo(); 
  26.  
  27.         DB::commit(); 
  28.         return 'success'
  29.  
  30.     } catch (Exception $e) { 
  31.         DB::rollBack(); 
  32.         return 'fail'
  33.     } 
  34. }  
  35. //TestTable model 
  36. /** 
  37.  * Model操作示例 
  38.  * 
  39.  * findAll 
  40.  * 
  41.  * @return void 
  42.  */ 
  43. public function modelFindAllDemo() 
  44.     $where = [ 
  45.         'id'   => ['>=', 2], 
  46.     ]; 
  47.     $res = $this->where($where
  48.                 ->orderBy('id asc'
  49.                 ->limit(5) 
  50.                 ->findAll(['id','create_at']); 
  51.     $sql = $this->sql; 
  52.  
  53.     return $res; 

[ file: framework/orm/* ]

服务容器模块

什么是服务容器?

服务容器听起来很浮,按我的理解简单来说就是提供一个第三方的实体,我们把业务逻辑需要使用的类或实例注入到这个第三方实体类中,当需要获取类的实例时我们直接通过这个第三方实体类获取。

服务容器的意义?

用设计模式来讲:其实不管设计模式还是实际编程的经验中,我们都是强调“高内聚,松耦合”,我们做到高内聚的结果就是每个实体的作用都是极度专一,所以就产生了各个作用不同的实体类。在组织一个逻辑功能时,这些细化的实体之间就会不同程度的产生依赖关系,对于这些依赖我们通常的做法如下:


 
 
  1. class Demo 
  2.     public function __construct() 
  3.     { 
  4.         // 类demo直接依赖RelyClassName 
  5.         $instance = new RelyClassName(); 
  6.     } 

这样的写法没有什么逻辑上的问题,但是不符合设计模式的“最少知道原则”,因为之间产生了直接依赖,整个代码结构不够灵活是紧耦合的。所以我们就提供了一个第三方的实体,把直接依赖转变为依赖于第三方,我们获取依赖的实例直接通过第三方去完成以达到松耦合的目的,这里这个第三方充当的角色就类似系统架构中的“中间件”,都是协调依赖关系和去耦合的角色。最后,这里的第三方就是所谓的服务容器。

在实现了一个服务容器之后,我把Request,Config等实例都以单例的方式注入到了服务容器中,当我们需要使用的时候从容器中获取即可,十分方便。使用如下:


 
 
  1. // 注入单例 
  2. App::$container->setSingle('别名,方便获取''对象/闭包/类名'); 
  3.  
  4. // 例,注入Request实例 
  5. App::$container->setSingle('request'function () { 
  6.     // 匿名函数懒加载 
  7.     return new Request(); 
  8. }); 
  9. // 获取Request对象 
  10. App::$container->getSingle('request'); 

[ file: framework/Container ]

Nosql模块

提供对nosql的支持,提供全局单例对象,借助我们的服务容器我们在框架启动的时候,通过配置文件的配置把需要的nosql实例注入到服务容器中。目前我们支持redis/memcahed/mongodb。

如何使用?如下,


 
 
  1. // 获取redis对象 
  2. App::$container->getSingle('redis'); 
  3. // 获取memcahed对象 
  4. App::$container->getSingle('memcahed'); 
  5. // 获取mongodb对象 
  6. App::$container->getSingle('mongodb'); 

[ file: framework/nosql/* ]

接口文档生成和接口模拟模块

通常我们写完一个接口后,接口文档是一个问题,我们这里使用Api Blueprint协议完成对接口文档的书写和mock(可用),同时我们配合使用Swagger通过接口文档实现对接口的实时访问(目前未实现)。

Api Blueprint接口描述协议选取的工具是snowboard,具体使用说明如下:

接口文档生成说明


 
 
  1. cd docs/apib  
  2. ./snowboard html -i demo.apib -o demo.html -s  
  3. open the website, http://localhost:8088/ 

接口mock使用说明


 
 
  1. cd docs/apib  
  2. ./snowboard mock -i demo.apib  
  3. open the website, http://localhost:8087/demo/index/hello 

[ file: docs/* ]

单元测试模块

基于phpunit的单元测试,写单元测试是个好的习惯。

如何使用?

tests目录下编写测试文件,具体参考tests/demo目录下的DemoTest文件,然后运行:


 
 
  1. vendor/bin/phpunit 

测试断言示例:


 
 
  1. /** 
  2.  * 演示测试 
  3.  */ 
  4. public function testDemo() 
  5.     $this->assertEquals( 
  6.         'Hello Easy PHP'
  7.         // 执行demo模块index控制器hello操作,断言结果是不是等于'Hello Easy PHP'  
  8.         App::$app->get('demo/index/hello'
  9.     ); 

phpunit断言文档语法参考

[ file: tests/* ]

Git钩子配置

目的规范化我们的项目代码和commit记录。

  • 代码规范:配合使用php_codesniffer,在代码提交前对代码的编码格式进行强制验证。
  • commit-msg规范:采用ruanyifeng的commit msg规范,对commit msg进行格式验证,增强git log可读性和便于后期查错和统计log等, 这里使用了 Treri 的commit-msg脚本,Thx~。

[ file: ./git-hooks/* ]

辅助脚本

cli脚本

以命令行的方式运行框架,具体见使用说明。

build脚本

打包PHP项目脚本,打包整个项目到runtime/build目录,例如:


 
 
  1. runtime/build/App.20170505085503.phar  
  2. <?php 
  3. // 入口文件引入包文件即可 
  4. require('runtime/build/App.20170505085503.phar'

[ file: ./build ]

如何使用?

执行:

  • composer install
  • chmod -R 777 runtime

网站服务模式:

  • 步骤 1: yarn install
  • 步骤 2: DOMAIN=http://localhost:666 npm run demo
  • 步骤 3: cd public
  • 步骤 4: php -S localhost:666

访问网站:http://localhost:666/index.html

访问接口:http://localhost:666/Demo/Index/hello

demo如下:

客户端脚本模式:


 
 
  1. php cli --method= --= ...  
  2. 例如, php cli --method=demo.index.get --username=easy-php 

获取帮助:

使用命令 php cli 或者 php cli --help

问题和贡献

不足的地方还有很多,如果大家发现了什么问题,可以给我提 issue 或者PR。

或者你觉着在这个框架实现的细节你想了解的,一样可以给我提 issue ,后面我会总结成相应的文章分享给大家。

如何贡献?


 
 
  1. cp ./.git-hooks/* ./git/hooks 

然后正常发起PR即可, 所有的commit我都会进行代码格式(psr)验证和commit-msg验证,如果发生错误,请按照提示纠正即可。

项目地址: https://github.com/TIGERB/easy-php

TODO

  • 懒加载优化框架加载流程
  • 性能测试和优化
  • 变更Helper助手类的成员方法为框架函数,简化使用提高生产效率
  • 提供更友善的开发api帮助
  • 模块支持数据库nosql自定义配置
  • 支持mysql主从配置
  • ORM提供更多链式操作api
  • 框架log行为进行级别分类
  • 想办法解决上线部署是配置文件问题
  • 基于phar文件和git webhook自动化打包部署
  • ...
作者:佚名
来源:51CTO
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1月前
|
SQL 安全 PHP
PHP 自发布以来一直在 Web 开发领域占据重要地位,PHP 8 更是带来了属性、刚性类型等新特性。
【10月更文挑战第1天】PHP 自问世以来,凭借其易用性和灵活性,在 Web 开发领域迅速崛起。从简单的网页脚本语言逐步演进为支持面向对象编程的现代语言,尤其自 PHP 5.3 引入命名空间后,代码组织和维护变得更加高效。PHP 7 的性能优化和 PHP 8 的新特性(如属性和刚性类型)进一步巩固了其地位。框架如 Laravel、Symfony、Yii2 和 CodeIgniter 等简化了开发流程,提高了效率和安全性。
46 2
|
2月前
|
存储 PHP 开发者
深入浅出PHP:构建你的首个动态网页
【9月更文挑战第24天】在数字时代的今天,掌握编程技能不再是专业技术人员的专利。PHP作为一种流行的服务端脚本语言,因其易学性和灵活性而广受欢迎。本文将引导您从零开始,通过一个简单实例—创建个人博客页面,逐步深入PHP的世界。我们将一起探索变量、循环和函数等基本概念,并最终将这些元素融合到实际的代码中。不论你是编程新手还是希望扩展知识的开发者,这篇文章都将为你提供一次愉快的学习旅程。
43 0
|
13天前
|
SQL 安全 前端开发
PHP与现代Web开发:构建高效的网络应用
【10月更文挑战第37天】在数字化时代,PHP作为一门强大的服务器端脚本语言,持续影响着Web开发的面貌。本文将深入探讨PHP在现代Web开发中的角色,包括其核心优势、面临的挑战以及如何利用PHP构建高效、安全的网络应用。通过具体代码示例和最佳实践的分享,旨在为开发者提供实用指南,帮助他们在不断变化的技术环境中保持竞争力。
|
15天前
|
PHP 开发者
深入浅出PHP:构建你的第一个Web应用
【10月更文挑战第35天】在数字时代的浪潮中,掌握编程技能已成为通往未来的钥匙。本文将带你从零开始,一步步走进PHP的世界,解锁创建动态网页的魔法。通过浅显易懂的语言和实际代码示例,我们将共同打造一个简单但功能强大的Web应用。无论你是编程新手还是希望扩展技能的老手,这篇文章都将是你的理想选择。让我们一起探索PHP的魅力,开启你的编程之旅!
|
15天前
|
API PHP 数据库
PHP中哪个框架最适合做API?
在数字化时代,API作为软件应用间通信的桥梁至关重要。本文探讨了PHP中适合API开发的主流框架,包括Laravel、Symfony、Lumen、Slim、Yii和Phalcon,分析了它们的特点和优势,帮助开发者选择合适的框架,提高开发效率、保证接口稳定性和安全性。
37 3
|
18天前
|
SQL 安全 PHP
探索PHP的现代演进:从Web开发到框架创新
PHP是一种流行的服务器端脚本语言,自诞生以来在Web开发领域占据重要地位。从简单的网页脚本到支持面向对象编程的现代语言,PHP经历了多次重大更新。本文探讨PHP的现代演进历程,重点介绍其在Web开发中的应用及框架创新,如Laravel、Symfony等。这些框架不仅简化了开发流程,还提高了开发效率和安全性。
24 3
|
21天前
|
SQL 安全 PHP
探索PHP的现代演进:从Web开发到框架创新
PHP 自发布以来一直在 Web 开发领域占据重要地位,历经多次重大更新,从简单的脚本语言进化为支持面向对象编程的现代语言。本文探讨 PHP 的演进历程,重点介绍其在 Web 开发中的应用及框架创新。自 PHP 5.3 引入命名空间后,PHP 迈向了面向对象编程时代;PHP 7 通过优化内核大幅提升性能;PHP 8 更是带来了属性、刚性类型等新特性。
25 3
|
24天前
|
人工智能 搜索推荐 PHP
PHP在Web开发中的璀璨星辰:构建动态网站的幕后英雄###
【10月更文挑战第25天】 本文将带您穿越至PHP的宇宙,揭示其作为Web开发常青树的奥秘。通过生动实例与深入解析,展现PHP如何以简便、高效、灵活的姿态,赋能开发者打造动态交互式网站,同时不忘探讨其在新时代技术浪潮中面临的挑战与机遇,激发对技术创新与应用的无限思考。 ###
32 1
|
21天前
|
自然语言处理 关系型数据库 MySQL
PHP编程入门:构建你的第一个网页应用
【10月更文挑战第29天】本文旨在引导初学者步入PHP编程的世界,通过深入浅出的方式介绍PHP的基础知识,并指导读者如何动手实践,搭建一个简单的网页应用。文章不仅涉及PHP代码的编写,还包括了环境配置、项目结构设计以及前后端交互的基本概念。适合对Web开发感兴趣且希望快速入门的朋友阅读。
33 0
|
1月前
|
SQL 缓存 安全
深入PHP:构建高效Web应用的实用技巧
【10月更文挑战第4天】在动态网站开发领域,PHP以其易用性和灵活性广受欢迎。本文将引导你通过实用的PHP技巧来提升Web应用的性能和安全性。我们将探讨从数据库优化到代码组织的多个方面,并配以实例代码,让你能够在实际项目中立即应用这些知识。文章的目的是让PHP开发者能够在不牺牲代码可读性和维护性的前提下,编写出更快、更安全的应用程序。
下一篇
无影云桌面