zhamao-framework/docs/event/framework-annotations.md
jerry 6155236d3c update to v2.4.0 (build 399)
add CheckConfigCommand.php
add config update record docs
adjust swoole version to 4.5.0
fix stop and reload bugs
add $_running_annotation
add remote terminal
update global config
add timer tick exception handler
add zm_xxx global functions
add isAtMe(), splitCommand(), matchCommand() function for MessageUtil
add workerAction(), sendActionToWorker(), resumeAllWorkerCoroutines() functions for ProcessManager
optimize CQCommand match function
add custom TerminalCommand annotation
add TuringAPI
add getReloadableFiles() function for ZMUtil
2021-03-24 23:34:46 +08:00

17 KiB
Raw Blame History

框架核心注解事件

框架核心注解事件区别于机器人和路由注解事件,这里框架注解事件都是直接或封装调用 Swoole 的回调事件的,所以对一些比较底层或者基础的操作都在这里做,例如收到 HTTP 或 WebSocket 连接后执行的事件函数。

OnOpenEvent()

当有 WebSocket 连接接入框架时,触发注解事件。

属性

类型
名称 @OnOpenEvent
触发前提 当有 WebSocket 连接接入框架时,触发注解事件
命名空间 ZM\Annotation\Swoole\OnOpenEvent
适用位置 方法
返回值处理

参数

参数名称 参数范围 用途 默认
connect_type string 限定连接的类型,通过炸毛框架支持的方式指定传入类型,详见 进阶 - 接入 WebSocket 客户端

用法

@OnOpenEvent("foo")
@OnOpenEvent(connect_type="default")

事件绑定参数

$conn: ConnectionObject 类型,返回一个当前 WS 连接的连接对象。

OnCloseEvent()

当有 WebSocket 连接断开框架时,触发注解事件。

属性

类型
名称 @OnCloseEvent
触发前提 当有 WebSocket 连接断开框架时,触发注解事件
命名空间 ZM\Annotation\Swoole\OnCloseEvent
适用位置 方法
返回值处理

参数

参数名称 参数范围 用途 默认
connect_type string 限定连接的类型,通过炸毛框架支持的方式指定传入类型,详见 进阶 - 接入 WebSocket 客户端

用法

@OnCloseEvent("foo")
@OnCloseEvent(connect_type="default")

事件绑定参数

$conn: ConnectionObject 类型,返回一个当前 WS 连接的连接对象。

OnRequestEvent()

当 HTTP 请求接入时,触发注解事件。

属性

类型
名称 @OnRequestEvent
触发前提 当 HTTP 请求接入时,触发注解事件
命名空间 ZM\Annotation\Swoole\OnRequestEvent
适用位置 方法
返回值处理

参数

参数名称 参数范围 用途 默认
rule string,必须是可执行且返回 bool 的 PHP 代码 前置条件 rule 为 true
level int 事件优先级(越大越靠前) 20

OnMessageEvent()

当有 WebSocket 连接接入框架后发送过来消息,触发注解事件。

属性

类型
名称 @OnMessageEvent
触发前提 当有 WebSocket 连接接入框架后发送过来消息,触发注解事件
命名空间 ZM\Annotation\Swoole\OnMessageEvent
适用位置 方法
返回值处理

参数

参数名称 参数范围 用途 默认
connect_type string 限定连接的类型,通过炸毛框架支持的方式指定传入类型,详见 进阶 - 接入 WebSocket 客户端

用法

@OnMessageEvent("foo")
@OnMessageEvent(connect_type="default")

事件绑定参数

$conn: ConnectionObject 类型,返回一个当前 WS 连接的连接对象。

OnPipeMessageEvent()

当有 其他 Worker 进程通信发来指令激活响应。2.2.0 版本可用)

属性

类型
名称 @OnPipeMessageEvent
触发前提 当有 WebSocket 连接接入框架后发送过来消息,触发注解事件
命名空间 ZM\Annotation\Swoole\OnPipeMessageEvent
适用位置 方法
返回值处理

参数

参数名称 参数范围 用途 默认
action string 限定动作名称

用法

@OnPipeMessageEvent("foo")
@OnPipeMessageEvent(action="bar")

事件绑定参数

$data: 数组,内容如下:

