ASCII码 ASCII码

PHP 基于 SW-X 框架,搭建高性能API架构(一)

发布于:2022-02-18 10:48:15  栏目:技术文档

前言

官网地址:SW-X框架-专注高性能便捷开发而生的PHP-SwooleX框架

希望各大佬举起小手,给小弟一个star:https://github.com/swoolex/swoolex

架构图谱

版本更新规则

每个新版本迭代以v1.0.1的大中小版本起名,应用代码存储在/app/http/版本号目录下,.改为_

新版本需要拷贝上一个版本的可用代码,进行修改,并保留原代码。

版本发布

每个新版本开发完成后,需要在/box/route.php文件中,修改镜像路由地址,使其生效到对外接口地址中,如下:

  1. use \x\Route;
  2. // 对前端开放版本映射
  3. Route::mirror([
  4. '/v1_0_1/controller/' => '/api/',
  5. ]);

控制器命名

控制器统一存储在/app/http/版本号/controller/目录下,以一个接口一个文件的方法进行定义。

例如,需要编写一个Shop模块的create接口,那应该创建文件如下:

文件地址:/app/http/版本号/controller/shop/create.php,代码如下:

  1. namespace app\http\v1_0_1\controller\shop;
  2. use x\controller\Http;
  3. class create extends Http
  4. {
  5. /**
  6. * index方法默认会在路由中忽略
  7. */
  8. public function index() {
  9. return $this->fetch('演示控制器');
  10. }
  11. }

未通过镜像路由映射前的访问地址是:/v1_0_1/controller/shop/create

通过镜像路由映射后的访问地址是:/api/shop/create

请求类型限制

对于GET|POST|AJAX请求类型的限制,统一使用@Get@Post@Ajax的方式声明。

例如限制只允许POST-AJAX问题的接口:

  1. namespace app\http\v1_0_1\controller\shop;
  2. use x\controller\Http;
  3. class create extends Http
  4. {
  5. /**
  6. * index方法默认会在路由中忽略
  7. * @Post
  8. * @Ajax
  9. */
  10. public function index() {
  11. return $this->fetch('演示控制器');
  12. }
  13. }

参数默认值预设

控制器中,禁止使用以下习惯申明参数默认值:

  1. namespace app\http\v1_0_1\controller\shop;
  2. use x\controller\Http;
  3. class create extends Http
  4. {
  5. /**
  6. * index方法默认会在路由中忽略
  7. */
  8. public function index() {
  9. $param = \x\Request::get();
  10. // 场景一
  11. if (!isset($param['status'])) $param['status'] = 1;
  12. // 场景二
  13. $param['status'] = (isset($param['status']) == false) ? 1 : $param['status'];
  14. // 场景三
  15. $param['status'] = $param['status'] ??1;
  16. }
  17. }

对于以上isset()判断参数是否未传递后,设置默认值的场景,要统一使用@Param注解提前声明,例如:

  1. namespace app\http\v1_0_1\controller\shop;
  2. use x\controller\Http;
  3. class create extends Http
  4. {
  5. /**
  6. * index方法默认会在路由中忽略
  7. * @Param(name="status", value="1")
  8. */
  9. public function index() {
  10. $param = \x\Request::get();
  11. // 如果未提交的情况下,可以直接获取到默认值
  12. var_dump($param['status']);
  13. }
  14. }

警告:@Param注解参数预设,只对isset()场景有效,empty()is_null()等为空场景无效。

表单校验

禁止在控制器中编写表单格式校验的任何代码,表单校验需要统一在/box/validate/目录中创建校验器。

校验器的具体使用方法,可以参考SW-X官网文档:校验器。

例如创建一个司机相关的校验器,文件:/boxx/validate/Driver.php,代码如下,包含了3种校验场景:

  1. namespace box\validate;
  2. use x\Validate;
  3. class Driver extends Validate
  4. {
  5. // 定义字段对应的规则
  6. protected $rule = [
  7. 'id' => 'require|int',
  8. 'driver_sn' => 'require|between:1,120',
  9. 'phone' => 'require|phone'
  10. ];
  11. // 自定义错误值声明
  12. protected $message = [
  13. 'id.require' => '{:preset}未提交',
  14. 'id.int' => '{:preset}不是整数格式',
  15. 'driver_sn.require' => '{:preset}未提交',
  16. 'driver_sn.between' => '{:preset}长度只能在{0}-{1}位之间',
  17. 'phone.require' => '{:preset}未提交',
  18. 'phone.phone' => '{:preset}格式错误',
  19. ];
  20. // 可以设置message时的字段别名,会把{字段名}占位符替换后一起抛出
  21. protected $alias = [
  22. 'id' => '司机ID',
  23. 'driver_sn' => '司机编号',
  24. 'phone' => '司机手机号码',
  25. ];
  26. // 场景定义
  27. protected $scene = [
  28. // 编辑
  29. 'edit' => ['id','driver_sn', 'phone'], // 需要校验的字段
  30. // 新增
  31. 'create' => ['driver_sn', 'phone'],
  32. // 查询表单
  33. 'select' => [
  34. 'field' => ['driver_sn', 'phone'], // 需要校验的字段
  35. 'delete_rule' => [ // 删除校验规则
  36. 'driver_sn' => 'require',
  37. 'phone' => 'require',
  38. ],
  39. ],
  40. ];
  41. }

