Hook机制里登场的角色
稍有接触过 WordPress 主题或插件制作修改的朋友,对 WordPress 的Hook机制应该不陌生,但通常刚接触WordPress Hook 的新手,对其运作原理可能会有点混乱或模糊。本文针对 WordPress Hook 运作大致做个简单的说明,而预设读者是理解基本的 PHP function 语法及运作,但对 WordPress Hook 机制不是很明白。

Hook机制里登场的角色
先从“登场角色”的个别说明开始:
WordPress核心
指的是 WordPress 内建的程式码架构,提供 WordPress 主要的基本功能。
Hook
也许你早已听说,Hook 本身虽是钩子的意思,但直译又有点奇怪,所以一般通常都不直译它,而是直接称它 Hook 。WordPress 的 Hook 也可以想像成“钩子”,这些“钩子”会埋在 WordPress 网站中特定几处的程式码中,埋进去时使用的语法,其“标示位置”的意义比较大,没有实质运作的内容。当程式执行到有埋 Hook 的地方时,它会找出所有对应到自己的 Hook Function (也就是所有“钩到”该 Hook 的 hook function),并一一执行。
因此若没有针对此 Hook 去“加入”要钩上去的 Hook Function,执行到此什么也不会做。因此,它等于是WordPress核心预留一个执行的机会给未来想要加入定制功能的开发者。
Hook Function
Hook Function 里会有实质运作的内容,即是实作了一些定制功能,可能是存取 DB、增加 HTML code、执行其他函式等等。我们在 Hook Function 里写好所需的功能后,就可以利用“加入至对应 Hook”的语法,把 Hook Function自已钩到该 Hook 上,使得该 Hook 被执行到时,也会连带执行自己。
Hook机制是如何运作的?
举个例子,我们拿 wp_head 及 wp_footer 这两个内建的hook来说明,wp_head 这个 hook 就是用来埋在负责输出标签的程式码中,而 wp_footer 就是用来埋在输出页尾的程式码中 (定义于 wp-includes/general-template.php,用 wp_head() 及 wp_footer() 包装起来)。这两个 hook,主要都是在布景档案中使用的,常见会出现在 header.php 及 footer.php 中。
请看下面的情境示例图,我们把 wp_head 及 wp_footer 看成是”钩子“,而别的 hook functions 就能来鈎住它:

我们马上来写一个简单的例子。我们要写一个 hook function,就叫它 print_sth(),然後把它钩上 wp_head 这个hook。因为 wp_head() 的内容实际上就只有 do_action( 'wp_head' ); 这一行内容,而 wp_footer() 的内容也只有 do_action('wp_footer');所以我们直接把 do_action 的语法换到图上去,比较容易做说明,因此示意图变成:

如此,只要执行到输出 header.php 时,就会执行到 wp_head(),就如同执行到 do_action( 'wp_head' ); 此时WP核心会去找所有”钩上”wp_head 这个 hook 的 hook function,於是就找到我们写的 print_sth() ,然後就执行它,所以结果它做的事就会出现在网站上,也完成了”定制”的动作:

