对于开发者来说,整个框架系统最重要的就是插件开发了,很多功能需求都需要插件来完成。插件的制作其实主要分为两种,一种是web接口调用,比如:天气查询、物流查询、考试成绩查询等等,这些都需要通过访问其他网站的开放接口来获取相应数据,在获取数据后以文本形式或图文消息回复给用户。还有一种就是网站制作,具体点儿就是一个小型的功能微站,比如留言板、预约、抽奖等,这些都需要页面的支持,页面由HTML5+CSS3+jQuery来实现效果(最佳)。当然了,不管是哪种类型的插件,都有可能会用到微信公众平台官方提供的高级接口,这些在插件里都可以实现的很完美。
说了那么多,weiphp框架里的插件到底是个什么呢?这里的插件就是个小型的MVC,里面继承并扩展了onethink里的插件的设计模式。所以在学习weiphp插件制作之前,建议可以先学习一下onethink里的插件制作和模型制作。当然了,你也可以不用去学习,只要按照我下面讲的一步一步去做,也是可以的。咱们这里就以制作一个医院预约插件来举例。
2、需求分析:
对于医疗机构的预约功能来说,用户触发预约功能,微信客户端引导用户进入预约页面,用户填写预约信息,选择专家,提交数据,预约成功,工作人员在系统里查看预约信息。这里为了讲解插件开发简化了很多需求,实际的商业开发的时候,不仅仅是这些功能,例如还包括专家的分配管理、积分、订金支付等等。
3、设计数据表&制作模型:
对于预约功能插件的数据表来说,首先一点可以确定的是,表里一条记录就是一个预约,那么这个表里需要的字段自然就好梳理出来了。数据表里应该包含的基本信息有:预约客户的信息、预约专家的信息、预约的时间。这里有个概念需要弄清楚,就是关注者和预约客户的区别,这两者可能是同一个人,也可能不是同一个人,因为我们不能拒绝关注者帮助任何人预约,比如一个关注者要为自己的爷爷奶奶预约一个医生,那么这两个角色就是不一样的。所以客户在预约的时候需要填写客户信息,而不是从关注者表或者Oauth2.0去获取关注者信息。
根据这些分析,这个数据表就不难设计了。如下表所示:
字段名 | 中文名称 | 类型及精度 | 作用 | 备注 |
id | 序号 | int(11) | 序号 | |
clientname | 预约客户 | varchar(30) | 预约用户名 | 和关注者不一样,患者不一定就是用户 |
sex | 客户性别 | varchar(6) | 客户性别 | 直接存“男”或“女” |
age | 客户年龄 | varchar(3) | 客户年龄 | |
mobile | 客户电话 | int(12) | 客户电话 | |
orderdate | 预约就诊时间 | int(15) | 预约就诊时间 | 患者在这个时间去就诊 |
expert | 专家姓名 | varchar(255) | 专家姓名 | |
uid | 关注者ID | int(11) | 联系方式 | 关联follow表id |
addtime | 预约创建时间 | int(15) | 预约创建时间 | 关注者在客户端创建预约的时间 |
email | 电子邮箱 | varchar(50) | | |
openid | 关注者openid | varchar(150) | | 由微信提供 |
创建模型,进入 后台=》系统设置=》模型管理,点击新增按钮,进入新增模型页面。这里的操作也是继承了onethink模型管理里的设计模式。如下图所示:
“模型标识”里填写英文名称,也就是数据表名(无表前缀)。模型名称填写中文名称,模型类型必须是独立模型。其他默认即可。确定,提交。这时,系统跳转到模型列表页面,这个列表是按照模型标识的首字母排序的,所以你可以很快的找到你刚才新建的模型,点击右侧的编辑链接,进入到编辑模型页面,如下图:
在“设计”一栏下有个字段管理,字段列表旁边点击“新增”按钮,开始添加刚才咱们设计出来的字段。
字段名就是数据表里的字段名,字段标题是他的中文名称,字段类型就是MySQL标准数据类型,字段定义是字段的属性,可以手动更改。参数、默认值、字段备注为空。是否显示,选择始终显示,是否必填,对应于数据表中该字段是否可以为空,所以视情况而定。
点击上面“高级”一栏,如下图:
这里分为两部分。熟悉ThinkPHP的朋友都知道TP模型基类里有两个比较方便的小功能,分别是自动验证和自动完成。这个高级部分,就是对该字段设计验证方式和自动完成方式。当我们在这里设置验证方式的时候,程序后台就会调用模型里的自动验证的方法,当我们设置自动完成方式的时候,程序后台同样会调用模型里的自动完成方法。根据ThinkPHP对这块的设计,我们可以知道,验证方式就是当我们调用模型类的create()方法创建数据对象的时候,就对各个字段的数据按照我们制定的验证方式进行验证。当我们调用模型类的create()方法创建数据对象的时候,先要按照自动完成规则对数据进行加工处理,然后再插入到数据库里。所以设置高级里的这些选项,对数据可以严格把关。当然了,你也可以把这些逻辑写到控制器里。在这里,为了突出主要次要,我暂且不使用这个功能,大家感兴趣的话,可以按照我上面说的,然后参照ThinkPHP手册里讲的去设计一下。
好,按照我上面所说的方法,把我们设计的数据表字段都添加进去。这时,查看数据库里,已经多了一个order表了。
最后回到编辑模型页的设计,这里有个“表单设计分组”,这个功能原先在onethink里面,是在后台添加文章数据的时候为了好看或者操作方便而设计的一种把表单分配给选项卡里的功能,但是在weiphp里,用处和意义都不大,所以不必理会。感兴趣的童鞋可以参考我之前做的“
onethink学习心得”。继续看“设计”下面的内容,这里有个列表定义,如下图:
这里是设置该模型数据列表页所要显示的字段数据。关于这一部分,可以参考onethink官方手册的模型制作,这里也是继承了onethink的真传。我这里不会细说,但是需要指出几点:1,每一行左边是和数据库里的字段名完全一样的字段名,其后是英文冒号,再其后就是中文名称,这个中文名称会在列表页里的thead标签里显示。2、字段名后可以添加一个处理函数,字段名和函数名之间用单竖线隔开,数据在经过函数处理过后,显示出来。函数可以是ThinkPHP框架内的函数,也可以是开发人员在function.php里自定义的函数。函数里只能return数据,而不是echo 数据,否则数据显示不出来。3、最后一行,
,这个是列表里最后一列用来显示一些编辑链接的。其规则是[EDIT]代表编辑的地址,&id=[id]是get传参。有不明白的,可以参考这里:
http://document.onethink.cn/manual_1_0.html#onethink_2_7 “设计”页最下面的默认搜索字段和高级搜索字段都是设置列表页里搜索框的,当我们在搜索框里输入我们想要查找的内容的时候,程序就会按照这里的设置,在数据库里按照这个字段查找。
前台数据列表效果如下:
4、制作插件:
模型制作好以后,进入插件管理=》微信插件,这是微信插件的列表,点击上面的快速创建按钮,进入插件创建页面。如下图:
这里我已经填写好了。标识名是插件的英文名称,和模型的标识名称是一样的,但是需要注意的是这里的标识名首字母必须大写,而模型的标识名首字母是小写的,因为ThinkPHP的规范命名法是驼峰命名法,创建好插件后,插件里的文件夹名称和类文件名类名都是按照标识名来命名的。而数据库表名一般都是小写的。当然了,你也可以把插件的标识名和模型的标识名设置成不一样的。后面我们会讲到。
插件名称就是中文名称,在左侧菜单显示的就是中文名称。版本号,可以自定义。作者,可以自定义。描述里简单写一下这个插件的作用,以便后期维护的时候,或者别的童鞋来查看的时候,方便找到想要的插件。安装后是否启用,打上对勾。是否需要配置,这个选项的意思是是否需要配置一下配置文件,我建议大家不要在这里填写,具体的做法,后面会讲到,咱们在这先不勾选。是否需要管理列表,勾选下面的复选框。
预览按钮显示出来的是即将生成的插件文件里的代码,里面的内容都是根据这个新建页面的表单数据生成的。不过,查看这些,意义不大,可以略过。
好,点击确定,提交表单。此时先不要着急安装,去服务器查看一下,Addons目录下应该有一个名叫“Order”的文件夹了,这个就是插件文件夹,里面包含了这个插件的所有文件。这时候,我们来创建一个配置文件config.php,代码如下:
配置文件里的参数设置采用数组形式,键名就是参数名,键值是一个描述表单的数组,title是表单名称,type是表单类型,value是表单默认值,tip是表单说明注释,当type是select、radio或者是checkbox的时候,需要添加一个options参数,用来设置备选项,其值为一个一维数组,数组的键名就是值,键值是代表的含义。比如是否开启插件里的选项,当该表单选择开启的时候,PHP代码里获取到的值就是1,反之亦然。在PHP代码里使用getAddonConfig()函数来获取配置参数的值,函数参数就是插件名。获取到配置参数以后就可以根据配置来决定插件的具体功能了。
其中,参数isaction是否开启插件,当选择开启的时候,即可使用插件,当选择关闭的时候,会提示用户功能关闭。参数expert是设置专家名字,这里为了算法简单,暂且使用笨办法吧:-)。 在textarea里专家名字之间用英文半角空格隔开,在PHP代码里再使用explode函数分割开。参数title是图文消息的标题,参数cover是图文消息的图片,desc是图文消息的描述。当参数类型是picture的时候,表单是file类型的,上传图片,数据库里存储的是图片表的id,需要使用函数get_cover_url()来解析出实际的url地址。
好,配置文件编写完成,这时候去后台插件管理=>微信插件,找到刚才创建的插件,在右侧点击安装,安装成功后,后台操作基本上到此就OK了。这时,在前台可以查看到由配置文件生成的配置页面:
5、开发:
在网站根目录里,有个Addons目录,里面找到刚才生成的Order目录,这即是咱们的预约插件目录。里面的目录结构,熟悉MVC的朋友一看就知道了,这里不再敖述。
打开模型文件WeixinAddonModel.class.php,如图:
在这些方法里,关键的是reply方法,他是插件与外界沟通的桥梁,当用户向公众号发送信息时(不仅包括直接发送,也包括点击按钮,扫描二维码,关注公众号等),就会调用所定向的插件里的reply方法,在这个方法里,设置回复信息,回复的信息内容则可以自定义,可以是插件配置里设置的,可以是数据库里的数据,也可以是通过其他服务器的接口获取的数据。比如我们做一个查询天气预报的插件,插件就会在reply方法里通过调用其他开放的API来获取天气预报的数据,然后组成要回复的信息。该方法里最后调用$this->replyNews()方法,这是回复图文消息方法,源代码在父类里。在父类里你会发现不止reply这一个回复方法,还有其他的回复类型,replyText,replyImage等等。根据你想回复的消息类型来调用即可。微信有哪些消息类型,可以查看官方文档(
http://mp.weixin.qq.com/wiki/14/89b871b5466b19b3efa4ada8e577d45e.html)。
那么除了reply方法,大家看到下面有很多事件响应方法,这些事件响应方法该如何使用呢?首先来看这样一个代码,找到文件/Application/Home/Controller/WeixinConreoller.class.php,对!看到这里,很多人想起来了,咱们在配置公众账号的时候,在微信官方的管理平台上设置的服务器地址指向的就是这个控制器的index方法:
第34行之前的代码都是系统初始化方法。看到第35行,调用reply方法,reply方法就在下面第40行。用户发送消息给公众平台,在index方法里,进行初始化,比如记录用户的openid,获取公众号的token等等。那么在下面的reply方法里,就是对用户发送过来的消息进行处理,根据用户消息类型和消息内容调用相应的插件,被调用的插件使用其模型里的WeixinAddonModel.class.php类里的reply方法做出相应的回复。
现在看WeixinConreoller.class.php里的第60至78行,如图:
这段代码说明当用户发送过来的消息类型是event的时候,这里将会遍历系统里所有的插件,并执行每个插件里WeixinAddonModel.class.php类里的事件方法。这样说有点儿抽象,举个例子,比如用户点击了一下菜单里的一个按钮(按钮是click类型),那么这段代码就会遍历所有插件,并且检查每个插件里WeixinAddonModel.class.php类里是否有click方法,如果有,则执行这个方法。在74行代码里,把按钮推送过来的EventKey值当做推送过来的文本来赋值给关键字变量$key,这样做的目的是在后面的代码里匹配调用对应的插件。这里仅仅是做了关注和点击按钮事件,开发人员可以根据需求扩展一下,添加扫描二维码事件等等。
现在我们回过头来看一下模型WeixinAddonModel.class.php,reply方法有两个参数$dataArr和$keywordArr。第一个参数$dataArr是将微信服务器推送过来的xml信息转化成的数组,如图所示:
里面键值对的含义,可以对比参照原始的xml数据。
第二个参数$keywordArr是用户发送的信息所涉及的关键词的数据,从keyword表里读出来的。该表的结构请参见在线开发手册
http://www.weiphp.cn/wiki/。该参数形式如图:
在reply方法里,变量$articles就是图文消息结构数组,如果里面只有一个数组的话,回复的是单图文消息,如果有多个数组的话,就是多图文消息。大家可以看到参数”Url”指向一个地址,这个地址由函数addons_url生成,第一个参数是指定插件、控制器和方法,第二个参数是一个数组,用来以get方式向第一个参数指定的方法传递参数。
那么,这里指定了当用户点击图文消息时,跳转至Order插件的Order控制器的appoint方法,下面,我们来分析这个方法。如图所示:
首先根据用户的uid在数据库里查询该用户是否已经预约过了,如果预约过了,那么给出一个提示,并退出页面。接下来,根据插件配置参数判断活动是否已经结束,如果结束了,那么同样也要提示,并退出页面。其中脚本代码:
<script>document.addEventListener('WeixinJSBridgeReady',function OnBridgeReady(){WeixinJSBridge.call('closeWindow');});</script>
是微信浏览器专属的一个监听事件(addEventListener),微信浏览器加载页面后,即执行退出页面的动作(closeWindow)。
这里,是否允许用户多次预约,可以做一个插件配置,然后由工作人员自行在后台配置页面上进行设置。就像控制活动是否结束一样。当然了,提示语也可以由配置里去设置。
继续看PHP代码,接下来就是获取插件配置里填写的专家名字,并传递给页面。以供用户在页面上选择。页面效果如下(页面由
方倍工作室编著《微信公众平台最佳实践》提供):
页面和数据提交后的处理代码对本教程意义不大,这里省略。
提交信息后,成功添加到数据库里,这时跳转到成功页面,如图:
然后呢,我们查看一下weiphp管理系统页面,如图:
可以看到,我们提交的预约信息已经从后台展现出来了。
接下来介绍一下自定义选项和自定义模型名。
当我们在管理平台上查看插件的时候,每个插件默认可以查看到数据列表和设置配置的页面,他的链接可以用如下方法设置:
这段代码放到OrderController.class.php里,这样的话,每次访问lists数据列表页和config设置配置页时,首先执行这段代码(因为_initialize是ThinkPHP控制器里的初始化方法),配置好每一页上方的选项卡:
解释一下这段代码,这里的选项卡使用二维数组的方式来配置,每一维数组代表一个选项,其中title是选项卡名称,也就是当前页的标题,url是其链接地址,class是样式类,这个样式类是由操作方法来决定的,如果当前页是config方法的话,那么这里的class值就是current(样式是高亮),其他同理。常量_ACTION是当前操作方法名,关于weiphp新加的一些常量,可以参阅官方帮助手册:
http://www.weiphp.cn/wiki/,
这里的显示的页面是由weiphp提供的默认的页面,模板文件在/Application/Home/View/default/Addons。当然了,你也可以自己做好看的模板,方法是将weiphp默认的这些模板全部拷贝到当前插件的View/default/Order目录下,并按照自己的设计去修改config.html和lists.html文件,在修改的时候,要注意里面的ThinkPHP的模板继承等模式,这里就不再详细阐述了。
下面讲一下自定义模型名。weiphp插件默认的数据表是与插件自身同名的表,如果插件的表和自身不同命,那么就需要开发者在控制器里重新定义数据表名,并且重载增删改查的方法。在上面初始化函数里有个类属性变量$this->model,这就是重新定义了模型名(表名)。在控制器里添加如下方法:
6、关键词:
这里的关键词关联的是关键词库里的,进入 账号管理=》关键词维护,即可看到有哪些关键词,所谓关键词,就是当用户给公众号发送的文本,当文本里匹配到关键词的时候,即触发对应的功能插件。具体的关键词处理,可以查看/Application/Home/Controller/WeixinController.class.php里reply方法。