php中关于hook钩子函数底层理解
作者:梅坞茶坊 发布时间:2023-06-12 06:49:55
假设你有一套登录注册业务。一开始很简单,老板说只需要常规的注册登录就行。
但是到了后面,接口被刷,老板然你在注册登录前加个验证码
然后没过多久,老板又说,当用户注册时,我们给用户的邮箱或者手机发一条欢迎短信或者邮件吧
还没过上多久,老板说,当新注册时,我们给手机注册的发送200金币,给邮箱注册的发送100金币,作为注册奖励。
接着没过多久,老板说,如果一个用户超过1个月没登录的话,再次登录时,你给就给他账户发送100金币作为回归奖励,
结果过了不久,老板又说,注册时判断一下他是手机号注册还是邮箱注册,如果是邮箱就跳转 A 页面,如果是手机号就跳转 B 页面
过了一段时间,老板又说,我觉得第二个 idea 不好,我们给他去掉吧。
。。。。
等等,在业务中,我们对一个需求,会遇到各种变更,如果我们不使用 Hook ,就需要去频繁的改动主业务代码,而且还很容易出错,如果像这个情况,我们在一开始在代码中埋下以下 Hook:
「收到注册表单」
「收到登录表单」
「注册失败」
「登录失败」
那么我们只需要去处理这些 Hook 就行,丝毫不用去改动原本的代码,而且,如果我们有一天不需要某个功能,直接删除那个功能的模块代码就行。整个流程,我们的核心功能代码都没有发生过变动,如果其中一个无法使用,那我们停用掉那一个就好。
ThinkPHP的核心就是 Hook。Discuz 插件、WordPress 插件、Emlog 插件 核心都是 Hook。
举个例子:
钩子是编程里一个常见概念,非常的重要。它使得系统变得非常容易拓展,(而不用理解其内部的实现机理,这样可以减少很多工作量)。
钩子作用
钩子函数可以截获并处理其他应用程序的消息。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。
钩子实现
钩子的完整实现应该叫事件驱动。事件驱动分为两个阶段,第一个阶段是注册事件,目的是给未来可能发生的“事件”起一个名字,简单的实现方法是用单例模式产生一个持久的对象或者注册一个全局变量,然后将事件名称,以及该事件对应的类与方法插入全局变量即可。也就是挂载一个钩子。
第二个阶段是触发事件,本质上就是在事件的全局变量中查询要触发的事件名称,然后找到注册好的类与方法,实例化并运行。这样子就可以摆脱传统方式中程序必须按顺序的规则,进一步实现解除耦合的目的。
<?php
/**
* 定义钩子
*/
class Hook
{
private $hooklist = null;
//添加
public function add($people)
{
$this->hooklist[] = new $people;
}
//触发事件
public function exec()
{
foreach ($this->hooklist as $people)
{
$people->act();
}
}
}
/** 钩子实现
*/
class man
{
public function act()
{
echo 'this is man <br>';
}
}
class WoMen
{
public function act()
{
echo 'this is women <br>';
}
}
class child
{
public function act()
{
echo 'this is a child <br>';
}
}
/**注册事件
*/
class Ball
{
public function __construct()
{
$this->hook=new Hook();
}
public function down()
{
echo 'ball is downing <br>';
//添加,去掉钩子
$this->hook->add('man');
//$this->hook->add('woMen');
$this->hook->add('child');
}
public function dothing()
{
$this->hook->exec();
}
}
$ball = new Ball();
$ball->down();
$ball->dothing();
来源:https://blog.csdn.net/qq_32421489/article/details/128655989
猜你喜欢
- if rs.bof then 表示:当前指针的位置是在第一行记录之前 if rs.eof then 表示:当前指针的位置是在最后一行记录之后
- Mysql分页采用limt关键字select * from t_order limit 5,10; #返回第6-15行数据select *
- 鼠标经过超链时的提示图层源码运行代码框<script>var oPopup = window.createPopup();fun
- 1.客户端的主页面:<%@LANGUAGE="VBSCRIPT" CODEPAGE="936"
- 最近对 Range 和 Selection 比较感兴趣。基本非 IE 的浏览器都支持 DOM Level2 中的 Range,而 IE 中仅
- YAHOO.util.Subscriber 与 YAHOO.util.CustomEvent。1. YAHOO
- ROW_NUMBER() OVER (PARTITION BY COL1 ORDER BY COL2) 表示根据COL1分组,在分组内部根据
- 107条javascript(js)常用的方法技巧,十分的实用,相信看了下面的这些js编程技巧和方法,能够给javascript初学者解决很
- 此文章主要向大家讲述的是SQL Server数据库的分布式数据库系统的实际目标,通俗的讲就是研制分布式数据库系统的目的、动机,其中主要包括的
- 分页程序sub show_page参数说明:total_records 总记录数everypage_records 每页显示条数
- 我们知道,一般的关系数据库(如SQL Server、Oracle、Access等)中的查询操作是支持集合操作的,例如可以用“Update A
- 我们开发数据库应用时,常常需要用到模糊查询。如果同一个条件需要匹配很多字段怎么办呢?通常,程序员会每个字段都在SQL中“field like
- 1.获取function形参个数functionName.length2.较适用的运算符delete:删除以前定义的对象属性或方法的引用vo
- 1.尽量不要对列名进行函数处理。而是针对后面的值进行处理例如where col1 = -5的效率比where -col1=5的效率要高因为后
- 之前就见过很多网站在侧边栏上使用<dl />标签对来完成侧边栏栏目的布局,最近在研究DEDECMS的默认模板时,也发现该模板在大
- 当您使用FILESYSTEMOBJECT(fso)对象获得某个目录下的文件列表的时候,你有没有发现无法控制它们的排序方式,比如按照名字排序,
- MySQL数据库线程缓冲池的相关知识是本文我们主要要介绍的内容,MySQL数据库支持线程缓存,在多线程连接模式下,如果连接断开后,将这个线程
- 问:SQL Server应该怎样访问Sybase数据库的表?答:具体方法如下:1: 安装Sybase客户端版本的要求:Sybase Clie
- 在java中一个hashCode算法,可以用来计算一个字符串的hash值,今天一个朋友突然问俺能不能在js中计算hashCode,要求和ja
- 为满足用户的视觉追求及产品的背景图片的换肤功能,设计师难免在设计上会用到半透明的效果。因此页面重构师基于视觉及产品的需要,采用了PNG32的