From 6ba209c4c780d9f377c4742c0645da32a36eeb83 Mon Sep 17 00:00:00 2001 From: jerry Date: Thu, 31 Dec 2020 00:28:16 +0800 Subject: [PATCH] update docs --- docs/event/index.md | 16 ++++- docs/event/事件分发器.md | 119 +++++++++++++++++++++++++++++++++++++ docs/event/框架注解事件.md | 71 +++++++++++++++++++++- docs/event/路由注解事件.md | 108 ++++++++++++++++++++++++++++++++- mkdocs.yml | 1 + 5 files changed, 312 insertions(+), 3 deletions(-) create mode 100644 docs/event/事件分发器.md diff --git a/docs/event/index.md b/docs/event/index.md index c4955a2c..be3237fe 100644 --- a/docs/event/index.md +++ b/docs/event/index.md @@ -53,4 +53,18 @@ class Hello { 机器人开发过程中常见的 `@CQCommand`,或者是 HTTP 服务器路由绑定 `@RequestMapping` 都是相当于由对应注解代表了事件,而 `@Middleware`,`@Closed` 等这类注解显然不代表任何事件,只能当作这个函数或类的修饰属性而已。代表了事件的注解,我们称之为**注解事件**,它会在某种事件达成条件后触发注解下方的函数本身。 -值得注意的是,注解事件本身概念是我凭空捏造的,我不好解释所以只能创造这么一个词来代指这一抽象的概念,硬要解释的话,大致就好比一个社区里有一个卖牛奶的,有几家人订阅了每日上门送牛奶的服务,只要你打了“给我配送牛奶”的注解,他就会上门。而它送的不止一种奶,可以给你个性化定制,比如让卖牛奶的给你带包糖带瓶水,而描述这个的注解就只能做一个之前注解的修饰。假设你只写了带包糖的注解,没有写给我配送牛奶的注解,那他永远也不会给你送牛奶和糖过来。 \ No newline at end of file +值得注意的是,注解事件本身概念是我凭空捏造的,我不好解释所以只能创造这么一个词来代指这一抽象的概念,硬要解释的话,大致就好比一个社区里有一个卖牛奶的,有几家人订阅了每日上门送牛奶的服务,只要你打了“给我配送牛奶”的注解,他就会上门。而它送的不止一种奶,可以给你个性化定制,比如让卖牛奶的给你带包糖带瓶水,而描述这个的注解就只能做一个之前注解的修饰。假设你只写了带包糖的注解,没有写给我配送牛奶的注解,那他永远也不会给你送牛奶和糖过来。 + +## 阻断事件 + +由于炸毛框架内的注解事件统一由一个通用的事件分发器进行分发,所以你在任何注解事件内都可以用通用的方式阻断当前正在运行的事件。 + +首先就是要记得先 use 事件分发器的类:`use ZM\Event\EventDispatcher;`。 + +```php +EventDispatcher::interrupt(); +EventDispatcher::interrupt($data); // 也可以带返回值,自定义注解事件时有用。 +``` + + + diff --git a/docs/event/事件分发器.md b/docs/event/事件分发器.md new file mode 100644 index 00000000..9ddad1e5 --- /dev/null +++ b/docs/event/事件分发器.md @@ -0,0 +1,119 @@ +# 事件分发器(进阶) + +事件分发器是以上所有注解事件执行函数的一个分发器,如果你在上一章已经学会了如何创建自定义注解,那么本章就来说明如何用内置的事件分发器进行分发自定义事件。 + +如果你不需要了解或自定义有关事件分发的功能,此处可无需阅读。 + +## 属性 + +- 类名:`ZM\Event\EventDispatcher` + +## 方法 + +### EventDispatcher::interrupt() + +阻断当前正在运行的事件,只能在事件内部被调用的函数中实现。 + +### __construct() + +构造方法。 + +```php +EventDispatcher::__construct(string $class = '') +``` + +初始化一个事件分发器,可进行一系列设置,对事件分发做限定。 + +#### 参数 + +`$class`:设置要分发的事件对应的注解类名,支持自定义注解(例如 `CQMessage::class`) + +### setRuleFunction() + +设置函数触发规则判定的函数(就是在执行事件函数前执行的规则判定) + +```php +setRuleFunction(callable $rule = null) +``` + +#### 参数 + +`$rule`:支持回调或闭包。闭包的参数为执行对应事件函数所绑定的注解事件对象。 + +```php +$dispatcher = new EventDispatcher(CustomEvent::class); +$dispatcher->setRuleFunction(function($obj) { + return $obj->name == "zhamao" ? true : false; +}); +``` + +上方的 `$obj` 就是 CustomEvent 类的实例,参数绑定为注解中对应的参数。 + +### setResultFunction() + +设置事件函数返回值处理的回调函数。 + +```php +setReturnFunction(callable $return_func) +``` + +#### 参数 + +`$return_func`:设置事件函数返回值处理的回调函数,回调参数绑定为对应单独事件函数的返回值。 + +```php +$dispatcher = new EventDispatcher(CustomEvent::class); +$dispatcher->setReturnFunction(function($return) { + if (is_string($return)) Console::info("函数返回了 ".$return); +}); +``` + +### dispatchEvents() + +开始分发事件。 + +```php +dispatchEvents(...$params) +``` + +#### 参数 + +自定义参数,这里填入的参数将被填入被分发的函数参数中。 + +```php +$dispatcher->dispatchEvents("foo", "bar"); +``` + +```php +getOption("connect_id") . " 已连接!"); + } +} +``` + +这里的 Console 是终端输出组件,详情见组件一栏对应的文档查询。 + +### 示例2(阻断 Chrome 访问框架时多访问一次的问题) + +```php +getRequest()->server['request_uri'] == '/favicon.ico'",level=200) + */ + public function onRequest() { + EventDispatcher::interrupt(); + } +} +``` + +其中 EventDispatcher 为事件分发器,interrupt 是通用阻断方法,如果你平常只使用阻断,则只需掌握这一个方法即可,`EventDispatcher::interrupt()` 在所有事件内可用。 \ No newline at end of file diff --git a/docs/event/路由注解事件.md b/docs/event/路由注解事件.md index 8fa46da2..08411bfa 100644 --- a/docs/event/路由注解事件.md +++ b/docs/event/路由注解事件.md @@ -122,4 +122,110 @@ public function index($arg) { ## 获取请求参数 GET / POST -炸毛框架支持获取外部 HTTP 请求进来的 GET 和 POST 请求,通过获取 HTTP 请求对象 [`Request`](/advanced/inside-class/) 即可。 \ No newline at end of file +炸毛框架支持获取外部 HTTP 请求进来的 GET 和 POST 请求,通过获取 HTTP 请求对象 [Request](/advanced/inside-class/) 即可。对象具体属性和方法点这个链接进去就行。 + +### 示例 + +=== "获取 GET" + + ```php + /** + * @RequestMapping("/testUrl") + */ + public function testUrl() { + $get = ctx()->getRequest()->get; + if(isset($get["name"])) return "hello, ".$get["name"]; + else return "Unknown name!!"; + } + ``` + +=== "获取 POST(x-www-form-urlencoded)" + + ```php + /** + * @RequestMapping("/testUrl") + */ + public function testUrl() { + $post = ctx()->getRequest()->post; + if(isset($post["name"])) return "hello, ".$post["name"]; + else return "Unknown name!!"; + } + ``` + +=== "获取 JSON POST" + + ```php + /** + * @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!!"; + } + ``` + +## 设置路由请求方式 + +如果想要设置允许请求控制器的 HTTP 请求方式,可以使用方法在控制器中的 `@RequestMapping` 注解配置 `method` 参数,可以是 `GET`,`POST`,`PUT`, `PATCH`,`DELETE`,`OPTIONS`,`HEAD` 中的一个或多个。 + +- 限定 HTTP 方法:`@RequestMapping(method="GET")`,`@RequestMapping(method={"GET","POST"})` + +## 静态文件服务器 + +框架支持了静态文件的访问。如需使用,则需要先到配置文件中配置相应的 `static_file_server` 参数中 `status` 为 `true`。 + +框架分为两种静态文件服务器,一种是全局的静态文件服务器,比如框架部署在 `http://127.0.0.1:20001/` 上通过 HTTP 访问,如果没有访问到 `@RequestMapping` 注解事件注册的路由地址,则会通过 url 自动查找静态文件服务器设置的根路径下面的文件,如果都不存在则会返回 404。 + +### 配置全局静态文件服务器 + +我们假设在你写的框架应用的根目录下,有如下文件和内容: + +``` +resources/html/hello.html (下面是内容) + + + + + +框架文档内容太多了,写不完!!! + + +``` + +然后在 `global.php` 配置文件中静态文件服务器参数为: + +```php +/** 静态文件访问 */ +$config['static_file_server'] = [ + 'status' => true, + 'document_root' => realpath(__DIR__ . "/../") . '/resources/html', + 'document_index' => [ + 'index.html' + ] +]; +``` + +最终,我们通过 `vendor/bin/start server` 等方式,启动框架后,浏览器访问 `http://127.0.0.1:20001/hello.html` 即可获取内容。 + +### 配置局部静态文件服务器 + +所涉及的类的命名空间:`use ZM\Http\StaticFileHandler;` + +局部静态文件服务器一般用于,比如机器人要发送图片,或者给其他 HTTP 服务提供文件下载的接口时可用。我们假设写了一个图片收集的一个静态文件夹区域,将其中一个子路由当作图片静态目录: + +```php +/** + * @RequestMapping("/images/{filename}") + * @param $param + * @return StaticFileHandler + */ +public function staticImage($param) { + Console::info("[下载图片] " . $param["filename"]); + return new StaticFileHandler($param["filename"], "/path/to/your/image_dir/"); +} +``` + +这样当用户访问 `http://框架地址/images/aaa.jpg` 就可以快速地调用此路由下的局部文件服务器功能了。 \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 515274ca..94dd90b5 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -66,6 +66,7 @@ nav: - 框架核心注解事件: event/框架注解事件.md - 中间件注解: event/中间件.md - 自定义注解: event/自定义注解.md + - 事件分发器: event/事件分发器.md - 框架组件: - 框架组件: component/index.md - 进阶开发: