在讲插件开发之前,如果对iWebShop的整体架构没做了解,先看回我们之前的教程,之后再来学习插件的开发
>[info]iWebShop从 V4.4版本开始全面支持插件机制,插件是什么东西?打个比方,如果iWebShop是一个手机操作系统,插件就是APP。回到理论,插件是一种可以热插拔的(动态安装和卸载),可以实现一定功能性并且对目前现有运行系统不会产生任何影响的一种松散耦合的设计模式,而且易扩展,可以让更多的开发者参与进来,让产品自身的功能更加丰富彩,它也可以通过动态的安装组合,实现不同的产品架构。
## 一、拦截器(钩子)
说到插件就不得不提到钩子,插件之所以能够动态的加载到系统运行的各个环节中,主要是依赖于钩子。什么是钩子呢?钩子就是iWebShop 系统在运行中预留的一些事件函数, 我们把插件注册(挂接)到 iWebShop的某个事件上面,当 iWebShop 运行到这个事件的时候就会自动触发并且调用插件。简单来说,就是程序运行到一个有“钩子”标志的代码时,会调用相应的插件。
![](http://it.sunzoon.com/wp-content/uploads/2016/07/20160812120955.png)
iWebShop为开发者预留的大量的钩子,同时也支持开发者自己定义钩子事件。
## 二、插件存放目录
iWebShop的所有插件都存放到plugins目录下,其下的每个子目录代表每个插件,并且每个插件目录下面还要新建一个与插件目录名称一样的插件入口文件,比如插件名字叫“sonline” ,那么我们要在 plugins目录下新建一个sonline目录,并且在这个 sonline目录下还要新建一个 sonline.php 类文件
![](http://it.sunzoon.com/wp-content/uploads/2016/07/20160812113124.png)
把插件所需要的所有东西都放到自己的目录里面:
![](http://it.sunzoon.com/wp-content/uploads/2016/07/20160812113620.png)
## 三、插件功能
### 插件核心类 plugin.php
classes/plugin.php 是插件的核心类,所有插件的注册,调用,配置等等都必须要依靠它,想深入了解iWebShop插件机制的,可以深入了解这个文件。
### 插件内置钩子事件
打开plugin.php,有系统内置的所有钩子,如图:
![](http://it.sunzoon.com/wp-content/uploads/2016/07/20160812112941-1024x397.png)
在进行开发的时候,可以好好利用这些内置的钩子。
之前我们讲过iWebShop在运行机制,实际上在这个运行过程当中,会自动触发plugin核心类的注册事件,以达到调用各个插件的目的。
![](http://it.sunzoon.com/wp-content/uploads/2016/07/20160812110612-1024x202.png)
以上流程图就是iWebShop整个运行所触发的事件,我们的插件就要注册(挂接)到这些事件上。这里有个情况,就是这里的事件触发是广泛的
比如onCreateController 这个事件会监听所有控制器的创建,但是有的时候,我们的插件仅仅是针对某个控制器的,比如前台访问统计,或者是后台的订单自动取消等,这些功能仅需要监听(注册)site.php和 order.php控制器,于是我们可以把事件名称做一下变形,比如:onCreateController@site onCreateController@order 这样就可以为某个控制器绑定事件了
同理动作 (action) 也是如此, 那么我们只需要继续追加@动作 ID 比如, 我们要在首页 (site/index)动作中做处理,那么监听的事件名字:onCreateAction@site@index 按照层级关系追加就可以了,控制器(controller)包含动作(action)
下面我们介绍最常用的事件:
**【onCreateController】**
控制器(controller)创建完成,可以得到当前正在运行的控制器,并且给控制器动态增加方法,设置数据等操作。
**【onCreateAction】**
动作(action)创建完成,此时还没有执行动作(action)
**【onCreateView】**
视图(view)创建完成
**【onFinshView】**
视图(view)调用结束
**【onFinishAction】**
动作(action)调用结束
**【onFinishController】**
控制器完成结束
### 插件注册接口 reg
`public static function reg($event,$classObj,$method = "")`
$event :事件名称
$classObj:类对象或者匿名函数
$method:方法名称,当$classObj为类对象时此参数有意义,否则无用
核心插件类中有一个重要的接口 通过此静态方法,把事件与插件进行注册绑定(挂接) ,简单说就是把某个$event事件交由一个函数或者对象方法去处理
打开 orderAutoUpdate 插件的 orderAutoUpdate.php,以看到以下代码:
![](http://it.sunzoon.com/wp-content/uploads/2016/07/20160812123649-1.png)
上面的注册表示,当系统运行 order/order_list 或 ucenter/order 的时候,运行自定义插件里面的 orderUpdate 方法
### 事件触发接口 trigger
`public static function trigger($event,$data = null)`
$event : 事件名称
$data : 传送参数
当系统运行到每个事件的时候,都要运行此接口,用来通知各个插件,由于插件父类(pluginBase)已经预留了以上的一些系统级事件(比如:onCreateController),并且会自动调用,所以开发者注册此类系统事件不需要手动调用trigger函数,但是如果是非系统事件就必须要在代码中手动触发,比如 classes/menu.php 中的创建后台菜单事件,就必须要调用 plugin::trigger 接口,如图:
![](http://it.sunzoon.com/wp-content/uploads/2016/07/20160812142434.png)
这相当定义一个节点,当程序运行到此处时,触发事件
### 插件基类公开接口
核心文件中有个重要的插件基类 class pluginBase 用户开发的所有插件都必须要继承(extends)这个类,这个插件基类包含了很多工具函数,都是开发者要用到的,所以熟悉和了解此类库对开发插件具有重大意义,这些接口随着日后的更新也会越来越完善。以下为官方提供的接口说明:
![](http://it.sunzoon.com/wp-content/uploads/2016/07/20160812111505-1024x37.png)![](http://it.sunzoon.com/wp-content/uploads/2016/07/20160812111348-1024x495.png)
具体的用法我们在后续的实例中说明。
### 思考
在每个操作上加上了钩子,会不会影响系统的性能?
答案是当然会影响性能,比不上你在每个程序的钩子节点上加入代码来得效率高。但做一个系统不能单纯只考虑性能的角度出发,钩子不滥用的话,系统的开销是不大的。用这一点的性能换取系统的扩展性,是完全值得去做后一些事。
以上文章的内容有多处引用官方的文档,以免误导读者,详细的用法我会在之后的文章开展。
>[warning]如有不明白的地方,留言或是加入我们 “三众技术QQ交流群”一起讨论
## 关于我们
>[danger][三众科技](http://www.sunzoon.com)资讯平台——大道至简,悦你所阅!
>本教程由[三众简悦](http://it.sunzoon.com)原创,转载请注明出处,作者:bobball,由bobo整理成看云书籍
三众技术交流群:**543102562**
欢迎大家加入我们,共同讨论IT,互联网技术。同时可以扫描下面的二维码关注我们,谢谢!
![三众科技服务号](http://it.sunzoon.com/wp-content/uploads/2016/06/qrcode_for_gh_401d25b05314_344.jpg)