# 路由注解事件

炸毛框架提供了一个简易但是高效易用的 HTTP 路由注解,你可以使用路由功能来开发任何 Web 应用微服务、API 接口、中间件等。

开发提示

本章节涉及的路由和控制器概念可能和其他传统框架有一些出入,而且炸毛框架非绝对根据 PSR 标准进行开发,目的是使用上一些常见的东西尽可能地灵活和不啰嗦。

# 控制器和路由

Controller 和 Route 为路由注解事件的核心注解事件,其中 Controller 的注解事件为 @Controller,Route 的注解事件为 @RequestMapping

# Controller()

# 属性

类型
名称 @Controller
触发前提 当路由 url 匹配到时进入触发
命名空间 ZM\Annotation\Http\Controller
适用位置
返回值处理 对类注解修饰,无返回值

# 参数

参数名称 参数范围 用途 默认
prefix string,必需 控制器的 url

# RequestMapping()

# 属性

类型
名称 @RequestMapping
触发前提 当路由 url 匹配到时进入触发
命名空间 ZM\Annotation\Http\RequestMapping
适用位置 方法
返回值处理 返回类型是 string 时,自动调用 HTTP 响应并返回 200 状态码

# 参数

参数名称 参数范围 用途 默认
route string,必需 控制器的 url
name string 路由的名称
request_method array,限定 RequestMethod::GET 等常量 限制激活路由的 HTTP 方法 [RequestMethod::GET,RequestMethod::POST]
params array,当路由中含有如 {id} 类似的动态路由时,会动态改变 动态参数的路由参数值的绑定 []

# 函数调用参数

  • $param:如果路由中存在变量(动态路由),则会把动态路由所匹配的参数放入 $param 数组中。
/**
 * @RequestMapping(route="/test/{ass}")
 */
public function testName($param) {
    return "Your name is ".($param["ass"] ?? "unknown");
} 
1
2
3
4
5
6

# 路由示例

代码

<?php
namespace Module\Example;

use ZM\Annotation\Http\Controller;
use ZM\Annotation\Http\RequestMapping;
/**
 * @Controller("/api")
 */
class Hello {
	/**
	 * @RequestMapping("/index")
	 */
	public function index(){
		ctx()->getResponse()->end("This is API index page"); // 使用上下文获取响应对象
	}
	/**
	 * @RequestMapping("/ping")
	 */
	public function ping(){
		return "pong"; // 直接返回字符串
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

效果

效果描述

当访问浏览器的 http://localhost:20001/api/index 时,浏览器会返回 This is API index page,当访问 /api/ping 的 url 时,浏览器会返回 pong

/            -> 无任何路由
/api/index   -> Hello->index
/api/ping    -> Hello->ping
1
2
3

提示

@Controller/ 的时候,效果和不写是一样的,@RequestMapping//index/inside 等多级路由也是可以的。

# 绑定参数

@RequestMapping 中,不仅可以写静态的路由地址,也可以写绑定的参数。例如:@RequestMapping(route="/index/{name}"),则访问 /index/xxx 的时候,你在函数方法内可以这样获取此参数:

/**
 * @RequestMapping("/index/{name}")
 */
public function index($arg) {
    return "Your param 'name' is ".$arg["name"];
}
1
2
3
4
5
6

# 获取请求参数 GET / POST

炸毛框架支持获取外部 HTTP 请求进来的 GET 和 POST 请求,通过获取 HTTP 请求对象 Request 即可。对象具体属性和方法点这个链接进去就行。

# 示例

# 获取 GET

/**
 * @RequestMapping("/testUrl")
 */
public function testUrl() {
  $get = ctx()->getRequest()->get;
  if(isset($get["name"])) return "hello, ".$get["name"];
  else return "Unknown name!!";
}
1
2
3
4
5
6
7
8

# 获取 POST(x-www-form-urlencoded)

/**
 * @RequestMapping("/testUrl")
 */
public function testUrl() {
  $post = ctx()->getRequest()->post;
  if(isset($post["name"])) return "hello, ".$post["name"];
  else return "Unknown name!!";
}
1
2
3
4
5
6
7
8

# 获取 JSON POST

/**
 * @RequestMapping("/testUrl")
 */
public function testUrl() {
  $post = ctx()->getRequest()->rawContent();
  $json = json_decode($post, true);
  if ($json === null) return "Invalid json data!";
  if(isset($json["name"])) return "hello, ".$json["name"];
  else return "Unknown name!!";
}
1
2
3
4
5
6
7
8
9
10

# 设置路由请求方式

如果想要设置允许请求控制器的 HTTP 请求方式,可以使用方法在控制器中的 @RequestMapping 注解配置 method 参数,可以是 GETPOSTPUT, PATCHDELETEOPTIONSHEAD 中的一个或多个。

  • 限定 HTTP 方法:@RequestMapping(request_method="GET")@RequestMapping(request_method={"GET","POST"})

注意

此处是 request_method,而不是 method,因为炸毛框架的注解 method 是保留属性,写错会出现问题。

# 静态文件服务器

框架支持了静态文件的访问。如需使用,则需要先到配置文件中配置相应的 static_file_server 参数中 statustrue

框架分为两种静态文件服务器,一种是全局的静态文件服务器,比如框架部署在 http://127.0.0.1:20001/ 上通过 HTTP 访问,如果没有访问到 @RequestMapping 注解事件注册的路由地址,则会通过 url 自动查找静态文件服务器设置的根路径下面的文件,如果都不存在则会返回 404。

# 配置全局静态文件服务器

我们假设在你写的框架应用的根目录下,有如下文件和内容:

resources/html/hello.html (下面是内容)
<html>
<head>
<meta charset="utf-8">
</head>
<body>
框架文档内容太多了,写不完!!!
</body>
</html>
1
2
3
4
5
6
7
8
9

然后在 global.php 配置文件中静态文件服务器参数为:

/** 静态文件访问 */
$config['static_file_server'] = [
    'status' => true,
    'document_root' => realpath(__DIR__ . "/../") . '/resources/html',
    'document_index' => [
        'index.html'
    ]
];
1
2
3
4
5
6
7
8

最终,我们通过 vendor/bin/start server 等方式,启动框架后,浏览器访问 http://127.0.0.1:20001/hello.html 即可获取内容。

# 配置局部静态文件服务器

所涉及的类的命名空间:use ZM\Http\StaticFileHandler;

局部静态文件服务器一般用于,比如机器人要发送图片,或者给其他 HTTP 服务提供文件下载的接口时可用。我们假设写了一个图片收集的一个静态文件夹区域,将其中一个子路由当作图片静态目录:

/**
 * @RequestMapping("/images/{filename}")
 * @param array $param
 * @return StaticFileHandler
 */
public function staticImage(array $param) {
  Console::info("[下载图片] " . $param["filename"]);
  return new StaticFileHandler($param["filename"], "/path/to/your/image_dir/");
}
1
2
3
4
5
6
7
8
9

这样当用户访问 http://框架地址/images/aaa.jpg 就可以快速地调用此路由下的局部文件服务器功能了。