This commit is contained in:
zhouyangyang 2022-06-14 19:36:15 +08:00
commit a4b70328c6
23 changed files with 624 additions and 0 deletions

0
.nojekyll Normal file
View File

9
README.md Normal file
View File

@ -0,0 +1,9 @@
## 文档说明
### 运行
```sh
docsify serve
```

1
_sidebar.md Normal file
View File

@ -0,0 +1 @@
* [Home](/)

1
asset/docsify.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
asset/prism-php.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
asset/search.min.js vendored Normal file

File diff suppressed because one or more lines are too long

59
asset/vue.css Normal file

File diff suppressed because one or more lines are too long

21
database.md Normal file
View File

@ -0,0 +1,21 @@
## 数据库设计
1. 数据任何一张表需保留`create_uid,update_uid,created_at,updated_at,deleted_at`依次表示记录创建人,更新人,创建时间,更新时间,删除时间。`created_at,updated_at,deleted_at` 类型为datetime。
2. 业务数据主表需要保留`service_id`字段该字段用于定义多服务租户数据隔离字段在后面逻辑业务code中该字段不需要手动写入应有程序底层自动管理。
3. 除json text blog 字段可以设置默认值null其他类型字段必须设置默认值。
4. 数字类型默认整数类型默认为0浮点数类型0.*,除业务需求默认使用无符号。
5. 字符串类型默认为''。varchar 类型必须根据业务场景设置合适长度。
6. 关于时间字段统一使用datetime类型禁止使用init 类型。
7. 业务枚举值统一使用Tinyint 类型。
8. 主键统一使用无符号Bigint类型主键名称必须为id。
## 数据库索引
1. 表中`service_id`字段,必须与需要索引字段建立复合索引。
2. 普通索引必须idx_开头唯一uni_头
3. 建立索引必须有较大索引基数前提下。
## 数据迁移文件
【参考官方文档】 https://hyperf.wiki/2.2/#/zh-cn/db/migration

176
directory_structure.md Normal file
View File

