# 控制器方法鉤子(hook)
## 原理
程序訪問控制器方法的時候,檢查是否存在相應的hook,如果有對應的hook,那么就先執行hook,再繼續執行當前方法,當然,如果hook里面執行中斷繼續執行,那后面就不會執行,而同一個方法可能有多個hook,那么就依次執行(安裝hook表的ID正序)。
## 舉例
**需要實現的功能**
如果我要在用戶進入首頁的時候檢測用戶的IP,并顯示在首頁上顯示出用戶的訪問IP
**分析**
首頁相關的控制器是`Home/c/HomeController.php`,相關的方法是`index()`
那么我要做的是在這個控制器+方法上面加個hook,即`new Home/c/HomeController()->index()`
**實現**
1. 先在前臺Home/plugins文件夾下面寫一個`控制器+方法`實現這個檢測IP的功能
~~~
<?php
namespace Home\plugins;
//定義本文件空間
use Home\c\HomeController;
//使用HomeController控制器
use FrPHP\Extend\Page;
use FrPHP\Extend\ArrayPage;
//直接繼承原Home/c下面的HomeController控制器
class IpTestController extends HomeController
{
//直接復制HomeController的index方法,再修改
function index(){
//插入獲取用戶IP的方法
$ip = GetIP(); //系統內置的方法,無需考慮如何實現
//賦值到模板中輸出,這一步不能缺少,否則無法輸出
$this->ip = $ip;
/**以上為新增內容**/
//檢查緩存
$url = current_url();
$cache_file = APP_PATH.'cache/data/'.md5(frencode($url));
$this->cache_file = $cache_file;
$this->start_cache($cache_file);
$this->display($this->template.'/index');
$this->end_cache($this->cache_file);
//此方法最后寫了exit中斷繼續執行
}
}
?>
~~~
> 注意:這個`index`方法自帶`exit`中斷繼續執行下去,而如果你要寫繼續執行下去的話,就不要寫`exit`,程序會繼續執行下去。
> 從制作思路上考慮,直接繼續原控制器,然后復制對應的方法,進修改的比較方便的,但也僅僅只能在這個方法上添加一個hook,多個則不行,因為中斷執行了。
2. 加入系統中hook表
> 該章節涉及到后臺安裝插件制作,不熟悉的朋友,先看下個章節的插件文件介紹和說明
在`PluginsController.php`的`install`方法里添加進數據庫
~~~
//執行SQL語句在此處處理,或者移動文件也可以在此處理
public function install(){
//下面是新增test表的SQL操作
//檢測是否已安裝前臺插件
$filepath = APP_PATH.'Home/plugins/IpTestController.php';
if(file_exists($filepath)){
JsonReturn(array('code'=>1,'msg'=>'前臺Home下面已存在相應的Banip控制器!'));
}
//注冊到hook里面
$w['module'] = 'Home';
//所在的模塊
$w['namespace'] = 'Home';
//hook所在的空間命名(v1.6.4已廢棄)
$w['controller'] = 'Home';
//hook所在的控制器名(縮寫)
$w['action'] = 'index';
//hook所在的方法
$w['all_action'] = 0;//是否該控制器所有方法都執行此hook
$w['hook_namespace'] = 'Home';
//插件控制器所在的空間命名(v1.6.4已廢棄)
$w['hook_controller'] = 'IpTest';
//插件控制器名
$w['hook_action'] = 'index';
//插件所執行的方法
$w['plugins_name'] = 'iptest';//插件文件夾
$w['addtime'] = time();
M('hook')->add($w);
return true;
}
~~~
同樣,你注冊了插件,就要卸載插件,刪除對應的hook數據
~~~
//卸載程序,對新增字段、表等進行刪除SQL操作,或者其他操作
public function uninstall(){
//下面是刪除test表的SQL操作
M('hook')->delete(['plugins_name'=>'iptest']);
return true;
}
~~~
3. 完善插件安裝文檔
4. 測試插件是否能夠成功安裝并實現功能
> hook確實有些復雜,但是其強大之處在于做小功能,檢測類,比如檢測驗證碼,獲取數據做其他處理等等,可以多個hook,不只基于一個控制器。
- 引言
- 條款
- 開始使用
- 模板標簽
- 公共配置
- 系統配置
- 自定義配置
- 網站欄目
- 全局欄目屬性
- 導航欄相關
- 當前欄目下的直系下級
- 當前欄目下的直系上級
- 欄目詳情頁
- 欄目列表頁
- 欄目分頁
- 輸出三級及三級以上欄目
- 當前位置面包屑
- 獲取當前欄目的頂級欄目
- 直播講解欄目相關
- 文章詳情頁
- 基本內容
- 點贊
- 收藏
- 相關文章
- 輸出新增字段
- 商品詳情頁
- 基本內容
- 輸出新增字段
- 商品圖集
- 點贊
- 收藏
- *點評星星
- 加入購物車
- *評論
- 相關商品
- 自定義字段
- 原樣輸出
- 單選字段
- 多選字段
- loop標簽
- 通用說明
- loop分頁
- 案例說明
- like使用
- 怎么判斷loop沒有數據
- limit使用
- day參數
- table缺省參數
- 單選多選相關
- 單選字段輸出
- 多選字段輸出
- 特殊輸出
- 輸出換行
- 替換字符串
- 輸出被解析的HTML原句
- 截取字符串
- 內容body去除HTML
- 分割字符輸出
- 人性化時間顯示
- 搜索功能
- 單模塊搜索
- 多模塊搜索
- 搜索擴展
- 搜索結果列表頁
- 會員模塊
- 判斷是否登錄
- 判斷是否評論
- 計算評論數
- 如果判斷會員組是否權限
- 如何輸出分組信息
- 如何輸出所有用戶分組
- 如何輸出所有會員
- 輸出某個會員發布的內容
- 查詢一個用戶的所有信息
- 輸出我的粉絲列表
- 輸出我的關注列表
- 獲取粉絲數
- 獲取關注數
- 判斷是否關注
- 關注與取消關注鏈接
- 判斷會員是否購買該商品
- foreach標簽
- for標簽
- fun標簽
- php標簽
- 不解析標簽
- if..else..標簽
- screen篩選標簽
- 客戶端判斷
- 輪播圖
- 友情鏈接
- 自定義圖集輸出
- Tags標簽調用及使用說明
- 網站留言調用
- 自定義單頁
- 各種統計
- 各種計數顯示數
- 文章歸檔內容歸檔
- 系統架構
- 高級功能
- ajax數據交互
- ajax在欄目頁的應用
- ajax在screen篩選中的應用
- screen多選篩選
- Message留言表單
- 萬能表單
- 多語言支持
- 系統高級配置說明
- 網站動態鏈接
- 郵件發送
- 自定義路由配置
- 插件開發
- 控制器方法覆蓋(cover)[簡單]
- 控制器方法鉤子(hook)[復雜]
- 制成后臺安裝插件
- 微信小程序
- 開始起步
- 小程序開發
- API訪問接口數據
- 輪播圖(幻燈片)
- 訪問欄目列表
- 詳情頁查詢
- 欄目詳情查詢
- 留言接口
- 附錄
- 時間
- 富文本編輯器導航
- 偽靜態配置
- 二維碼生成
- 常見問題
- 靜態生成HTML頁面失敗問題
- 為什么默認模板打開首頁很慢,而打開后臺卻很快?
- 如何判斷首頁、欄目頁、內容頁、單頁
- 視頻教程
- 版本更新
- 寶塔一鍵部署