在講插件開發之前,如果對iWebShop的整體架構沒做了解,先看回我們之前的教程,之后再來學習插件的開發
>[info]iWebShop從 V4.4版本開始全面支持插件機制,插件是什么東西?打個比方,如果iWebShop是一個手機操作系統,插件就是APP。回到理論,插件是一種可以熱插拔的(動態安裝和卸載),可以實現一定功能性并且對目前現有運行系統不會產生任何影響的一種松散耦合的設計模式,而且易擴展,可以讓更多的開發者參與進來,讓產品自身的功能更加豐富彩,它也可以通過動態的安裝組合,實現不同的產品架構。
## 一、攔截器(鉤子)
說到插件就不得不提到鉤子,插件之所以能夠動態的加載到系統運行的各個環節中,主要是依賴于鉤子。什么是鉤子呢?鉤子就是iWebShop 系統在運行中預留的一些事件函數, 我們把插件注冊(掛接)到 iWebShop的某個事件上面,當 iWebShop 運行到這個事件的時候就會自動觸發并且調用插件。簡單來說,就是程序運行到一個有“鉤子”標志的代碼時,會調用相應的插件。

iWebShop為開發者預留的大量的鉤子,同時也支持開發者自己定義鉤子事件。
## 二、插件存放目錄
iWebShop的所有插件都存放到plugins目錄下,其下的每個子目錄代表每個插件,并且每個插件目錄下面還要新建一個與插件目錄名稱一樣的插件入口文件,比如插件名字叫“sonline” ,那么我們要在 plugins目錄下新建一個sonline目錄,并且在這個 sonline目錄下還要新建一個 sonline.php 類文件

把插件所需要的所有東西都放到自己的目錄里面:

## 三、插件功能
### 插件核心類 plugin.php
classes/plugin.php 是插件的核心類,所有插件的注冊,調用,配置等等都必須要依靠它,想深入了解iWebShop插件機制的,可以深入了解這個文件。
### 插件內置鉤子事件
打開plugin.php,有系統內置的所有鉤子,如圖:

在進行開發的時候,可以好好利用這些內置的鉤子。
之前我們講過iWebShop在運行機制,實際上在這個運行過程當中,會自動觸發plugin核心類的注冊事件,以達到調用各個插件的目的。

以上流程圖就是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,以看到以下代碼:

上面的注冊表示,當系統運行 order/order_list 或 ucenter/order 的時候,運行自定義插件里面的 orderUpdate 方法
### 事件觸發接口 trigger
`public static function trigger($event,$data = null)`
$event : 事件名稱
$data : 傳送參數
當系統運行到每個事件的時候,都要運行此接口,用來通知各個插件,由于插件父類(pluginBase)已經預留了以上的一些系統級事件(比如:onCreateController),并且會自動調用,所以開發者注冊此類系統事件不需要手動調用trigger函數,但是如果是非系統事件就必須要在代碼中手動觸發,比如 classes/menu.php 中的創建后臺菜單事件,就必須要調用 plugin::trigger 接口,如圖:

這相當定義一個節點,當程序運行到此處時,觸發事件
### 插件基類公開接口
核心文件中有個重要的插件基類 class pluginBase 用戶開發的所有插件都必須要繼承(extends)這個類,這個插件基類包含了很多工具函數,都是開發者要用到的,所以熟悉和了解此類庫對開發插件具有重大意義,這些接口隨著日后的更新也會越來越完善。以下為官方提供的接口說明:

具體的用法我們在后續的實例中說明。
### 思考
在每個操作上加上了鉤子,會不會影響系統的性能?
答案是當然會影響性能,比不上你在每個程序的鉤子節點上加入代碼來得效率高。但做一個系統不能單純只考慮性能的角度出發,鉤子不濫用的話,系統的開銷是不大的。用這一點的性能換取系統的擴展性,是完全值得去做后一些事。
以上文章的內容有多處引用官方的文檔,以免誤導讀者,詳細的用法我會在之后的文章開展。
>[warning]如有不明白的地方,留言或是加入我們?“三眾技術QQ交流群”一起討論
## 關于我們
>[danger][三眾科技](http://www.sunzoon.com)資訊平臺——大道至簡,悅你所閱!
>本教程由[三眾簡悅](http://it.sunzoon.com)原創,轉載請注明出處,作者:bobball,由bobo整理成看云書籍
三眾技術交流群:**543102562**
歡迎大家加入我們,共同討論IT,互聯網技術。同時可以掃描下面的二維碼關注我們,謝謝!
