上一节中,介绍了如何处理消息和回复消息。这一节我们主要介绍下如何基于规则进行回复。
为了尽可能简单,把规则直接写入到配置文件中,通过读写配置文件来获取规则。
本节结束的自动回复是基于文本消息进行触发的,其他的消息类型咱不考虑。
首先定义规则类,规则包含三个属性:
关键词;
规则类型,比如是精确匹配,模糊匹配,还是正则匹配等;
回复消息内容,规则匹配之后,回复的消息内容。
Rule具体属性如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/** * 精确匹配 */ const TYPE_EXACT_MATCH = 1; /** * 模糊匹配 */ const TYPE_FUZZY_MATCH = 2; public $keyword; public $type; public $messageInfo; public $messageid; public $allRules; |
我们的消息内容定义在MessageInfo中,两者是通过messageid来关联的。messageid是根据消息数量来自增长实现的。
MessageInfo主要属性如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
/** * 消息类型:文本 */ const MESSAGE_TYPE_TEXT = "text"; /** * 消息类型:图文 */ const MESSAGE_TYPE_NEWS = "news"; /** * messageid * 回复消息的id */ public $messageid; /** * content * 回复消息的内容 */ public $content; /** * msgType * 回复消息的类型 */ public $msgType; |
msgType标识出调用哪种消息类型来发送回复消息。接口为responseMsg。content是具体的消息内容。
通过RuleConfig类来实现增加规则,写入配置文件,从配置文件中读取规则。
配置文件举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
Array ( [rules] => Array ( [0] => Array ( [keyword] => test [type] => 1 [messageid] => 1 ) [1] => Array ( [keyword] => test1 [type] => 1 [messageid] => 2 ) ) [messageInfos] => Array ( [0] => Array ( [messageid] => 1 [msgType] => text [content] => this is a test ) [1] => Array ( [messageid] => 2 [msgType] => text [content] => this is a other test ) ) ) |
测试代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public function testAddRule() { $msgInfo = new MessageInfo(); $msgInfo->msgType = MessageInfo::MESSAGE_TYPE_TEXT; $msgInfo->content = 'this is a other test'; $rule = new Rule(); $rule->keyword = 'test1'; $rule->type = Rule::TYPE_EXACT_MATCH; $rule->messageInfo = $msgInfo; $ruleConfig = new RuleConfig('wxid'); $ruleConfig->addRule($rule); } |
我们把规则写入到配置中后,就考虑集成到我们项目中。
时序图中,RuleController是自动回复的入口,在初始化,会注册所有的回复策略,在本例中,我们只有一个基于配置的回复策略。然后,每个回复策略去处理用户的发的消息。如果匹配了规则,就会发送相应的消息,否则交给TextMsg继续处理消息。
ConfigReplyTactic对外只有一个reply接口,接口返回bool用于表示,是否匹配了规则。回复策略从RuleConfig获取规则。但是,我们可以写的更灵活,从不同的规则源获取。
具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
<?php require ROOT_PATH . '/src/RuleConfig.php'; /** * ConfigReplyTactic * 基于配置的回复策略 * * @package * @version $id$ * @copyright 1997-2005 The PHP Group * @author Tobias Schlitt <<span style="text-decoration: underline;">toby@php.net</span>> * @license PHP Version 3.0 {@link <span style="text-decoration: underline;">http://www.php.net/license/3_0.txt</span>} */ class ConfigReplyTactic { private $_rules; public function reply($postObj) { $rule = $this->matchRule($postObj); // 没找到规则,直接返回 if (!$rule) { return false; } return $this->sendReplyMsg($rule, $postObj); } /** * matchRule * 查找匹配规则 * * @param mixed $postObj * @access public * @return void */ public function matchRule($postObj) { $content = $postObj->Content; $rules = $this->getRules; foreach ($rules['rules'] as $rule) { if ($rule['type'] == Rule::TYPE_EXACT_MATCH) { // 如果是精确匹配 if ($content == $rule['keyword']) { return $rule; } } else if ($rule['type'] == Rule::TYPE_FUZZY_MATCH) { // 如果是模糊匹配 if (strpos($content, $rule['keyword']) !== false) { return $rule; } } } return false; } public function getRules() { // WEIXINID:config配置里的,当前商家的微信ID $config = new RuleConfig(WEIXINID); $this->_rules = $config->readConfig(); return $this->_rules; } /** * sendReplyMsg * 根据匹配到的规则进行回复消息 * * @param mixed $rule * @param mixed $postObj * @access public * @return void */ public function sendReplyMsg($rule, $postObj) { foreach ($this->_rules['messageInfos'] as $msgInfo) { if ($msgInfo['messageid'] == $rule['messageid']) { // 具体的消息发送 $msgClass = MsgController::factory($msgInfo['msgType']); if ($msgClass) { $msgClass->responseMsg($postObj, $msgInfo['content']); return true; } } } Logger::error("not find messageid:{$rule['messageid']}"); return false; } } |
====================
代码参考:https://github.com/bruceding/MPDemo