在较早的一篇文章中,实现了一个公共平台PHP类
使用这个类以后,公共平台程序变成以下这样简单的一个形式:
主程序只有三行:
include_oncejostudio.wechat.php;
$object=newWeChat(TOKEN,onMessage);////创建一个WeChat类的实例 $object-process();//处理消息
再写一个消息处理函数
functiononMessage(WeChat$object,$messageType,$content,$arg1,$arg2){
switch(messageType){......
}}
这种程序结构很像用C语言进行windows编程(一个WinMain主程序,一个消息处理函数)
然而,随着处理逻辑的增加,消息处理函数的代码會變得很复杂(可能有很多个switch),把所有功能写在一个函数中是不好的风格(好的编程风格是一个函数最好不要超过一屏)。
一个公共平台往往提供多个应用功能,比如:
欢迎您!回复数字选择项目:\r\n1讲笑话2听音乐
上述例子有两个应用,1是讲笑话,2是听音乐。 当然 主菜单选择本身也可以看作是一个应用
我们的程序要记录用户上一次输入时的状态,比如:記錄用戶當前是在什麼應用狀態,是在主菜單呢、還是在笑话應用、音樂應用。
否则,每次用户输入时,不知道是对哪个应用进行输入。
由于公共平台并不提供类似cookie这样的功能,我们必须在自己的网站上记录用户的状态。
為些,我首先寫了一個User類,用於保存用戶狀態。(源碼文件:jostudio.user.php,
一個用戶的數據以文本文件形式保存在一個文件中,文件名是用戶OpenID號,統一放在user目錄下。數據格式採用JSON。
初始状态时,用戶有二個狀態變量:App和Stage,两个变量均为string型
App用於記錄用戶當前在哪個應用
Stage用於記錄用戶在該應用中完成了哪一步
User类的使用方法:
1,創建用戶:$user=newUser($openId,$savePath);//savePath是存盤目錄
2,寫入狀態:$user-setAppState($app,$stage);
寫入狀態值後將自動存盤
3,讀出App狀態值:$user-getApp();
4,讀出Stage狀態值:$user-getStage();
5,设置用户自定义的键值(形如:$key=$value) $user-set($key,$value);
6,读出用户自定义的键值 $user-get($key);
重新设计这个例子:
欢迎您!回复数字选择项目:\r\n1讲笑话2听音乐
分成三个应用状态:
App=main主菜单选择
App=joke讲笑话
App=music听音乐
修改消息处理函数如下:
functiononMessage(WeChat$object,$messageType,$content,$arg1,$arg2){
$user=newUser($object-fromUser,$savePath);//$object-fromUser就是用户的OpenID
switch($user-getApp()){
case:casemain:
mainMessage($object,$messageType,$content,$arg1,$arg2);
break;
casejoke:
jokeMessage($object,$messageType,$content,$arg1,$arg2);
break;
casemusic:
musicMessage($object,$messageType,$content,$arg1,$arg2);
break;
}}
mainMessage()函数负责主菜单的消息处理,jokeMessage()函数负责笑话应用的消息处理,musicMessage()函数负责音乐应用的消息处理,...
通过这样修改,通过判断不同的app状态,把消息处理分散到三个函数mainMessage,jokeMessage,musicMessage中,程序优雅很多了。
我把三个消息处理函数分别写在三个文件中,每个文件只写一个函数,再在主程序中include进来
app.main.php文件包含mainMessage()
app.joke.php文件包含jokeMessage()
app.music.php文件包含jokeMessage()
这什么要这样拆分一个程序呢?
这是模块切分的道理,好处是,整体程序合理切分,每一个文件、函数的功能都很清晰简单,耦合程度不高;
每一个函数代码不会很长,容易看懂,不容易出错,也可分工,不同的人编码
在实际应用中,我把switch($user-getApp()){...}这一段也省了
利用PHP的call_user_func()函数,通过判断App名称,动态调用相应的消息处理函数
具体不再详述,见代码吧
代码在