# 控制器方法钩子(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\\\\c';
//hook所在的空间命名
$w['controller'] = 'Home';
//hook所在的控制器名(缩写)
$w['action'] = 'index';
//hook所在的方法
$w['all_action'] = 0;//是否该控制器所有方法都执行此hook
$w['hook_namespace'] = '\\\\Home\\\\plugins';
//插件控制器所在的空间命名
$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)[复杂]
- 制成后台安装插件
- 附录
- 时间
- 富文本编辑器导航
- 版本更新