CI框架源码阅读笔记6 扩展钩子 Hook.php

CodeIgniter 源码解读之钩子 钩子的使用及原理 CI如同 Laravel、TP 一样提供了 类似 中间件的 功能,支持在控制器执行前及执行后的操作,CI形象的将它比作 钩子 (hooks)。这篇,我们会先写一个使用钩子的例子,然后再去读源码,了解他的使用方式。 开启钩子(application/config.php) /* |-------------------------------------------------... 阅读详情

CI框架允许你在不修改系统核心代码的基础上添加或者更改系统的核心功能(如重写缓存、输出等)。例如,在系统开启hook的条件下(config.php中config[‘enablehooks′]=TRUE;),通过添加特定的钩子,可以让系统在特定的时刻触发特定的脚本:hook[‘post_system’] = array(
‘class’ => ‘frameLog’,
‘function’ => ‘postLog’,
‘filename’ => ‘post_system.php’,
‘filepath’ => ‘hooks’,
);
上述钩子定义了一个post_system的钩子,用于在最终的页面渲染之后的脚本处理(参数的含义可以参考后面或者手册,这里暂时不做更多解释)。

那么问题来了:

钩子是什么?
CI中支持的钩子有哪些?
CI中钩子是如何实现的?
我们一步步来看。

1.  钩子是什么
  百度百科上对于钩子的定义是:

钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。

  从上述定义我们可以看出几点:

钩子是一种事件驱动模式,它的核心自然是事件(CI中pre_system,pre_controller等都是特定的事件)。
既然是事件驱动,那么必然要包含最重要的两个步骤: (1)、事件注册。对于Hook而言,就是指Hook钩子的挂载。(2).事件触发。在特定的时间点call特定的钩子,执行相应的钩子程序。
既然是事件驱动,那么也应该支持统一挂钩点的多个注册事件。
启动Hook钩子之后,程序的流程可能会发生变化,且钩子之间可能有相互调用的可能性,如果处理不当,会有死循环的可能性。同时,钩子的启用使得程序在一定程度上变得复杂,难以调试。
2.  CI中预定义钩子
CI中提供了7个可用的预设挂钩点,分别是:

  pre_system: 指在系统加载前期的钩子

  pre_controller:调用控制器之前的钩子,路由与安全性检查已经完毕

  post_controller_constructor:控制器实例化之后,任何方法调用之前

  post_controller:控制器完全运行之后

  display_override:重写display

  cache_override :重写缓存

  post_system:最终的页面发送到客户端之后

3.  CI中钩子的实现
  CI中钩子的核心功能是由Hook组件完成的,先看该组件的类图:

其中:

  enabled: 钩子功能是否开启的标志。

  hooks :保存系统中启用的钩子列表

  in_progress:之后我们会看到,这个标志位用于防止钩子之间的互相调用而导致的死循环。

  _construct是Hook组件的构造函数,这其中调用了_initialize来完成初始化的工作

  _call_hook: 调用_run_hook来call指定的钩子程序。之前CodeIgniter.PHP中我们已经看到,_call_hook是实际提供给外部调用的接口。

  _run_hook: 实际执行钩子程序的函数

在开始之前,我们先贴出预定义钩子的结构。这个结构可能会贯穿在源代码的始终,因而我们有必要知道该结构的参数含义。

$hook[‘xx’] = array(
‘class’ => ‘xx’, //钩子调用的类名,可以为空
‘function’ => ‘xx’,//钩子调用的函数名
‘filename’ => ‘xx’,//该钩子的文件名
‘filepath’ => ‘xx’,//钩子的目录
‘params’ => ‘xx’//传递给钩子的参数
);
1).  钩子组件初始化

_initialize函数用于钩子组件的初始化,该函数主要完成的工作有:

(1) 检查配置文件中hook功能是否被启用,这需要加载Config(配置管理组件):

[php] view plain copy print?
$CFG =& load_class(‘Config’, ‘core’);

if ($CFG->item(‘enable_hooks’) == FALSE)
{
return;
}
(2) 加载定义的hook列表

同样,你可以设定不同的ENVIRONMENT启用不同的hook,如果有的话,优先加载ENVRIONMENT下的hook:

[php] view plain copy print?
if (defined(‘ENVIRONMENT’) AND is_file(APPPATH.’config/’.ENVIRONMENT.’/hooks.php’))
{
include(APPPATH.’config/’.ENVIRONMENT.’/hooks.php’);
}
elseif (is_file(APPPATH.’config/hooks.php’))
{
include(APPPATH.’config/hooks.php’);
}
(3) Hook的检查。如果未设置任何hook,或者设置的hook格式错误,则不作任何处理,直接退出:

[php] view plain copy print?
if ( ! isset(hook)OR!isarray(hook))
{
return;
}

经过initialize之后,Hook::hooks中存储了已经定义的hook列表:

[php] view plain copy print?
this->hooks =&hook;
2.  Call指定的钩子

_call_hook是主程序中直接调用的接口。该接口主要的工作有:

(1). 检查钩子是否被启用,以及call的钩子是否被预定义(如果未启用或者call的钩子不存在,则直接返回):

[php] view plain copy print?
if ( ! this−>enabledOR!isset(this->hooks[$which]))
{
return FALSE;
}
(2). 检查同一个挂钩点是否启用了多个钩子,如果有,则依次执行之:

[php] view plain copy print?
if (isset(this−>hooks[which][0]) AND is_array(this−>hooks[which][0]))
{
foreach (this−>hooks[which] as val)  
    {
this->_run_hook($val);
}
}
(3). 否则,只有一个钩子,执行它

[php] view plain copy print?
else
{
this−>runhook(this->hooks[$which]);
}
_run_hook是实际执行hook的函数。

3.  run执行特定的钩子程序

_run_hook函数是hook的实际执行者,该函数接收一个预定义的hook数组作为参数,实现如下:

(1). 如果传递的参数压根就不是数组(自然也就不是有效的hook),那么直接返回:

[php] view plain copy print?
if ( ! is_array($data))
{
return FALSE;
}
(2). 检查hook执行状态。

in_progress用于标志当前hook的执行状态。这个参数的主要作用,是防止hook之间的相互调用而导致的死循环。

[php] view plain copy print?
if ($this->in_progress == TRUE)
{
return;
}
(3). Hook的合法性检查。

为了方便讲述,我们再次提出一个预定义的hook需要的参数:

$hook[‘xx’] = array(
‘class’ => ‘xx’, //钩子调用的类名,可以为空
‘function’ => ‘xx’,//钩子调用的函数名
‘filename’ => ‘xx’,//该钩子的文件名
‘filepath’ => ‘xx’,//钩子的目录
‘params’ => ‘xx’//传递给钩子的参数
);
其中class和params是可选参数,其他3个参数为必选参数,如果不提供,则由于无法准确定位到hook程序,只能直接返回:

[php] view plain copy print?
if ( ! isset(data[′filepath′])OR!isset(data[‘filename’]))
{
return FALSE;
}

filepath=APPPATH.data[‘filepath’].’/’.$data[‘filename’];

if ( ! file_exists($filepath))
{
return FALSE;
}
(4). 到这里,已经基本确认钩子程序的位置了,这里有两种情况:

a. 预定义的hook中class参数为空,表明使用的是过程式的调用方式,则直接执行hook文件中的function xxx

b. class参数不为空,提供的是面向对象的方式,则实际的钩子程序是class−>function .同样,如果既没有设置class,也没有设置function参数,则无法执行hook,直接返回:

[php] view plain copy print?
class=FALSE;function = FALSE;
$params = ”;

/* 获取 hook class */
if (isset(data[′class′])ANDdata[‘class’] != ”)
{
class=data[‘class’];
}