@ -0,0 +1,176 @@
## 框架版本
hyperf 2.[1-2].[*]
## 目录结构
```
├── Amqp //mq 消费者&生产者定义
│   ├── Consumer //消费者
│   │   ├── Config
│   │   ├── Member
│   │   └── Notice
│   └── Producer //生产者
│   ├── Member
│   └── Notice
├── Constant //定义常量
├── Controller //控制器
│   ├── Auth
│   ├── Card
│   ├── Company
│   ├── Flow
│   ├── GenConfig
│   ├── Group
│   ├── Log
│   ├── Manage
│   ├── Member
│   ├── Notice
│   ├── Order
│   ├── Organize
│   ├── Response
│   │   └── Enum
│   ├── SignIn
│   ├── Task
│   └── Verification
├── Event //事件
│   ├── Company
│   ├── Log
│   ├── Member
│   ├── Organize
│   └── Task
├── Exception //异常
│   └── Handler
├── JsonRpc //RPC 2.1 版本 起始
│   ├── Consumers
│   │   └── Tenant
│   ├── Providers
│   │   └── Member
│   └── Traits
├── Listener //监听
│   ├── Member
│   ├── Notice
│   ├── Organize
│   └── Task
├── Middleware //中间件
│   ├── Auth
│   ├── Manage
│   └── Service
├── Model //数据模型
│   ├── QueryBuild
│   │   └── resolves
│   ├── Scope
│   └── Traits
├── Process //自定义进程
│   ├── Extra
│   │   └── Job
│   ├── Order
│   │   └── Job
│   └── Task
│   └── Level
│   └── Job
├── Request //定义前端请求文件
│   ├── Card
│   ├── Company
│   ├── Config
│   ├── Credit
│   ├── Flow
│   ├── Group
│   ├── Manage
│   ├── Oauth
│   ├── Order
│   ├── Organize
│   └── Traits
├── Script //自定义脚本文件
└── Service //服务模块
├── ApiDispatch // api 代理分发
├── Assist // 辅助功能类库
├── Common // 公共服务
│   └── Config
├── LogicModule // 逻辑业务模块
│   ├── Auth //权限
│   │   ├── Oauth //授权
│   │   ├── Third //三方登录
│   │   └── Traits //特性
│   ├── Card
│   │   └── Bind
│   ├── Company
│   ├── Contract
│   ├── Flow
│   │   ├── Client
│   │   └── Traits
│   ├── Group
│   ├── Logger
│   ├── Manage
│   │   └── Auth
│   ├── Member
│   │   ├── Card
│   │   │   ├── Order
│   │   │   └── Pay
│   │   │   └── Traits
│   │   ├── Medal
│   │   │   └── Traits
│   │   ├── Member
│   │   ├── MemberSave
│   │   ├── Privilege
│   │   │   └── Traits
│   │   └── Statistics
│   ├── Menu
│   ├── Notice
│   ├── Order
│   ├── Organize
│   │   └── Traits
│   ├── SignIn
│   │   └── Contract
│   ├── Task
│   │   ├── Contract
│   │   ├── Exec
│   │   │   └── Handler
│   │   ├── Privilege
│   │   │   └── Handler
│   │   ├── Process
│   │   │   └── Handler
│   │   ├── Risk
│   │   │   └── Handler
│   │   ├── TaskObj
│   │   │   └── Relate
│   │   ├── Template
│   │   └── Traits
│   └── Traits
│   └── Member
├── MessageWatch
└── RiskControl // 风控层
├── Contract //契约
├── Filter //过滤
│   └── sensitive
├── Task
└── Verification
├── Attribute
├── Code
│   └── Sms
└── Traits
```
## 编码&工具规范
### 编码
1. PHP编码完全按照[psr ](https://www.php-fig.org/psr/) 规范。
3. PHPDoc必须保留空行在第一个标记前使用空行。
4. 数组需要对其键值对。
5. 必须使用php7.4语法(更容易编写规范代码),函数入参/类属性 需要申明指定类型。
6. 必须使用公司php7.4容器开发,以保持环境一致。
### 工具
1. 强烈建议PHPstrom 新版作为开发工具。
2. 建议安装sonarlint 静态分析解决major坏味道及霉味代码。
## 依赖注入
官方文档https://hyperf.wiki/2.2/#/zh-cn/di
## 函数
封装了部分函数,方便调用 位置于app/Functions.php
常见函数如下:
1. get_redis() 获取redis 实列
2. list_to_tree() 列表转成tree
3. get_member_id() 获取当前会员id

28
exception.md Normal file
View File

@ -0,0 +1,28 @@
## 统一异常处理
目前会员中心工程中app/Exception 用来定义异常处理包含全局统一异常处理异常处理放在Handler文件中。开发者一般无需在业务code中使用try catch 去捕获异常。
## 错误枚举值
会员中心错误定义在app/Controller/Response/Enum/ErrorCode.php 文件中。开发者在编写业务逻辑代码需要提前在该文件定义错误枚举值。然后在code使用如下示例代码进行错误抛出。
```php
// code
if (!empty($entity)) {
throw new MemberException(ErrorCode::getMessage(ErrorCode::HAS_VERIFY, [$this->entity['text']]));
}
//normal
return true;
```
## 异常处理
如果目前会员中心异常处理不满足开发者业务需要开发者可以参考官方教程地址,实现满足自定义需求:
使用教程https://hyperf.wiki/2.2/#/zh-cn/exception-handler

1
guide.md Normal file
View File

@ -0,0 +1 @@
## guide

47
index.html Normal file
View File

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="Description">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="./asset/vue.css">
</head>
<body>
<div id="app"></div>
<script>
window.$docsify = {
name: '会员中心开发指导',
homepage: 'README.md',
loadSidebar: 'summary.md',
loadNavbar: true,
fallbackLanguages: ['zh-cn', 'en'],
mergeNavbar: true,
themeColor: '#3F51B5',
logo: '/logo.png',
auto2top: true,
routerMode: 'hash',
topMargin: 40,
subMaxLevel: 4,
search: {
paths: 'auto',
placeholder: '请输入要搜索的关键字',
noData: '没有结果',
depth: 6
}
}
</script>
<script src="./asset/prism-php.min.js" ></script>
<!-- Docsify v4 -->
<script src="./asset/docsify.min.js" ></script>
<script src="./asset/search.min.js"></script>
</body>
</html>

44
quick-dev/config.md Normal file
View File

@ -0,0 +1,44 @@
## config
`congfig` 配置指的是在数据表`yun_config` 一般用来保存程序运行前设定好的配置在runtime中不得进行变更。
该配置包含了:
1. 短信配置
2. sns登录配置
3. 昵称,实名认证,头像审核
4. 手机快捷登录
## gen_config
`gen_config`配置一般用来保存业务流程数据以及预设数据比如会员等级成长中心签到等配置。yun_gen_category_config是为了更好的划分gen_config对`gen_config`进行有效的分组。开发者在自己开发模块 使用`Config::getConfigMap()` 快速获取配置,代码示例如下:
```php
/**
* 获取个推快捷登录配置
*
* @return array
*/
private function getConfig(): array
{
$select = [
'mobile_quick_login',
'get_tui_iv',
'ge_tui_get_pn_url',
'ge_tui_app_id',
'ge_tui_app_key',
'ge_tui_master_secret',
'ge_tui_encrypt_method'
];
return Config::getConfigMap($select);
}
```

54
quick-dev/controller.md Normal file
View File

@ -0,0 +1,54 @@
## 创建
示例:
```php
class CompanyController
{
/**
* @Inject
* @var CompanyRequest
*/
protected CompanyRequest $companyRequest;
/**
* @param ApiLayerService $service
* @return ResponseInterface
* @throws MemberException
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function companiesForSimple(ApiLayerService $service): ResponseInterface
{
$result = $service->inject($this->companyRequest)->handle([
'logic_config' => [
CompanyService::class,//调用服务类
'getCompanySimpleList'//对应方法
]
]);
return (new AppResponse())->setResult($result)->success();
}
```
### 说明
1. 所有控制器方法 必须依赖ApiLayerService
2. ApiLayerService->inject 注入当前请求对象
3. 由handle注入服务调用编排配置
开发者初期只需要记住这样固定编排格式即可,配置如下
```php
[
'logic_config' => [
CompanyService::class,//调用服务类
'getCompanySimpleList'//对应方法
]
]
```
直白了说等同于 (new CompanyService(ApiConfigService $config))->getCompanySimpleList(); 并且将一系列依赖直接注入该对象中开发者在CompanyService直接调用相关依赖。

25
quick-dev/model.md Normal file
View File

@ -0,0 +1,25 @@
## 创建model
强烈推荐是官方脚手架创建model有如下好处
1. 自动生成model 属性
2. 自动生成$cast
脚手架命令:
```shell
//你的目录
php bin/hyperf.php gen:model {你的表名不带前缀}
```
## 继承基础model
**必须继承继承基础model** 文件位于model文件下Model文件
基础model提供功能如下
1. id 主键自动写入雪花算法
2. 提供encrypt/decrypt 字段加密和解密
3. checkUnique 字段唯一检测
4. serviceQuery() 服务查询
5. 自动协程转换数据库字段类型
6. 自动写入created_at updated_at service_id created_uid updated_uid

2
quick-dev/request.md Normal file
View File

@ -0,0 +1,2 @@
## 请求
参考官方教程即可 https://hyperf.wiki/2.2/#/zh-cn/request

60
quick-dev/service.md Normal file
View File

@ -0,0 +1,60 @@
## 服务
目前除了RiskControl层外所有的新建服务必须继承 BaseService 并且实现 LogicServiceContract 接口即app/Service/RiskControl 下文件除外。
这样继承之后新的服务就会自动依赖ApiConfigService数据并且提供setData($data),setId($id)自定义依赖数据源。
开发者在任何一个服务类中$this->data 获取前端或外部输入数据。
## 创建公共服务
在app/Service/Common 新建公共服务文件
## 创建逻辑服务
在app/Service/LogicModule 新建服务文件。
1. 建议开发者新建逻辑服务,应该考虑功能模块划分,将复杂功能拆分若干细小的模块,减少模块之间耦合性。
2. 建议开发者处理好interface与class 实现类的关系它们之间应该是一对多关系interface属于高级别约束而非实现类方法定义集合。
## 服务之间调用
### 通过make调用
```php
//通过make 调用 TaskService 触发任务
make(TaskService::class)->triggerTaskInner([
'task_key' => $task,
'options' => [
'member_id' => $member_id
]
]);
```
### 通过services() 函数调用
```php
// 通过services() 调用MemberSaveService 执行checkMember
public function add(array $data): array
{
//
/**
* @var MemberSaveService $service
*/
$service = services(MemberSaveService::class);
$this->checkMember($data);
}
```
### 为什么不建议使用容器获取或注解?
使用Di或注解虽然可以高并发提供内存占用以及免去class 重复创建性能损耗但容器或注解会使依赖对象变为单列对象均不能包含状态值。因此破坏了oop 部分设计模式的拓展和应用,反而是限制了服务或对象的拓展以及延申。对于业务逻辑代码每次跟随请求变化,短生命周期更容易开发&维护。
如果某些场景需要长生命周期,应使用协程上下文来保存依赖对象或数据。

11
quick-dev/start.md Normal file
View File

@ -0,0 +1,11 @@
## 确定使用的版本
目前会员存在2.0/2.1 维护分支2.1 分支目前应用mmds(会议与会员管理系统)处于开发阶段开发者在为具体项目使用会员中心建议2.0稳定分支开发新业务(具体应该根据实际判断)
## git-flow
开发者应该遵循gitflow的分支策略这也是code进行mr参考之一方便review者确定当前mr目的性。
**注意**
1. 目前Release 目前暂时不存在。
2. 主分支以版本号进行管理,实现多个版本同时维护。
3. master develop 目前按照固定时间合并最新稳定/开发分支。

21
request.md Normal file
View File

@ -0,0 +1,21 @@
## 请求格式
1. 除文件上传之外其他api请求一律使用**Content-Type: application/json** 提交。
2. 使用path可变变量替换实际请求参数提高api接口安全性和可读性。比如tenant/member/member/{id}
## 路由风格
1. 建议采用RestfulApi定义路由风格。
2. **路由path必须使用小驼峰命名**
### 路由示例
1. 【正确✔】 {host}}/member/order/orders
2. 【错误❌】{host}}/member/order/get_order_list
### 路由定义
1. 推荐在config/routes 定义 方便集中管理
2. 通过路由注解定义

