当前位置: 首页 > news >正文

PHP Swoft2 框架精华系列:Controller 控制器组件解析,用法详解

@Controller 注解

/*** 表示路由最基础的前缀,此处为 `/`,RequestMapping 中引入的 @prefix 就是此处的 prefix 值* @Controller("/")* @Controller(prefix="/")* * 可以不用写 `/`, 会自动加上,表示 `/user` 前缀的路由* @Controller("user")*/

路由设置

@RequestMapping 注解,用来获取用户自定义的 http 路由规则。

  • route,字符串类型

    配置路由的路径,可以加入中括号,括起来的部分表示可选路由(可有可无),自定义参数用花括号中间写名字的形式来书写(例:@prefix_index[-{page}]), @prefix 表示 @Controller 注解中的 prefix 值。

  • name,字符串

    路由名称

  • method,数组类型

    决定被请求控制器的操作允许哪种请求方式 POST/GET,或者两者都配置上

  • params

    配置参数的匹配规则,以此来确定路由是否能够匹配。以上方 page 为例: params={"page"="\d+"}

完整示例:

/*** 此规则表示有一个 en_name 的参数,且此参数必须匹配正则 [A-Za-z0-9\-\_]+ 此调路由才能匹配* @RequestMapping(route="{en_name}/", params={"en_name"="[A-Za-z0-9\-\_]+"}, method={"GET"})* 此规则表示,为 / 或者 /index.html 或者 /list-12.html 这种形式* @RequestMapping(route="/[list-{page}.html|index.html]", params={"page"="[2-9]\d*|1\d+"}, method={"GET"})*/

参数传递

  • getParsedBody

    如果请求 body 中有参数,且方法校验规则 @Validate 标签 type 不设置(默认为 body),或者设置为 body,则校验规则会校验 body 中的参数,通过 getParsedBody 方法获取到的为校验规则校验且修改(比如默认值)之后的参数的值。

  • getParsedQuery

    如果请求 query 中有参数,且方法校验规则 @Validate 注解 type 设置为 get,则校验规则会校验 query 中的参数。通过 getParsedQuery 方法获取到的,为校验器校验且修改之后的参数值。

  • getParsedPath

    如果路由参数(路径中参数)有传值,且方法校验规则 @Validate 注解设置 type 为 path,则校验规则会校验path 中的参数。通过此方法获取到的,为校验器校验且修改之后的参数值。

注意:如果没有添加校验器,则获取值为null(详见 ValidatorMiddleware::class)。必须有合法校验器,才有可能通过以上方法获取到值。

  • getParsedBody=getBody

  • getParsedQuery=getQueryParams

  • getParsedPath=getQueryParams

GET 请求,不能通过body 获取参数,如果使用body,校验器校验不到相应的参数,getParsedBody 会直接返回设置的默认值(如有有的话)。

使用

// 通过三个方法均可获得用户传递的参数
$request->getParsedBody();
// 获取单个校验过的数据
$page = $request->parsedBody('page');
$size = $request->parsedBody('size');
// 获取 GET 请求中的所有经过校验的参数数据
$query = $request->getParsedQuery();
// 获取路由参数经过校验器的值
$request->getParsedPath();
/*** 获取内容,并且校验 query 中的参数值* @RequestMapping("list", method="GET")* @Validate(validator=PageListDto::class, fields={"page", "size"}, type="query")** @param Request $request* @param Response $response* @return Response* @throws ApiException*/

校验器源码解析

所有的校验触发,均是通过 http-server 组件中的 httpDispatcher分发器,中设置的 middlewares 来触发的,负责校验的中间件为 ValidatorMiddleware::class

注意分发器中设置的 middlewares 为全局分发器(即所有请求都会触发此处配置的中间件),如果有选择的配置中间件,可以使用 @Middlewares 或者 @Middleware注解(用来标注具体的类,或者方法,只有被标注的对象在请求时候才会触发此中间件)。具体解析请查看中间件的优先级介绍。

/*** @param array $body* @param array $validates* @param array $query* @param array $path** @return array* @throws ValidatorException*/
public function validateRequest(array $body, array $validates, array $query = [], array $path = []): array
{// 循环遍历当前控制器方法上注解的校验规则foreach ($validates as $name => $validate) {$validator = ValidatorRegister::getValidator($name);if (empty($validator)) {throw new ValidatorException(sprintf('Validator(%s) is not exist!', $name));}// 获取当前校验器类型,是系统校验器还是自定义校验器$type     = $validator['type'];$fields   = $validate['fields'] ?? [];$unfields = $validate['unfields'] ?? [];$params   = $validate['params'] ?? [];// 获取当前校验规则的类型(校验get、body、还是path)$validateType = $validate['type'];// 如果校验器类型指定为get,则只校验匹配的get类型参数// Get query paramsif ($validateType === ValidateType::GET) {$query = $this->doValidate($query, $type, $name, $params, $validator, $fields, $unfields);continue;}// 如果校验器类型指定为path,则只校验路由的path参数// Route path paramsif ($validateType === ValidateType::PATH) {$path = $this->doValidate($path, $type, $name, $params, $validator, $fields, $unfields);continue;}// 如果未指定,默认校验body参数$body = $this->doValidate($body, $type, $name, $params, $validator, $fields, $unfields);}return [$body, $query, $path];
}

另外,对于比较复杂的校验,比如数组内部元素的一些具体校验规则,默认是没有提供的,可以通过自定义的校验规则来完成类似的校验。或者直接通过 validate 全局函数来动态进行校验。

// 此函数通过校验 validator 单例对象来触发校验
function validate(array $data,string $validatorName,array $fields = [],array $userValidators = [],array $unfields = []
): array {/* @var Validator $validator */$validator = BeanFactory::getBean('validator');return $validator->validate($data, $validatorName, $fields, $userValidators, $unfields);
}

相关文章:

  • leetcode 1432. 改变一个整数能得到的最大差值 中等
  • PCB设计教程【大师篇】stm32开发板PCB布线(电源部分)
  • 基于C_PSO与BP神经网络回归模型的特征选择方法研究(Python实现)
  • Nginx超快速入门
  • Vite:下一代前端构建工具的革命性突破
  • 对于数据库触发器自动执行的理解
  • 使用VSCode开发MCU,FreeRTOS进Hard_Fault调试
  • idea2024使用卡顿
  • golang-linux环境配置
  • LeetCode 1385.两个数组间的距离值
  • 基于深度强化学习的智能机器人路径规划系统:技术与实践
  • 车载软件架构 --- 汽车中央控制单元HPC软件架构方案实例
  • 用于汽车毫米波雷达的四维高分辨率点云图像
  • 【MPC】模型预测控制笔记 (3):无约束输出反馈MPC
  • Seelen UI 是Windows 桌面开发
  • 深度学习进化史:从神经元的诞生到万亿参数的觉醒
  • 电阻篇---上拉电阻的取值
  • Java垃圾回收机制
  • 1.17 模板引擎EJS
  • 如何可视化机器学习模型:从线性回归到神经网络
  • 重庆市住房和城乡建设厅网站首页/域名访问网站
  • 设计企业公司网站/新闻源软文发布平台
  • 公司网站用什么开发/今日头条热搜榜
  • 如何注册小程序商家/成都搜索优化整站优化
  • ppt做视频的模板下载网站有哪些内容/网店运营的工作内容
  • 批发电商做的好的网站/百度网络营销