/* 获取 hook function */
if (isset(data[‘function’]))  
{
function = $data[‘function’];
}

/* 获取传递的 hook 参数 */
if (isset(data[‘params’]))  
{
params = $data[‘params’];
}

/* 如果class和function都不存在,则无法定位hook程序,直接返回 */
if (class===FALSEANDfunction === FALSE)
{
return FALSE;
}
(5). 设置执行标志in_progress,并执行上述两种情况下的hook:

[php] view plain copy print?
/* 面向对象的设置方式 */
if (class !== FALSE)  
{  
    if ( ! class_exists(
class))
{
require($filepath);
}

$HOOK = new $class;  
$HOOK->$function($params);  

}

else
{
if ( ! function_exists(function))  
    {  
        require(
filepath);
}

$function($params);  

}
最后,别忘了在hook执行完之后,设置标识位in_progress为false,并返回执行成功的标志:

[php] view plain copy print?
$this->in_progress = FALSE;
return TRUE;
Hook组件的完整源码:

[php] view plain copy print?

电力电子论文(TPE、TTE)投稿经验分享 电力电子顶刊论文投稿经验 阅读详情

相关推荐

SAP 物料账前期没有运行的解决方法

If you use the actual costing (material ledger), you must have completely closed all period-end closing operations in the actual costing for the penultimate period prior to the period shift. Use the '...