[
    "action" => "你的上面的名称",
    ... //其他自己发送时随便定义,带什么都行
]

OnSwooleEvent()

绑定 Swoole 所相关的事件,例如 WebSocket 接入、收到 WS 消息、关闭 WS 连接HTTP 请求到达等。这个是旧的统一的 Swoole 事件分发注解。请尽量使用上面几个新的注解

属性

类型
名称 @OnSwooleEvent
触发前提 当参数指定的 type 对应的事件被触发后激活
命名空间 ZM\Annotation\Swoole\OnSwooleEvent
适用位置 方法
返回值处理

注解参数

参数名称 参数范围 用途 默认
type string,支持填入 openrequestclosemessage 限定事件的类型,必填
rule string,必须是可执行且返回 bool 的 PHP 代码 例如判断连接是否为 QQ 机器人(connectIsQQ() rule 为 true
level int 事件优先级(越大越靠前) 20

事件绑定参数

$conn: ConnectionObject 类型,返回一个当前 WS 连接的连接对象。

OnStart()

在框架加载后执行的注解事件,用于初始化 Worker 进程,此注解事件会在 Worker 进程中执行,且可以指定在哪个 Worker 进程中执行。

属性

类型
名称 @OnStart
触发前提 在框架加载后激活
命名空间 ZM\Annotation\Swoole\OnStart
适用位置 方法
返回值处理

注解参数

参数名称 参数范围 用途 默认
worker_id int,要在哪个 Worker 进程上执行,默认为 0范围是 0{你设定的 Worker 数量-1},如果是 -1 的话,则会在所有 Worker 进程上触发。 限定只执行的 Worker 进程

OnTick()

在框架加载后创建毫秒计时器。

属性

类型
名称 @OnTick
触发前提 在框架加载后激活
命名空间 ZM\Annotation\Swoole\OnTick
适用位置 方法
返回值处理

注解参数

参数名称 参数范围 用途 默认
tick_ms int必填,间隔的毫秒数,例如 1 秒间隔为 1000,范围大于 0小于 86400000。
worker_id int,要在哪个 Worker 进程上执行,默认为 0范围是 0{你设定的 Worker 数量-1},如果是 -1 的话,则会在所有 Worker 进程上触发。 限定只执行的 Worker 进程

OnTask()

定义一个在工作进程中运行的任务函数。详情见 进阶 - 使用 TaskWorker 进程处理密集运算

属性

类型
名称 @OnTask
触发前提 在框架加载后激活
命名空间 ZM\Annotation\Swoole\OnTask
适用位置 方法
返回值处理 有,返回 Worker 进程的结果

注解参数

参数名称 参数范围 用途 默认
task_name string必填,任务函数的名称,不建议重复。
rule 设置触发前提PHP 代码,返回 bool 值即可,参考 OnRequestEvent 限定是否执行

OnSetup()

在框架加载前执行的代码。此部分代码是在主进程执行的,不可在此事件中使用任何协程相关的功能。

比如我们要改变所有进程的 ini 设置,这时使用 @OnStart(-1) 这样只设置了 Worker 进程的内容,而主进程和管理进程无法被覆盖到。如果需要设置全局的一些配置,务必在此 @OnSetup 注解下执行。

属性

类型
名称 @OnSetup
触发前提 在框架加载前激活
命名空间 ZM\Annotation\Swoole\OnSetup
适用位置 方法
返回值处理

注解参数

无。

TerminalCommand()

添加一个远程终端的自定义命令。2.4.0 版本起可用)

属性

类型
名称 @TerminalCommand
触发前提 连接到远程终端可触发
命名空间 ZM\Annotation\Command\TerminalCommand
适用位置 方法
返回值处理

注解参数

参数名称 参数范围 默认
command string必填,命令字符串
description string,要显示的帮助文本

示例1机器人连接框架后输出信息

<?php
namespace Module\Example;
use ZM\Annotation\Swoole\OnOpenEvent;
use ZM\ConnectionManager\ConnectionObject;
use ZM\Console\Console;
class Hello {
    /**
 	 * 在机器人客户端连接框架后向终端输出信息
 	 * @OnOpenEvent("qq")
	 * @param $conn
 	 */
	public function onConnect(ConnectionObject $conn) {
	    Console::info("机器人 " . $conn->getOption("connect_id") . " 已连接!");
	}
}

