Wordpress解析系列之PHP编写hook钩子原理简单实例
Wordpress作为全球应用最广泛的个人博客建站工具,有很多的技术架构值得我们学习推敲。其中,最著名最经典的编码技术架构就是采用了hook的机制。
hook翻译成中文是钩子的意思,单独看这个词我们难以理解这个hook机制(即钩子机制)是什么意思。那么笔者就用大白话以通俗易懂方式给大家讲解一下什么是hook机制,以及用原生PHP函数编写实现简单实例。
大白话解释:以Wordpress为例,它的hook机制就是在网页加载时一起加载了很多hook变量,也就是钩子变量,这些变量作用是绑定相关的函数,只要hook变量被加载,Wordpress就会用一个内置通用API函数解析出hook变量包含的函数并执行。好理解吧,一句话就说清楚了hook机制,但是实现并不简单,最关键的就是那个内置API函数解析hook变量。后面笔者先不给大家掰Wordpress源码的hook解析过程了,那个太复杂,考虑的方面很多,学习理解起来比较困难。这里我们采用更简单直接的解说方式,利用原生PHP函数编写个简单的hook机制plugin插件管理类,和大家一起更加直观的理解钩子机制的原理过程。
下面代码的基本过程是:PluginManager内部有hook键值数组_listener()。
1、plugin注册到PluginManager类的包含hook键值的监听数组_listener()中,
2、PluginManager类实例对象调用trigger函数实现加载所有plugin插件并执行功能方法。
具体过程详见如下代码注释分析:
<?php // 已注册插件管理核心类
class PluginManager
{
/**
* 监听数组,保存所有已注册插件的类私有的核心数组变量,数组的键名是钩子名,值是对应的插件信息
* @var array private $_listeners
*/
private $_listeners = array();
/**
* 默认构造函数的作用是通过get_active_plugins()读取plugins目录下所有已激活插件信息
* 同时初始化这些插件,注册到核心类PluginManager数组变量$_listeners中
*
* @var array $plugins
* @return void
*/
public function __construct()
{
//这里$plugins数组包含我们获取已激活的所有插件信息,通过get_active_plugins()函数获取具体信息
$plugins = array();
$plugins = $this->get_active_plugins(); if(is_array($plugins) && !empty($plugins) && count($plugins) > 0)
{
foreach($plugins as $plugin)
{
// 约定每个插件类的名字为如下格式,例如DemoActions;
$class = $plugin['name'].'Actions';
if(class_exists($class))
{
//初始实例化已激活插件,$this代表PluginManager实例为参数
new $class($this);
}
}
}
} /**
* 注册需要监听插件的功能方法绑定到hook钩子,并把hook钩子加入到$_listeners数组
*
* @param string $hook 钩子变量,就是数组的键名,每个钩子可以绑定多个plugin插件类
* @param object $plugin 插件变量,get_class($plugin)获取插件对应的类
* @param string $method 插件$plugin类对应的功能方法
*/
function register($hook, $plugin, $method)
{
//获取插件实现的功能方法
$key = get_class($plugin).'->'.$method;
//echo $key.'<br>'; //这里可以测试$key的值是否是实例方法引用;
//将插件的实例对象和功能方法保存入对应键值为hook名的监听数组中
$this->_listeners[$hook][$key] = array($plugin, $method);
} /**
* 返回已激活的所有插件名称和路径,读取plugins目录下所有已激活插件信息
*
* @return array() $plugins 返回数组包含每组插件$name:插件名称,也是php文件名;$directory:插件所在路径
*/
function get_active_plugins()
{
$dir = dirname(__FILE__).DIRECTORY_SEPARATOR.'plugins';
$filesnames = scandir($dir);
$plugins = array();
foreach($filesnames as $filename)
{
if($filename!='.' &&$filename!='..')
{
$plugins[] = array(
'name' => strstr($filename,'.', true),
'directory'=>$dir);
}
}
return $plugins;
} /**
* 触发一个钩子名称下所有的插件自定义功能方法
*
* @param string $hook 钩子的名称
* @param mixed $data 输入钩子内对应插件自定义方法的参数,默认为空
* @return mixed
*/
function trigger($hook, $data='')
{
//查看要实现的钩子,是否在监听数组之中
if (isset($this->_listeners[$hook]) && is_array($this->_listeners[$hook]) && count($this->_listeners[$hook]) > 0)
{
// 循环调用hook钩子所有插件功能方法
foreach ($this->_listeners[$hook] as $listener)
{
// 取出插件实例对象类名
$class = $listener[0];
// 取出插件实例对象自定义的功能方法
$method = $listener[1];
if(method_exists($class,$method))
{
// 动态调用hook钩子下所有插件的功能方法,这里$data为可无的方法参数
$class->$method($data);
}
}
}
} }
下面的是插件类DemoActions,其解析函数内包含对pluginManager对象的引用,对应的插件文件是Demo.php,该插件自定义功能方法为sayHello()。
// 插件类,约定必须包含固定格式解析函数
class DemoActions
{
/**
* 解析函数的参数是pluginManager类的引用实例
* 函数调用pluginManager实例的register方法注册这个插件
*/
function __construct(&$pluginManager)
{
/* hookdemo参数是钩子的名称
* $this是Demo_actions类的实例
* say_hello参数是此插件的功能方法
*/
$pluginManager->register('hookdemo', $this, 'sayHello');
} // 这里是自定义的插件功能方法
function sayHello()
{
echo '<br>Hello World<br>';
}
}
实际使用的时候,编辑如下代码程序:
//实际应用程序
$pluginManager = new PluginManager; //插件管理类实例化对象
$pluginManager->trigger('hookdemo',''); //启动绑定到hookdemo钩子的所有插件功能;
至此,我们就完整的实现了hook钩子绑定插件信息及如何利用hook钩子执行插件自定义功能方法的原理。Wordpress的hook钩子原理与此类似,理解了上面的代码,再逐步深入理解Wordpress源码的钩子机制就会更加如鱼得水。
Wordpress解析系列之PHP编写hook钩子原理简单实例的更多相关文章
- WordPress 插件机制的简单用法和原理(Hook 钩子)
WordPress 的插件机制实际上只的就是这个 Hook 了,它中文被翻译成钩子,允许你参与 WordPress 核心的运行,是一个非常棒的东西,下面我们来详细了解一下它. PS:本文只是简单的总结 ...
- 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新
本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...
- ETL利器Kettle实战应用解析系列一【Kettle使用介绍】
本系列文章主要索引如下: 一.ETL利器Kettle实战应用解析系列一[Kettle使用介绍] 二.ETL利器Kettle实战应用解析系列二 [应用场景和实战DEMO下载] 三.ETL利器Kettle ...
- C# Hook钩子实例代码之截取键盘输入,需要的朋友可以参考下
一.关于本文 以最通俗的语言说明钩子的使用方法,具体到钩子的详细介绍可以参照下面的网址: http://www.microsoft.com/china/community/program/origin ...
- {Django基础十之Form和ModelForm组件}一 Form介绍 二 Form常用字段和插件 三 From所有内置字段 四 字段校验 五 Hook钩子方法 六 进阶补充 七 ModelForm
Django基础十之Form和ModelForm组件 本节目录 一 Form介绍 二 Form常用字段和插件 三 From所有内置字段 四 字段校验 五 Hook钩子方法 六 进阶补充 七 Model ...
- Android源码解析系列
转载请标明出处:一片枫叶的专栏 知乎上看了一篇非常不错的博文:有没有必要阅读Android源码 看完之后痛定思过,平时所学往往是知其然然不知其所以然,所以为了更好的深入Android体系,决定学习an ...
- 【转】Hook钩子C#实例
[转]Hook钩子C#实例 转过来的文章,出处已经不知道了,但只这篇步骤比较清晰,就贴出来了. 一.写在最前 本文的内容只想以最通俗的语言说明钩子的使用方法,具体到钩子的详细介绍可以参照下面的网址: ...
- HOOK钩子教程
[转载]HOOK钩子教程 http://blog.sina.com.cn/s/blog_675049f701019ka9.html(原贴) 先留着,好好学一学! 原文地址:HOOK钩子教程作者:X_T ...
- Kotlin协程解析系列(上):协程调度与挂起
vivo 互联网客户端团队- Ruan Wen 本文是Kotlin协程解析系列文章的开篇,主要介绍Kotlin协程的创建.协程调度与协程挂起相关的内容 一.协程引入 Kotlin 中引入 Corout ...
随机推荐
- grid栅格布局
前面的话 Grid布局方式借鉴了平面装帧设计中的格线系统,将格线运用在屏幕上,而不再是单一的静态页面,可以称之为真正的栅格.本文将详细介绍grid布局 引入 对于Web开发者来说,网页布局一直是个比较 ...
- Jquery DataTables 使用AJAX POST的问题
最近项目在用需要用表格,听说DataTables很好很强大,于是用了一下. Get请求没什么问题,问题处在POST请求上 Jquery原生的POST请求没有问题,代码如下 $.ajax({ url ...
- hibernate sql查询转换成VO返回list
hibernate sql查询转换成VO @Override public List<FenxiVo> getTuanDuiFenxiList(FenxiVo FenxiVo,Intege ...
- C++函数重载实现的原理以及为什么在C++中使用用C语言编译的函数时,要在函数名称前面加上extern "C"声明
C++相对于C语言而言支持函数重载是其极大的一个特点,相信在使用C语言的时候大家如果要写一个实现两个整型数据相加的函数还要写一个浮点型数据相加的函数,那么这两个函数的名字绝对不可以一样,这样无疑在我们 ...
- MOF编译器无法连接VMI服务器。原因可能是语义错误的解决方案
安装数据库时报错. 我这个是因为安装SQL SERVER时,没有卸载vs. 一般解决方法: WIN 7安装VS和SQL SERVER的顺序应该是先安装SQL SERVER 然后安装VS,当要重装SQL ...
- winform利用委托delegate进行窗体间通信
前段时间学习委托,感觉很模糊的样子,也做过许多实例,但是项目中一直没有用到,今天在项目中遇到一个很简单的例子,现在拿出来,做一个简单的记录. 要求:将弹出框里勾选的内容返回到主面板上. 工具:委托. ...
- 网络编程学习笔记(三)UDP
1.不可靠的.效率高.数据报(数据打成一个小包一个小包地往外发).非连接. 2.UDP是非连接的,因此严格来说并不区分服务器端和客户端. 3.UDP通信过程:UDP都是通过字节数组进行对话的. ...
- jquery 变量和原生js变量的关系
其实js 变量和 jquery没什么不一样, 也可以直接 var hhhh=$("header"); 但是当用到用到hhh时依然要用jquery 的方式,而不能js原生的方式.
- webpack3中文版使用参考文档--全面解析webpack.config.js
Webpack目前官方发布的最新版本是3.1.0,相对于2.0的怎么本,在语法上没有变动,只是新增了功能.使用webpack,需要事先安装node.js,并对node.js生态有一些基本的了解,比如( ...
- twemproxyMemcache协议解析探索——剖析twemproxy代码正编补充
memcache是一种和redis类似的高速缓存服务器,但是memcache只提供键值对这种简单的存储方式,相对于redis支持的存储方式多样化,memcache就比较简单了.memcache通过tc ...