含笑饮砒霜死后更嚣张 3315

Codeigniter(CI3)框架搭建RESTful API服务

https://blog.csdn.net/lizhi0524/article/details/69943913

ppxin的专栏 384

MATLAB随机生成m个三维坐标点,且各个坐标点之间的距离不小于n

randi函数 randi(max,m,n); %生成均匀分布的随机整数,max生成的随机整数最大值,生成m行n列的矩阵 编写函数sampling function [x,y,z]=sampling(lowx,upx,lowy,upy,lowz,upz,m,n) %该函数用来产生不重复的随机整数矩阵 %low—随机整数下界;up—随机整数上界;m—坐标点个数;n—各个坐标点之间的最小距离 %编...

qq_45384561的博客 9436

codeigniter 钩子权限校验

最近在写个php SMS的练手项目,遇到了权限管理方面的问题 权限校验用到了钩子,这个能一定程度减少对其他页面代码的入侵,减少耦合和java的切面编程有类似的设计思路。 前台和后台的权限校验是有区别的。 前台只需要判断用户是否有登录即可 后台则需要根据配置文件,对每个模块的权限和用户的权限做对比, 其实前台权限校验也可以参考后台的方式,只是略复杂,这就两种方式分开来说明 一、通用步骤 1、开启狗子 $config['enable_hooks'] = TRUE; 2、新建一个钩子 在con

小漠007的专栏 485

MobileNet V3 图像分类

MobileNet V3

Henry的博客 1767

用GraphPad Prism直出单细胞亚群堆叠柱状图

用GraphPad Prism直出单细胞亚群堆叠柱状图

fivehuge的博客 4195

jwt token php实例结合ci钩子实现身份认证

JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。其 JWT的组成 一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。 载荷(Payload) { “iss”: “Online JWT Builder”, “iat”: 1416797419, “exp”: 1448333419, “aud”: “www.ex...

qq_24074585的博客 2120

DeepSeek如何构建可扩展的 AI 驱动交易系统,基于 MetaTrader 5 与 Python 利用先进的数据处理、机器学习和容器化部署来优化算法交易。

MT5 Python API 架构设计分为三层:通信层:利用异步消息传递(例如 ZeroMQ 或标准套接字编程)支持每秒数万个数据请求。转换层: C++ 动态库有效地将 MT5 命令转换为 Python 对象(反之亦然),从而优化速度和内存使用率。接口层:提供Pythonic API,封装了所有终端功能,包括:1)实时价格订阅(滴答或秒级更新)2)历史数据检索(从M1到更高的时间范围)3)订单流监控(交易详情和市场深度)4)策略执行引擎(用于算法交易)

iCloudEnd的博客 1378

**[权限控制] 利用CI钩子实现权限认证

http://codeigniter.org.cn/forums/thread-10877-1-1.html 一直没找到CI的权限认证扩展,以前好像找到过一个老外的扩展,不过不怎么好用,现在记不清了,后来仿着jsp firter的方式用CI钩子写了一下,感觉还可以,做个小网站,小应用足够了,没必要搞得太复杂。看到很多人在网上问,这里把我们的方法分享一下,如果你有更好的实现,也请记得分享给我们。^...

weixin_34313182的博客 281

TVS 管击穿电压与钳位电压的工程解析

TVS二极管的核心参数击穿电压(VBR)和钳位电压(VC)常被混淆,但二者具有本质区别。VBR是

硬核科技 476

制作INCA和CANape通用的A2L

CANape和INCA通用的A2L配置与修改

赞的博客 5960

CI3框架初识-钩子

今日花了半天看完ci框架手册,对比其他框架,有所心得:  1.概念上的对比    1.1 CI的钩子(hook),其实就是类似于laravel,shopex等框架的中间件,只是可以通过挂钩点的概念实现过滤在何处实现。如下:    挂钩点 以下是所有可用挂钩点的一份列表: pre_system 在系统执行的早期调用,这个时候只有 基准测试类 和 钩子类 被加载了, 还没有

yuxianjun2012的博客 2022

在RStudio中使用GitHub Copilot:代码自动生成,从此告别手敲!

可以通过自定义提示词来引导Copilot生成符合自己需求的代码。再看一个做统计分析的。