创建完成后,使用@Validate注解,在控制器中进行场景绑定:

  1. namespace app\http\v1_0_1\controller\shop;
  2. use x\controller\Http;
  3. class create extends Http
  4. {
  5. /**
  6. * index方法默认会在路由中忽略
  7. * @Validate(class="\box\validate\Driver", scene="create")
  8. */
  9. public function index() {
  10. return $this->fetch('演示控制器');
  11. }
  12. }

权限校验

API统一绑定了全局中间件/box/middleware/Auth.php,如果需要跳过权限校验的Api,需要修改该中间件内部的$_skip成员属性即可。

Api-Restful管理

API统一使用Restful模块进行管理,目录在/restful/目录下,状态码与返回值说明存放在/restful/default/目录下。

例如现在要添加一个DRIVER_ERROR的状态码,对应CODE为30001,MSG为司机不存在

同时,该状态码下,还有一个MSG为司机余额不足

那么应该这样定义,修改/restful/default/code.php文件为如下代码:

  1. return [
  2. // default表示默认使用的msg
  3. 'DRIVER_ERROR' => [
  4. 'default' => '司机不存在', // 默认值
  5. 'balance_not' => '司机余额不足',
  6. ]
  7. ];

在控制器中就可以这样使用:

  1. namespace app\http\v1_0_1\controller\shop;
  2. use x\controller\Http;
  3. use x\Restful;
  4. class create extends Http
  5. {
  6. /**
  7. * index方法默认会在路由中忽略
  8. */
  9. public function index() {
  10. // 会默认使用default的MSG
  11. return Restful::code(Restful::DRIVER_ERROR())->callback();
  12. // 也可以指定抛出的MSG
  13. return Restful::code(Restful::DRIVER_ERROR())->msg('balance_not')->callback();
  14. // 如果要抛出数据集
  15. return Restful::code(Restful::DRIVER_ERROR())->data('数据集')->callback();
  16. }
  17. }

更多关于Restful的使用方法,可以参考SW-X官网文档:Restful支持。

关于Restful返回值强类型转换

系统会自动把返回值中字符串类型(string)的intfloat数据转换回真实类型。

空字符串,转换回null

注意,如果是string*.00会被强制转换成int类型的*

也就是0.00会被转成018.00会被转成18,这是PHP数据结构的先天上问题。

例如:

  1. {
  2. "code": 0,
  3. "msg": "请求成功",
  4. "data": {
  5. "user_id": "100",
  6. "money": "19.01",
  7. "list": [
  8. {
  9. "id": "1",
  10. "money": "0.00"
  11. },
  12. {
  13. "id": "2",
  14. "money": "18.00"
  15. }
  16. ],
  17. "region_id": ""
  18. }
  19. }

会被转换成:

  1. {
  2. "code": 0,
  3. "msg": "请求成功",
  4. "data": {
  5. "user_id": 100,
  6. "money": 19.01,
  7. "list": [
  8. {
  9. "id": 1,
  10. "money": 0
  11. },
  12. {
  13. "id": 2,
  14. "money": 18
  15. }
  16. ],
  17. "region_id": null
  18. }
  19. }

数据模型

控制器中,禁止直接使用Db基类操作,任何数据库相关的操作,都应该统一创建对应的Model类进行逻辑采集处理。

Model的存储目录为:/app/http/版本号/model/目录下。

例如司机表的新增操作,应该创建一个DriverModel.php文件:

  1. namespace app\http\v1_0_1\model;
  2. use x\Model;
  3. class DriverModel extends Model
  4. {
  5. // 添加司机
  6. public function add($data) {
  7. return $this->insert($data);
  8. }
  9. // 编辑司机
  10. public function edit($data) {
  11. return $this->where('id', $data['id'])->update($data);
  12. }
  13. }

下一章节,我们再来开始,一步步的搭建整个API项目架构。

相关推荐
阅读 +