这里的 Console 是终端输出组件,详情见组件一栏对应的文档查询。

示例2阻断 Chrome 访问框架时多访问一次的问题)

<?php
namespace Module\Example;
use ZM\Annotation\Swoole\OnSwooleEvent;
use ZM\Event\EventDispatcher;
class Hello {
    /**
     * 阻止 Chrome 自动请求 /favicon.ico 导致的多条请求并发和干扰
     * @OnRequestEvent(rule="ctx()->getRequest()->server['request_uri'] == '/favicon.ico'",level=200)
     */
    public function onRequest() {
        EventDispatcher::interrupt();
    }
}

其中 EventDispatcher 为事件分发器interrupt 是通用阻断方法,如果你平常只使用阻断,则只需掌握这一个方法即可,EventDispatcher::interrupt() 在所有事件内可用。

示例3接收 WS 客户端发来的数据)

接入 WebSocket 客户端

示例4使用 OnStart 给所有 Worker 进程写入缓存提速)

如果你有一些数据存到了文件、数据库中,且是只读不写的,那么就可以使用此方法将这个文件或者数据库的内容读入 Worker 进程的内存中进行使用来提速。

假设我们有一个大文件 json里面存着一份题库例如

{
    "0": {
        "question": "法的调整对象是( )。",
        "answer": {
            "A": "行为关系",
            "B": "思想关系",
            "C": "利益关系",
            "D": "各种社会资源"
        },
        "key": "A",
        "answer_type": 0
    },
    "1": {
        "question": "法律与其他社会规范的区别在于( )。",
        "answer": {
            "A": "是调整人们行为的规范",
            "B": "有约束力",
            "C": "由国家强制力保证执行",
            "D": "规定制裁措施"
        },
        "key": "C",
        "answer_type": 0
    },
    .....
}

那么我们可以使用 OnStart 来实现一个,将此文件读取到每个 Worker 进程中,并且快速取用的功能(以下做了一个简单的查题功能):

<?php
namespace Module\Example;
use ZM\Annotation\Swoole\OnStart;
use ZM\Annotation\CQ\CQCommand;
use ZM\Console\Console;
class Hello {
    public static $tiku = [];
    /**
     * @OnStart(-1)
     */
    public function onStart() { // 注意,此函数将会在每个 Worker 执行一次
        $file = file_get_contents("tiku.json"); //从文件读取json
        $json = json_decode($file, true); //json解析
        Hello::$tiku = $json; //将解析后的数组以静态变量的方式存到每个 Worker 的内存中
        Console::success("加载题库完成!");
    }
    /**
     * @CQCommand("找题")
     */
    public function findQuestion() {
        $tiku_id = ctx()->getNumArg("请输入题目的序号");
        if(!isset(Hello::$tiku[$tiku_id])) return "题目id为".$tiku_id."的题目不存在!";
        $timu = Hello::$tiku[$tiku_id];
        $msg = "题目名称:".$timu["question"];
        foreach($timu["answer"] as $k => $v) {
            $msg .= "\n".$k.". ".$v;
        }
        $msg .= "\n正确答案:".$timu["key"];
        return $msg;
    }
}

终端效果:(我们假设运行框架的电脑是四核 CPU

[14:28:00] [S] [#0] 加载题库完成!
[14:28:00] [S] [#2] 加载题库完成!
[14:28:00] [S] [#1] 加载题库完成!
[14:28:00] [S] [#3] 加载题库完成!

聊天效果:

) 找题 1 ( 题目名称:法律与其他社会规范的区别在于( )。\nA. 是调整人们行为的规范\nB. 有约束力\nC. 由国家强制力保证执行\nD. 规定制裁措施\n正确答案C

示例5创建每分钟自动执行的爬虫

/**
 * @OnTick(tick_ms=60000,worker_id=0)
 */
public function onCrawl() {
    $data = Foo::bar(); //这里是你自己写的要爬的接口等等一系列操作
    LightCache::set("your_data_key_name", $data); //将爬虫数据存入 LightCache 轻量缓存
}

示例6创建一个远程终端命令并调试框架

开个坑,以后填。(填坑标记