开发必看

    强烈推荐如下的开发流程开展系统开发工作:

    1. 本地安装 ModStart 框架,搭建开发环境;
    2. 在开发环境安装模块,同时进行二次开发和测试;
    3. 使用代码管理工具同步代码到仓库( git (opens new window)、);
    4. 使用代码仓库的代码部署到生产服务器。

    代码结构

    系统代码结构参照 Laravel 的目录结构,开发前必须了解以下目录

    应用、模块、功能组

    • 模块:有比较独立的功能,代码在 module/ 目录,每个模块一个目录,模块市场安装的模块也在该目录中。
    • 应用:和业务相关的代码不能独立成为模块复用,代码在 app/ 目录,用于系统个性化的需求开发。
    • 功能组:位于模块目录中,常见的功能组有 WebApiAdminOpenApi ,分别提供不同的分组功能

    路由加载流程

    通过 ModStart\ModStartServiceProvider 类来管理,具体的加载过程参考相关实现逻辑。

    系统会按照如下的顺序加载路由文件。

    • module/Xxx/Web/routes.php:所有模块中的Web前台路由
    • app/Web/routes.php:系统应用Web前台路由

    Admin 功能组

    系统会按照如下的顺序加载路由文件。

    • module/Xxx/Admin/routes.php:所有模块中的Admin后台路由
    • app/Admin/routes.php:系统应用Admin后台路由

    Api 功能组

    系统会按照如下的顺序加载路由文件。

    • module/Xxx/Api/routes.php:所有模块中的Api接口路由
    • app/Api/routes.php:系统应用Api接口路由

    OpenApi 功能组

    系统会按照如下的顺序加载路由文件。

    • module/Xxx/OpenApi/routes.php:所有模块中的OpenApi开放接口路由
    • app/OpenApi/routes.php:系统应用OpenApi开放接口路由

    现支持 PHP5.6、PHP7.0,部分依赖有改造,如需手动安装 Composer 第三方包,需要将 ModStart 私有源加入到 composer.json 中,避免 ModStart 更新时的私有包获取失败。

    请求和响应

    默认情况下,所有接口交互都采用 POST 的请求方式,页面展示采用 GET 的请求方式。

    响应使用统一的JSON返回

    1. {
    2. // 错误码,0表示业务处理正常,非0表示业务处理异常,可以定义多个状态码
    3. "code": 0,
    4. // 提示信息
    5. "msg": "提示信息",
    6. "data": {
    7. //...
    8. },
    9. // 跳转地址
    10. // [js]xxxx : 表示前端执行JS代码
    11. // [reload] : 表示页面立即刷新 window.location.reload()
    12. // 其他值 : 表示跳转到改地址
    13. "redirect": "重定向方式"
    14. }

    后端代码可以使用 类统一构造该返回结果

    1. use ModStart\Core\Input\Response;
    2. // 构造完整的返回结果
    3. Response::generate($code, $msg, $data = null, $redirect = null);
    4. // 构造一个成功的结果数据
    5. Response::generateSuccessData([ 'foo'=>'bar' ]);
    6. // 构造一个错误提示
    7. Response::generateError('错误提示');
    8. // 构造一个正确提示
    9. Response::generateSuccess('正确提示');

    更多使用方式请参考 Response开发必看 - 图4 (opens new window)

    业务异常处理

    业务异常处理使用统一的 BizException (opens new window) 处理。

    1. use ModStart\Core\Exception\BizException;
    2. // 抛出一个异常
    3. BizException::throws('错误信息');
    4. BizException::throwsIfEmpty('用户不存在', $user);
    5. // 条件判断并抛出异常
    6. BizException::throwsIf('记录不存在', empty($record));

    使用 抛出的异常,异常处理模块会自动对异常进行转换。

    如果请求是 Ajax ,结果会自动转换为标准返回,如图:

    如果请求是普通页面,会转换为标准错误页面,如图:

    数据库使用规范

    目前使用 MySQL 作为默认数据库,创建数据库表时,请始终保持至少三个字段(主键、创建时间、更新时间)。

    1. <?php
    2. use Illuminate\Database\Schema\Blueprint;
    3. use Illuminate\Database\Migrations\Migration;
    4. class CreateXxx extends Migration
    5. {
    6. public function up()
    7. {
    8. Schema::create('resume', function (Blueprint $table) {
    9. // 定义数据表主键ID
    10. $table->increments('id');
    11. // 定义数据表创建时间和更新时间 created_at 和 updated_at
    12. $table->timestamps();
    13. // 其他字段
    14. });
    15. }
    16. // ...
    17. }
    • 表名:的使用 模块名_表名,格式为小写+下划线。

    在Web应用程序中,我们经常要跟踪用户身份。当一个用户登录成功后,如果他继续访问其他页面,程序需要继续记录他的身份。

    HTTP协议是一个无状态协议,即Web应用程序无法区分收到的两个HTTP请求是否是同一个浏览器发出的。为了跟踪用户状态,服务器可以向浏览器分配一个唯一ID,并以Cookie的形式发送到浏览器,浏览器在后续访问时总是附带此Cookie,这样,服务器就可以识别用户身份。

    Web 功能组

    • Session::get 获取会话变量
    • Session::put 设置会话变量
    • Session::forget 删除会话变量

    Api目录中的请求,需要携带 api-token 请求头。

    • 第一次发起请求该值留空即可,返回的响应头中会在服务端生成 api-token
    • 在所有接口交互过程中,当响应头中存在 api-token 时,需要覆盖客户端的 api-token 值。
    • 通常第一个请求接口无需携带 api-token 信息,如配置接口 /api/config 、登录接口 /api/login

    具体可参考 vendor/modstart/modstart/src/App/Api/Middleware/SessionMiddleware.php

    Laravel 的 Cookie 配置信息配置文件位于 config/session.php,具体可参考以下几个配置

    • expire_on_close:关闭浏览器是否立即过期
    • path:Cookie 的 Path
    • domain:Cookie 的 域名

    系统默认的Cookie是加密的,如果不需要加密,可以禁用 Cookie 的加密中间件。

    文件位于:app/Http/Kernel.php

    注释掉Cookie加密中间件 \Illuminate\Cookie\Middleware\EncryptCookies::class

    文件上传与静态资源

    文件本地存储

    系统使用了统一的文件上传+存储方案,文件上传默认存储在 /public/data/ 目录中,默认类型+日期进行组织,类型包括 图片(image)、视频(video)、音频(audio)、文件(file)等,具体可在 vendor/modstart/modstart/config/data.php 设置。

    云存储支持

    系统支持市面上主流云存储,如阿里云OSS、腾讯云COS等()。

    通过安装云存储模块+配置即可完成文件上云,安装云存储已上传的文件不受影响。

    安装完成云存储后,可以手动迁移已上传的历史文件,通过 文件路径迁移助手开发必看 - 图8 (opens new window) 完成数据库字段静态文件路径的迁移。

    文件路径修正

    使用默认的本地存储,文件存储路径格式为 /data/xxx/xxx/xxx.xx ,对于需要返回给接口需要补全为全路径,可通过以下方法完成。

    1. // 将文件路径修正为带域名的全路径,如果本身是全路径原样反馈
    2. // 如 https://www.example.com/data/xxx/xxx/xxx.xx
    3. \ModStart\Core\Assets\AssetsUtil::fixFull('/data/xxx/xxx/xxx.xx');

    后台管理

    后台管理员相关操作

    1. // 使用的 Admin 类完整路径为
    2. use ModStart\Admin\Auth\Admin;
    3. // 判断当前管理员是否已登录
    4. Admin::isLogin();
    5. // 当前已登录管理员的ID
    6. $adminUserId = Admin::id();
    7. Admin::get( $adminUserId );
    8. // 增加管理员信息日志
    9. Admin::addInfoLog( $adminUserId, '日志摘要', ['数据'=>'数据值'] );
    10. // 增加管理员错误日志
    11. Admin::addErrorLog( $adminUserId, '错误摘要', ['数据键'=>'数据值'] );
    12. // 如果两个数组数据不相同记录日志
    13. Admin::addInfoLogIfChanged( $adminUserId, '数据改变了', ['数据'=>'数据值旧'], ['数据'=>'数据值新'] );

    后台免登陆接口请求

    • 要求:(MSCore >= 3.6.0)
    • 后台接口指 module/Xxx/Admin 中的接口

    免登陆接口使用说明

    免登陆请求示例代码

    1. $adminUserId = 1;
    2. $adminUserName = 'cms';
    3. $adminPassword = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
    4. $adminPasswordSalt = 'xxxxxxxxxx';
    5. $timestamp = time();
    6. $requestId = uniqid();
    7. $md5String = "$timestamp:$requestId:$adminUserId:$adminUserName:$adminPassword:$adminPasswordSalt";
    8. $sign = md5($md5String);
    9. $ret = CurlUtil::post('http://xxx.com/admin/site/config/setting', [
    10. 'siteName'=>'网站名称'
    11. ], [
    12. 'header' => [
    13. 'auth-admin-user-id' => $adminUserId,
    14. 'auth-admin-timestamp' => $timestamp,
    15. 'auth-admin-request-id' => $requestId,
    16. 'auth-admin-sign' => $sign,
    17. ]
    18. ]);
    19. print_r($ret);

    模块开发兼容性问题

    为了同时兼容 Laravel 5.1 和 Laravel 9.0,PHP 写法需要同时兼容 PHP 5.x 和 PHP 8.x 的语法。除此之外,一直的框架兼容性问题如下。

    Blade 输出变量

    1. 输出变量或默认值需要
    2. {{ empty($param) ? '默认值' : $param }}
    3. 以下写法不兼容
    4. {{ $param or '默认值' }} 只兼容 Laravel 5.1
    1. 封装的兼容性事件触发
    2. \ModStart\Core\Util\EventUtil::fire( $event )
    3. 以下写法不兼容
    4. Event::fire( $event )