我正在通过Messenger Platform API创建一个简单的聊天机器人,我几乎坚持如何有效地识别机器人可以做出反应的一组命令。我目前正在使用switch语句来检测以感叹号开头的命令(例如!showlist;!additem <single/set of parameter(s)>
)。
以下是我目前的情况:
switch(true){
case stristr($receivedMsg,'!additem'):
....
}
在代码的任何匹配阶段,要么先执行一组语句,要么首先推断最终参数,然后用它们执行一些语句。
我在上述设置中遇到的问题如下:
如果是带有参数的命令,则在使用以下语句检索这些参数时:
$item=str_replace('!additem', '', $receivedMsg);
在参数中包含不需要的文本非常容易;您可以使用trim()
来处理空格,或者暗示将始终存在空格并编辑上述语句以将其包含在函数中。例如。
$item=str_replace('!additem ', '', $receivedMsg);
但是当尝试将命令与params分开时,会出现其他问题。
我知道解决方案可能是使用系统字符串操作函数进行硬编码,但这对我来说似乎并不正确。人们在这种情况下做了什么?是不是有一种特定的方法来完全匹配命令并安全地发现最终用户&#39;错别字?
答案 0 :(得分:1)
您在自己的解决方案中没有使用正则表达式,但正确标记了它。通过stristr()
函数,我发现你不是在寻找更多的命令,所以我在RegEx上应用了相同的逻辑:
$msg = 'Gonna add it !additem param1,param2';
preg_match('~(!\S+)\s*(.*)~', $msg, $match);
$command = $match[1];
$parameters = preg_split('~\s*,\s*~', $match[2]);
我试图做一个单行,但后来认为这会更清洁。顺便说一句,我想知道转换声明。
RegEx细分:
~ # regex delimiter
( # Start of Capturing Group (1)
!\S+ # Match non-space characters that start with !
) # End of CG1
\s* # Any number of white-sapce characters
( # Start of CG2
.* # Match up to end
) # End of CG2
~ # regex delimiter
preg_split
也会收到正则表达式作为其第一个参数并尝试拆分它,几乎是explode
正则表达式。 \s*,\s*
表示可以包含在任意数量的空格中的逗号。
答案 1 :(得分:1)
if ($receivedMsg[0] == '!')
switch (strtolower(substr(reset(explode(' ', $receivedMsg)), 1)))
{
case 'additem':
// do this
break;
case 'delitem':
// do that
break;
default:
echo 'Command not recognized.';
}
那是一种方法。您还可以使用处理每个命令的函数声明一个数组,例如:
$handles = [
'additem' = function ($args) { /* add something */ },
'delitem' = function ($args) { /* del something */ },
// ...
];
if ($receivedMsg[0] == '!')
{
$args = explode(' ', $receivedMsg);
$cmd = strtolower(substr($args[0], 1));
if (isset($handles[$cmd]))
$handles[$cmd]($args);
else
echo 'Command not recognized.';
}
答案 2 :(得分:0)
基于我对@Havenhard和@revo提供的答案的解决方案,我已经编写了以下适用于我的解决方案:
$this->senderId = $messaging['sender']['id'];
$command_handlers = [
'additem' => "addItemCommand",
'showlist' => "showListCommand",
'rngroup' => "renameGroupCommand"
];
$actionCompletedOrh = new OutRequestHandler($this->senderId);
if(!empty($messaging['message']) && empty($messaging['message']['quick_reply'])){
$receivedMsg = $messaging['message']['text'];
$replyMsg = "";
$this->performSenderAction(0);
//isCommand uses this regex to perform the evaluation
//(^!\w+\s+([\w,\s]*$)|^!\w+$)"
if($this->isCommand($receivedMsg)){
//regex matching to get params in raw form
preg_match("~(^!\w+\s+([\w,\s]*$)|^!\w+$)~",$receivedMsg,$match);
//regex matching to get the command
preg_match("~^!\w+~",$match[0],$_match);
$command = strtolower($_match[0]);
$params = null;
if(count($match)>2){
//the function below uses preg_split as in @revo's example
$params = $this->getCommandParams($match[2]);
}
if(array_key_exists(substr($command,1), $command_handlers)){
$func = $command_handlers[substr($command,1)];
$replyMsg=$this->$func($params,$connection);
}
else{
$replyMsg=$this->getPromptMessage("cmer1");
}
}
else{
//All other messages - possibly processed with NPL
}
$this->performSenderAction(2);
$replyMsg = json_encode($replyMsg);
$actionCompletedOrh->sendJustTextMessage($replyMsg,$access_token);
}
你看到我能改进的东西吗?请让我知道评论中的内容和原因!