# think-restful **Repository Path**: steve_ma/think-restful ## Basic Information - **Project Name**: think-restful - **Description**: 自定义一个restful服务-方便快捷的输出restful接口-自己封装的一些小玩意 我自己的开发环境: ThinkPHP:8.0 PHP:8.1 理论上 php >= 7.1 thinkPHP >= 6.0 都可以使用 - **Primary Language**: PHP - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2023-08-08 - **Last Updated**: 2024-04-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # think-restful #### 介绍 自定义一个restful服务-方便快捷的输出restful接口-自己封装的一些小玩意 我自己的开发环境: ThinkPHP:8.0 PHP:8.1 理论上 php >= 7.1 thinkPHP >= 6.0 都可以使用 ### 安装教程 ```shell # 安装 $ composer require stevema/think-restful ``` ### 使用说明 ```php # 由于TP框架的Route太乱了 目前只支持TP的单应用模式 # 命令行执行代码 # $ php think make:restful api/v3/config # 如果不了解的话可以添加参数 -f 输出的文件会携带各种注释 # $ php think make:restful api/v3/config -f # 会自动生成对应的文件-输出 # Model:app\model\api\v3\ConfigModel created successfully. # Validate: /app/validate/api/v3/ConfigValidate.php # Resource: /app/resource/api/v3/ConfigResource.php # Filter: /app/filter/api/v3/ConfigFilter.php # Controller: /app/controller/api/v3/ConfigController.php # 然后配置一下路由接口就可以访问了 # 在 route/app.php 中添加路由 Route::group('config', function($prefix = 'config.'){ Route::get('',\app\controller\api\v3\ConfigController::class.'@index') ->name($prefix.'index'); Route::post('',\app\controller\api\v3\ConfigController::class.'@save') ->name($prefix.'save'); Route::get('/',\app\controller\api\v3\ConfigController::class.'@read') ->name($prefix.'read'); Route::put('/',\app\controller\api\v3\ConfigController::class.'@update') ->name($prefix.'update'); Route::patch('/',\app\controller\api\v3\ConfigController::class.'@patch') ->name($prefix.'patch'); Route::delete('/',\app\controller\api\v3\ConfigController::class.'@delete') ->name($prefix.'delete'); }); # 具体使用方式向下看 ``` ### 目录说明 ``` ├─ src │ ├─ commands # 命令 │ │ ├─ stubs # 生成的文件模版 │ │ └─ Create.php # make:restful 命令配置 │ ├─ traits # 方法引入 │ │ └─ Delete.php # 删除接口 │ │ └─ Index.php # 列表接口 │ │ └─ Read.php # 详情接口 │ │ └─ Restore.php # 恢复软删除接口 │ │ └─ Save.php # 新建接口 │ │ └─ Update.php # 修改接口 │ │ └─ SoftDelete.php # 软删除-微调-支持int的软删除 │ │ └─ UseTableNameAsMorphClass.php # 多对多关系用到的- │ └─ RestfulController.php # 公共controller │ └─ RestfulException.php # 异常文件 │ └─ RestfuklFilter.php # 列表筛选 │ └─ RestfulFilterResource.php # 列表分页解释器 │ └─ RestfulResource.php # 模型解释器 │ └─ RestfulServer.php # Restful服务提供者-把命令注册到项目中 └─ composer.json # 配置 ``` ### 使用方式 #### 模型-Model ```php # 模型就是TP的模型-具体去看TP文档 # 注意 模型对应的表一定要对 可以通过 $table 来绑定 class ConfigModel extends Model { // 设置当前模型对应的完整数据表名称 protected $table = 'sm_configs'; } ``` #### 模型解释器-Resource ```php # 模型在不同的列表或者不同的场景下所显示的字段是不同的 # 所以写了这么一个东西-可以直接拿来用-最后用到的都是toArray方法 class ConfigResource extends RestfulResource{ /** * 输出列表记录的- index方法 * $this->instance 是model的单条数据 或是数据集 * @return mixed */ public function toIndex(){ // return $this->instance->toArray(); return parent::toIndex(); } /** * 输出单条记录的- read方法 * $this->instance 是model的单条数据 或是数据集 * 数据集 你可以使用模型的hidden/visible/append/withAttr方法进行数据集的输出处理 * @return mixed */ public function toRead(){ // 你可以使用模型的hidden/visible/append/withAttr方法进行数据集的输出处理 // return $this->instance->toRead(); return parent::toRead(); } } ``` #### 数据验证-Validate ```php # 数据验证也是TP的Validate 我这里只是用到了scene 固定三个场景 # save 新增数据 update 修改数据 patch 部分修改数据 起名和controller对应的方法名一致 # 可以随意拓展 # patch 场景由于是部分修改 有些字段的require 就要去掉 可以添加方法 scenePatch class ConfigValidate extends Validate { protected $rule = []; protected $message = []; protected $scene = [ 'save' => [], 'update' => [], 'patch' => [], ]; // patch 场景由于是部分修改 有些字段的require 就要去掉 // public function scenePatch() // { // return $this->remove('field1', 'require') // ->remove('field2', 'require'); // } } ``` #### 列表筛选排序分页-Filter ```php # 列表筛选排序分页 专门为了接口通过url传参用到的 # 排序规则 DEFAULT_ORDERING='-id' 默认id倒序 # ACCEPT_FILTER_KEYS = [] 这里是参与检索的字段 - 可以在下面定义检索方法 # 不定义方法默认就是 $query->where($key, '=', $value); # public function name_filter($key, $value){ # $query = $this->getQuery(); # $query->where($key, 'like', "%{$value}%"); # } # 提供了几种分页方法 # noPaginate 无分页 、 paginate 默认分页 、 simplePaginate 简单分页 、 paginateX cursor分页 # 注意:paginateX 分页的时候 ordering一定要是主键- 不然会出现不可预知的错误 # 注意:FILTER_RESOURCE 是分页的解释器 - 默认没有 需要的话可以自己加一个 class ConfigFilter extends RestfulFilter{ /** * 默认排序规则 多个中间加逗号 比如 "-type,-id" */ protected const DEFAULT_ORDERING = '-id'; /** * 允许的检索字段 keys 空则不限制 所有的参数都可以参与过滤 * 注意这里只有id 没有前面的-号 */ protected const ACCEPT_ORDERINGS = ["id", 'create_at']; /** * 允许的检索字段 keys 空则不限制 所有的参数都可以参与过滤 */ protected const ACCEPT_FILTER_KEYS = []; /** * 分页用到的页码参数key */ protected const KEY_PAGE = 'page'; /** * 分页用到的每页显示条数参数key */ protected const KEY_SIZE = 'size'; /** * 分页用到的 cursor 参数key */ protected const KEY_CURSOR = 'cursor'; /** * 默认页数 */ protected const DEFAULT_PAGE = 1; /** * 默认条数 */ protected const DEFAULT_SIZE = 15; /** * 排序用到的参数key * paginateX 分页的时候 ordering一定要是主键- 不然会出现不可预知的错误 */ protected const KEY_ORDERING = 'ordering'; /** * 分页方法 nopaginate 无分页 、 paginate 默认分页 、 simplePaginate 简单分页 、 paginateX cursor分页 */ protected const PAGINATOR = 'paginateX'; /** * 资源解释器 - 返回之前重新编辑一下输出的数组 * 默认提供一个 可以用 也可以不用 * \Stevema\Restful\Filters\RestfulFilterResource::class */ protected const FILTER_RESOURCE = null; /** * 检索 自定义字段 比如 name字段 方法名是 name_filter * 可以获取 Query 后执行操作 * $query = $this->getQuery(); * @param $key 字段名 * @param $value 值 * @return void */ // public function name_filter($key, $value){ // $query = $this->getQuery(); // $query->where($key, 'like', "%{$value}%"); // } } ``` #### 控制器-Controller ```php # 控制器 use Index,Read,Update,Delete,Save; 需要哪个use哪个 每个可以对应一个或多个路由 # FILTERS = \app\filter\api\v2\ConfigFilter::class; 筛选、分页、排序插件-最好不要没有 # MODEL =\app\model\api\v2\ConfigModel::class; 数据库模型-这个要是没有和数据库就没关系了 # VALIDATE = \app\validate\api\v2\ConfigValidate::class 验证插件-可以没有 # RESOURCE = \app\resource\api\v2\ConfigResource::class 数据模型解释器-可以没有 # 如果你对我给出的这些控制器方法不满意 可以重写它 比如 class ConfigController extends RestfulController { use Index,Read,Update,Delete,Save; # 重写这个删除方法 public function performDelete($currentModel){ // $result = $currentModel->delete(); # 这里重写删除为假删除 $result = $currentModel->save(['is_del' => 1]); return $result; } } ``` #### 软删除-SoftDelete ```php # traits目录下 有SoftDelete.php文件 # 当Model引用它 可以配置软删除-微调后可以使软删除字段为int型 注意 如果使用了软删除 schema中一定要有软删除的字段 #use SoftDelete; #// 软删除字段 #protected $deleteTime = 'is_del'; #// 软删除字段默认值 #protected $defaultSoftDelete = 0; #// 自己写的-软删除被删除的值 #protected $deleteSoftDelete = 1; #$// 设置字段信息 #protected $schema = [ # ... # 'is_del' => 'int', #]; use stevema\restful\traits\SoftDelete; class TagModel extends Model { use SoftDelete; // 软删除字段 protected $deleteTime = 'is_del'; // 软删除字段默认值 protected $defaultSoftDelete = 0; // 自己写的-软删除被删除的值 protected $deleteSoftDelete = 1; // 设置当前模型对应的完整数据表名称 protected $table = 'sm_tags'; // 设置字段信息 protected $schema = [ 'id' => 'int', 'name' => 'string', 'create_time' => 'datetime', 'update_time' => 'datetime', 'is_del' => 'int', ]; // 模型允许写入的字段列表(数组) protected $fields = [ 'name' ]; } ``` ### 备注