27
response.md Normal file
View File

@ -0,0 +1,27 @@
## 统一响应
目前会员中心工程中app/Controller/Response/AppResponse.php 实现控制器controller统一响应开发者可以controller 实例化AppResponse进行响应切记勿用注解或di注入AppResponse导致AppResponse单列以至于返回数据异常。
代码示例:
```php
/**
* @param ApiLayerService $service
* @return ResponseInterface
* @throws MemberException
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function get(ApiLayerService $service): ResponseInterface
{
$result = $service->inject($this->request)
->handle([
'logic_config' => [
EnumConstService::class,
'getEnum'
]
]);
return (new AppResponse())->setResult($result)->success();
}
```

5
review/baseline.md Normal file
View File

@ -0,0 +1,5 @@
## 基线
如果不满足一下基线规则mr将被无条件驳回
1. 未按照整个项目架构和约定编写功能
2. 未遵循psr 规范&代码未格式化提交
3. 代码包含大量无效代码或测试代码,测试代码应该写入单元测试中

4
review/mr.md Normal file
View File

@ -0,0 +1,4 @@
## 创建MR
1. 自己本地开发分支to版本分支比如v2.0在gitlab 点击merge request 即可
2. 创建之前务必说明mr合并原因
3. 确保提交分支必须从版本分支checkout过来且该分支只存在属于提交作者代码。

26
summary.md Normal file
View File

@ -0,0 +1,26 @@
* 基础
* [架构](directory_structure.md)
* [数据库](database.md)
* [请求](request.md)
* [响应](response.md)
* [异常](exception.md)
* 快速开发
* [开始](quick-dev/start.md)
* [配置](quick-dev/config.md)
* [请求](quick-dev/request.md)
* [控制器](quick-dev/controller.md)
* [服务](quick-dev/service.md)
* [模型](quick-dev/model.md)
* Code Review
* [如何提交MR](review/mr.md)
* [规范基线](review/baseline.md)