Codewar的博客 330

php ci框架 hook,CI框架源码阅读笔记6 扩展钩子 Hook.php,cihook.php

CI框架源码阅读笔记6 扩展钩子 Hook.php,cihook.phpCI框架允许你在不修改系统核心代码的基础上添加或者更改系统的核心功能(如重写缓存、输出等)。例如,在系统开启hook的条件下(config.php中$config['enable_hooks'] = TRUE;),通过添加特定的钩子,可以让系统在特定的时刻触发特定的脚本:$hook['post_system'] = array...

weixin_35651070的博客 282

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

php 里的cl框架手册,CI框架学习笔记(一)

本文是CI框架学习笔记的第一篇,主要介绍了CI框架的环境安装,基本术语以及框架流程,非常的详细,有需要的朋友可以参考下最开始使用CI框架的时候,就打算写一个CI源码阅读的笔记系列,可惜虎头蛇尾,一直没有行动。最近项目少,总算是有了一些时间去写一些东西。于是准备将之前的一些笔记和经验记录下来,一方面权作备忘,另一方面时刻提醒自己:借鉴和学习才有出路,忘记过去意味着背叛!基本术语说明在本文开始之前,有...

weixin_31847579的博客 1799

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

php ci框架 hook,CI框架源码解读之利用Hook.php文件完成功能扩展的方法

CI框架源码解读之利用Hook.php文件完成功能扩展的方法发布于 2016-05-21 15:54:07 | 98 次阅读 | 评论: 0 | 来源: 网友投递CodeIgniter开源PHP开发框架CodeIgniter 是一个简单快速的PHP MVC框架。EllisLab 的工作人员发布了 CodeIgniter。许多企业尝试体验过所有 PHP MVC 框架之后,CodeIgniter 都成...

weixin_39580727的博客 119

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

CI框架源码阅读笔记1 - 环境准备、基本术语和框架流程

最开始使用CI框架的时候,就打算写一个CI源码阅读的笔记系列,可惜虎头蛇尾,一直没有行动。最近项目少,总算是有了一些时间去写一些东西。于是准备将之前的一些笔记和经验记录下来,一方面权作备忘,另一方面时刻提醒自己:借鉴和学习才有出路,忘记过去意味着背叛! 基本术语说明   在本文开始之前,有必要对文中反复出现的术语做一个简单的说明,如果你对这一部分已经熟谙,完全可以略过。本文中反复出现和提及的术

专注、专心 5775

CI框架源码阅读笔记4 引导文件CodeIgniter.php

到了这里,终于进入CI框架的核心了。既然是“引导”文件,那么就是对用户的请求、参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位。例如,用户的请求url: http://you.host.com/usr/reg   经过引导文件,实际上会交给Application中的UsrController控制器的reg方法去处理。 这之中,CodeIgniter.php做了哪些工作

专注、专心 6793

php ci框架 源码,CI框架源码完全分析之核心文件Codeigniter.php

272月/13$assign_to_config['subclass_prefix']));}/**php 程序运行默认是30s,这里用set_time_limt延长了,关于set_time_Limit() http://www.phpddt.com/php/set_time_limit.html* 扩展阅读,关于safe_mode:http://www.phpddt.com/php/643.ht...

weixin_36367249的博客 712

php ci hooks,CI框架源码阅览-钩子类hooks.php

CI框架源码阅读---------钩子类hooks.php/*** CodeIgniter** An open source application development framework for PHP 5.1.6 or newer** @packageCodeIgniter* @authorExpressionEngine Dev Team* @copyrightCopyright (c)...

weixin_39719165的博客 152

CI框架源码阅读---------钩子类hooks.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * * An open source application development framework for PHP 5.1.6 or newer * * @package CodeIgniter

andyliu的专栏 2039

php hook framework,利用Hook.php文件完成功能扩展的方法

CI框架源码解读之利用Hook.php文件完成功能扩展的方法本文实例讲述了CI框架源码解读之利用Hook.php文件完成功能扩展的方法。分享给大家供大家参考,具体如下:看了hook.php的源码,就知道CI使用hook来进行扩展的原理了。hook的基本知识 http://codeigniter.org.cn/user_guide/general/hooks.htmlCI中hook的使用经历了一个:...

weixin_39715290的博客 168
上一篇: 以前的shell笔记
下一篇: 网页的瀑布流布局
FreeeLinux
博客等级 码龄11年 421粉丝 356原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值