在物联网项目里,phpmqtt这个库是目前险些最常见、利用最广泛的一个mqtt通讯类库。大部分涉及到mqtt通讯的项目险些都会利用到它。利用该库来构建物联网设备的运用做事端,流程非常清晰:
1、订阅主题的同时,设置利益置函数;
2、去世循环侦听处理。

下面这段程序网上到处可见:
<?phprequire("../phpMQTT.php");$server = '127.0.0.1'; // 做事器IP$port = 1883; // 做事器端口$username = ''; // 用户名$password = ''; // 密码$client_id = 'clientid';$mqtt = new phpMQTT($server, $port, $client_id);$mqtt->debug = true;if(!$mqtt->connect(true, NULL, $username, $password)){ echo "连接失落败!\n"; exit(1);}// 订阅列表$topics = [ 'topic01' => ['qos' => 0, 'function' => 'procmsg'],];$mqtt->subscribe($topics, 0);while ($mqtt->proc()){}$mqtt->close();// 处理函数function procmsg($topic, $msg){ echo date('Y-m-d H:i:s') . ' [' . $topic . '] ' . $msg . PHP_EOL;}
这段代码用了最直不雅观的方法写成,代码里没有任何类的封装,表示了高度朴素的唯物主义精神。奇怪的是,网上能搜到的代码,险些都是类似上述的一段或者多段,看来猿猿们都非常长于和乐于节约笔墨,高度尊重原创者的版权,恨不能一字不改都用上。于是,用类的方法来布局上述过程的例子,一个都没看到。于是问题来了,如果上述代码中的procmsg,是一个类的方法的话,topics数组里的'function' => 'procmsg',到底该当若何书写才精确呢?
换句话说,procmsg处理函数,能否利用类的方法来实现?
当然能。——那么,怎么写呢?
相信有很多人考试测验过把'function' => 'procmsg'写成:'function' => 'self::procmsg'、'function' => '$this->procmsg',然后无一例外地创造回调没有发生。这是为什么?
首先,procmsg显然是函数名称,而且,显然是一个被mqtt回调的函数名称。有了这个线索就好办了,让我们扒开phpmqtt的代码看看,案创造场到底是什么。于是我们在phpmqtt.php里看到了这段代码:
/ message: processes a recieved topic / function message($msg){ $tlen = (ord($msg{0})<<8) + ord($msg{1}); $topic = substr($msg,2,$tlen); $msg = substr($msg,($tlen+2)); $found = 0; foreach($this->topics as $key=>$top){ if( preg_match("/^".str_replace("#",".", str_replace("+","[^\/]", str_replace("/","\/", str_replace("$",'\$', $key))))."$/",$topic) ){ if(is_callable($top['function'])){ call_user_func($top['function'],$topic,$msg); $found = 1; } } }
把稳第13行和14行,两个熟习的身影涌现了:
is_callablecall_user_func不理解上述函数的,请自行度娘。
找到call_user_func的解释和示例:「链接」
Example #4 Using a class method with call_user_func()
<?phpclass myclass {static function say_hello(){echo "Hello!\n";}}$classname = "myclass";call_user_func(array($classname, 'say_hello'));call_user_func($classname .'::say_hello');$myobject = new myclass();call_user_func(array($myobject, 'say_hello'));?>
可见,代码中的$top['function'],也便是'function' => 'procmsg'中的'procmsg',可以利用array($obj,'method_name')来表示。
以是,上述代码
// 订阅列表$topics = [ 'topic01' => ['qos' => 0, 'function' => 'procmsg'],];
就可以写成下面这样:
class example{ public function listen(){xxxxxx; // 省略其他代码// 订阅列表$procfunc = array($this, "procmsg");$topics = [ 'topic01' => ['qos' => 0, 'function' => $procfunc],];$mqtt->subscribe($topics, 0);while ($mqtt->proc()){}$mqtt->close();} public function procmsg($topic, $msg){ echo "hello\n"; echo "Msg Recieved: " . date("r") . " Topic: {$topic}\n"; echo "\t$msg\n"; }}
上述方法,利用的是类的实例。当然也可以利用静态类、静态方法。详细魄式可以参考「链接」。