简单的说,Hook 机制就是:WP 核心或其他插件、主题 提供想定制功能的人一个置入定制程式码(Hook Function)到特定的执行时间点(Hook)的机会。
WordPress的Action Hook与Filter Hook
WordPress中的 Hook 有两种,分别是”Action Hook“及”Filter Hook“,我们刚才举例的 wp_head 及wp_footer 都是属於 Action Hook。不过,一开始你可以先把这两种 Hook 看成是一样的东西,只是 Filter 多了一点点不同的特色,接着说明。
Action Hook
WP核心 (或主题、插件)在做它们该做的事时,如果执行到有埋 action hook 的程式码 (即是 do_action 语法) 时,会去找寻对应到的 hook functions,进而执行这些 hook functions(即那些透过 add_action() 来加入的 hook functions),藉此完成定制功能。WP核心并不期待 Action Hook functions 会有回传值,所以这里的 hook function 只被视为一个”独立切出来运作的功能“。
WP核心做它该做的事,你做你想做的事,做完就各自结束。
Filter Hook
跟 Action Hook 一样,WP核心 (或主题、插件)在做它们该做的事时,如果执行到有埋 filter hook 的程式码 (即是apply_filters语法) 时,就会去找寻对应的 hook functions ,进而执行这些 hook functions(即那些透过add_filter() 来加入的 hook functions ),藉此完成定制功能。与 Action Hook 不同之处是,所有”鈎上“ Filter Hook 的 hook functions 通常都会接收到参数,而WP核心会期待你拿到它提供的参数,并做完你想做的事后,要回传(return)一个值,让WP核心再利用你回传的值来接着完成它该做的事。
透过你的干涉,修改了WP核心丢给你的参数,WP核心再接着拿你改过的参数,继续完成它该做的事,此动作就像”过滤“的动作,因而得名 filter。
比较Action Hook与Filter Hook的操作语法
比较一下两种 Hook 在埋进某处程式码时所用的语法,假设我们在某处 (可能是在输出页首的程式码处,或输出文章标题、文章内容、侧边栏…等地方,要”出现定制效果“的地方)埋下这两种 hook:
/*--------------- Action Hook ---------------*/
// 埋下一个名叫'do_more'的action hook
do_action('do_more');/*--------------- Filter Hook ---------------*/
// 埋下一个名叫'get_special'的filter hook,注意它会有回传值
$c = apply_filters('get_special',$a, $b);
然后我们可以在某处 (可能是其他插件、functions.php 等处,要”实现定制功能“的地方)添加对应的 hook function:
/*--------------- Action Hook Function---------------*/
// 增加要钩上'do_more'这个hook的hook function,
// 并为此hook function取名叫more_func。
// 第一个参数是hook名称、第二个是hook function名称
add_action('do_more', 'more_func');// 添加more_func的內容,不需回传值
function more_func()
{echo 'do more thing...';
}
/*--------------- Filter Hook Function ---------------*/
// 增加要钩上'get_special' hook的hook function,
//并为此hook function取名叫special_func。
// 参数1是hook名称、参数2是hook function名称
// 参数3是Priority(优先序)、参数4是hook function参数的数目
add_filter('get_special', 'special_func', 10, 2);// 添加special_func的內容,需要給它回传值
function special_func($a, $b)
{$c = $a.' & '.$b; //做一些事,例如把两个参数连接起來
return $c; //回传值
}
所以其实两种 Hook 的运作方式几乎一样,只差在增加 Action Hook 函式不需回传值,而增加 Filter Hook function时,你必须要回传一个值。所以 Filter Hook 函式通常都有提供参数,让想定制的人可以取得它,处理后再回传。
但如果有一个 Filter Hook,它没有任何 hook function 有去钩它,它该怎么取得回传值?答案是,直接拿第一个它给的参数,以上面的例子来说,它会直接拿 $a 丢进 $c 。另外,其实我们也可以把 filter 写的跟 action 一样,只要不回传值就行,但 action hook 就没办法”模仿“ filter hook,因为无法取得回传值。
Hook Function的优先序(Priority)
如果有很多地方(主题或者插件的 functions.php)都 添加同一个 hook ,会怎么决定出现顺序?答案很显然是可以透过 Hook Function 的 Priority 参数来作优先序的设定:
就像我们刚才说明的例子中,我们使用 add_filter 加入 special_func 时设定的优先序是 10 ,这也是 Priority 参数的预设值。如果你希望它能优先被执行,就设定小于 10 的数字,反之,就设个 100、500 之类的,让它延后被执行。
但其实这里有个隐含的冲突问题。
以 wp_head 这个 hook 为例,如果我写了一个插件,希望透过 wp_head 来输出”增加 a.css 档案“的 HTML 语法,而 a.css 会重新设定 body 元素的样式,所以我希望它可以最后才被汇入,不要被其他 css 档干扰,于是我将 Priority 设为 900,但我怎么知道 Priority 900 够不够大?若某个WP网站,它除了安装我的插件,也安装了其他插件,而其他插件刚好也重新设定body元素的样式,然后把 Priority 设为 950,此时我写的插件在处理 body 样式时就出事了,于是就跟其他插件冲突了。
所以此时我们需要了解的是:我的WP网站可能装了很多插件,我怎么知道同一个 Hook 被加了多少 Hook Function,而每个 Hook Function 的 Priority 被设定为多少?
答案是,我们可以透过 $wp_filters 这个 global 变数来取得所有 hook 的信息,像是如下的 function:
// 列出所有的hook function及其priority
function list_hooked_functions($tag=false)
{global $wp_filter;
if ($tag)
{$hook[$tag]=$wp_filter[$tag];
if (!is_array($hook[$tag]))
{trigger_error("Nothing found for '$tag' hook", E_USER_WARNING);return;
}
}
else
{$hook=$wp_filter;
ksort($hook);
}
echo '<pre>';
foreach($hook as $tag => $priority)
{echo "<br />>>>>>\t<strong>$tag</strong><br />";
ksort($priority);
foreach($priority as $priority => $function)
{echo $priority;
foreach($function as $name => $properties) echo "\t$name<br />";
}
}
echo '</pre>';
return;
}
当我们呼叫 list_hooked_functions('wp_head'); 时,就会列出 wp_head 这个 Hook 所钩住的所有 hook function,可以看到 priority 10 之后有好几个都没有数字,因为它们都没有特别指定 priority,所以都是 10 ,包括我们刚才写的 print_sth 也在其中:
>>>>> wp_head
1 wp_enqueue_scripts
2 feed_links
3 feed_links_extra
8 wp_print_styles
9 wp_print_head_scripts
10 rsd_link
wlwmanifest_link
index_rel_link
parent_post_rel_link
start_post_rel_link
adjacent_posts_rel_link_wp_head
locale_stylesheet
wp_generator
rel_canonical
wp_shortlink_wp_head
print_sth
wp_admin_bar_header
_admin_bar_bump_cb
所以,冲突很难提早避免,但发生冲突时,可以预先思考有没有可能是因为 priority 的设定,导致结果跟预期不符合。
原文出自:http://www.mrmu.com.tw/2011/10/10/wordpress-hook/ ,倡萌整编。
Hook机制里登场的角色的更多相关文章
- 黄聪:WordPress 的 Hook 机制与原理(add_action、add_filter)
稍有接触过 WordPress 主题或插件制作修改的朋友,对 WordPress 的Hook机制应该不陌生,但通常刚接触WordPress Hook 的新手,对其运作原理可能会有点混乱或模糊.本文针对 ...
- Android插件化原理解析——Hook机制之动态代理
转自 http://weishu.me/2016/01/28/understand-plugin-framework-proxy-hook/ 使用代理机制进行API Hook进而达到方法增强是框架的常 ...
- Libco Hook 机制浅析
Libco Hook 机制浅析 之前的文章里我们提到过 Libco 有一套 Hook 机制,可以通过协程的让出(yield)原语将系统的阻塞系统调用改造为非阻塞的,这篇文章我们将深入解析 Hook 机 ...
- 【repost】JS中的hook机制
hook机制也就是钩子机制,由表驱动实现,常用来处理多种特殊情况的处理.我们预定义了一些钩子,在常用的代码逻辑中去适配一些特殊的事件,这样可以让我们少些很多if else语句.举个高考加分的例子,比如 ...
- 插件开发之360 DroidPlugin源码分析(二)Hook机制
转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52124397 前言:新插件的开发,可以说是为插件开发者带来了福音,虽然还很多坑要填补, ...
- PostgreSQL的hook机制初步学习
磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面:PostgreSQL内部结构与源代码研究索引页 回到顶级页面:PostgreSQL索引页 本文的目的一是为了备忘,二是为了抛砖引玉,希望 ...
- 浅谈svn的hook机制
一.什么是钩子 所谓svn的hook机制,就是用户在管理数据仓库的时候,当特定的事件发生时,相应的hook会被调用,hook 其实就相当于特定事件的处理函数. 当前 Subversion 提供了5种可 ...
- Nova中的Hook机制
Nova的代码中支持Hook机制,也就是在某些函数的前后,可以加入自己的代码逻辑.Hook代码可以完全独立于Nova开发,本质上使用setuptools的entry points机制.K版本的Open ...
- thinkphp5 自动注册Hook机制钩子扩展
Hook.php 文件已更新1.修复在linux环境下类的 \ 在basename 下无法获取到类名的问题2.修复linux 环境下无法使用hook::call 调用失败问题 请先安装thinkphp ...
随机推荐
- html特殊字符
平时写代码很少用到HTML的特殊字符,最常用的可能是 了,但有时在移动端为了节省时间,可能会用这些字符实现某种特殊效果,现整理如下: 使用方法: 这些字符属于unicode字符集,所以,你的文档需要声 ...
- 计蒜客A
联想公司最近要设计一个体现公司文化的 logo.联想的设计师想出了一个方案:先画了一个顶点 O,接着画出以顶点 O 为公共顶点的.夹角为 θ的两条线段 l1 和 l2 其中 l1作为圆 C1的 ...
- 【皇甫】☀IOC和AOP的拓展实例
<!--构造器注入 --> <bean id="user1" class="cn.happy.entity.User"> <con ...
- MapReduce 简介
2. MapReduce 简介 MapReduce 实际上是分为两个过程 map 过程 : 数据的读取 reduce 过程 : 数据的计算 并行计算是一个非常复杂的过程, mapreduce是一个并行 ...
- [原创]Android Lollipop (5.0) 原生代码 Settings 首页加载逻辑分析
主入口为com.android.settings.Settings. 这只是一个wrapper的类, 它继承于 SettingsActivity类,并且声明了一堆公有的继承于SettingsActiv ...
- 【转】Android各大发布市场
前言 如果只有一个或者少许的两三个Android市场,本文也没用存在的必要性,本文谨献给同在Android奋战的同仁. 声明 欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnbl ...
- Xcode 7 PCH宏文件的配置和使用---学会使用宏定义
使用宏的目的是什么? 由于实际开发中,有时候一些设置信息需要重复使用(例如设置打印信息.配置颜色.配置宽度等),如果每次都手动去敲每次都去创建会很麻烦.虽然宏使用的时候会占用内存,可是目前来说大部分开 ...
- 报表控件NCreport教程:子查询系统设计
数据报表中经常需要用到主从数据关系,比如发票.订单等一类的特殊文件,在报表控件NCreport中也不例外.数据报表至少有一个表头和一个通过 主键和外键关联的相关细节数据集.子查询系统则是通过父数据源驱 ...
- 数据采集实践学习二(C#)
前一篇文章写到我获取数据的方式不是通过分析HTML获得,而是通过分析请求链接,然后模拟请求方法获取数据,这只是一种方法.而且是在我通过分析HTML获取不到的情况下,曲线救国,参考别人文章实现的.很高兴 ...
- 2015/10 中外合璧再现辉煌—CCFC2015技术峰会
笔者有幸参加了CCFC技术峰会,现在发布照片几张.大家看一下. 2015年10月14日,CCFC 2015电子数据取证技术峰会于四川成都举办,有200余名一线取证技术人员及国内外各行业专家参会.此次峰 ...