上一节中,介绍了如何处理消息和回复消息。这一节我们主要介绍下如何基于规则进行回复。
为了尽可能简单,把规则直接写入到配置文件中,通过读写配置文件来获取规则。
本节结束的自动回复是基于文本消息进行触发的,其他的消息类型咱不考虑。
首先定义规则类,规则包含三个属性:
关键词;
规则类型,比如是精确匹配,模糊匹配,还是正则匹配等;
回复消息内容,规则匹配之后,回复的消息内容。
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
								