黄聪:WordPress动作钩子函数add_action()、do_action()源码解析
WordPress常用两种钩子,过滤钩子和动作钩子。过滤钩子相关函数及源码分析在上篇文章中完成,本篇主要分析动作钩子源码。
然而,在了解了动作钩子的源码后你会发现,动作钩子核心代码竟然跟过滤钩子差不多!是的,至此,我不得不告诉你,动作钩子只是WP开发者为了区分概念而把过滤钩子另外命名的一种东西!当然,它们还是有一些细微的差别,下面我们将从源码来深入解读。
动作钩子概念:动作钩子是WP代码执行到某处或某个事件发生时触发的一系列函数,插件可以利用动作钩子API在WP代码执行的特定点之前插入一系列函数以控制执行。它跟过滤钩子极像,唯一不同的是过滤钩子返回一个处理后的值,而动作钩子仅完成函数执行并不返回值,如果钩子不存在则返回NULL并新增该钩子。
动作钩子原理:由于动作钩子和过滤钩子几乎一样,所以它们的实现原理也是一样的。它主要利用一个全局变量$wp_filter,增加动作函数时使用add_action()函数给全局变量$wp_filter增加了一个数组元素,这个元素键名中含有钩子名,值中含有对应函数及执行优先级等信息,在调用do_action()函数使用动作钩子时,它通过循环查找出所有跟钩子关联的函数并将其依次调用,最后返回处理后的数据。
动作钩子使用步骤:
由于PHP代码会经过Zend等引擎翻译,代码中步骤的先后顺序并不重要,所以以下步骤仅为便于理解钩子原理的伪步骤,不具有实际参考意义!
1、创建钩子(可省略):使用do_action()函数可以创建一个没有挂载函数的钩子,挂载函数可以通过add_action()添加,最后再使用do_action()调用执行;
2、创建动作函数:它可以有传入参数也可以无传入参数,其他与创建普通函数没有任何区别,函数的作用为完成某项动作;
3、挂载函数:即使用add_action()将函数挂载到指定钩子上;
4、执行动作钩子:使用do_action()可以依次执行挂载在指定钩子上的所有函数以完成指定任务;
动作钩子函数详解:
在看动作钩子函数作用、参数说明等时,你会发现几乎是跟过滤钩子重复的。至于为什么会这样,那就要看源码了,我保证,看完源码后你会感慨自己被WP开发者涮了!
1、add_action($tag,$function_to_add,$priority = 10,$accepted_args = 1)
add_action()作用:该函数用于给指定的动作钩子$tag添加指定的挂载函数$function_to_add,同时它可以确定挂载函数执行优先级及其可接收参数个数;
add_action()参数说明:
$tag为钩子名;
$function_to_add为挂载函数名;
可选参数$priority为该挂载函数执行的优先级,默认为10,该数字越小则越早执行,数字相同则按其添加到钩子上的顺序执行,越早添加越早执行;
可选参数$accepted_args确定挂载函数接收的参数个数,默认为1;
add_action()源码分析:
function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
return add_filter($tag, $function_to_add, $priority, $accepted_args);
}
怎么样,看到了吧!被坑了有木有!add_action()函数的代码竟然是调用一次add_filter()!这尼玛完全是一个人的大名和小名的问题有木有!
2、do_action($tag, $arg = '')
do_action()作用:该函数调用挂载在过滤钩子$tag上的所有函数以完全特定的任务;
do_action()参数说明:
$tag为钩子名;
$arg为动作钩子上挂载函数的传入参数,默认为空;
do_action()源码分析:
function do_action($tag, $arg = '') {
global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
if ( ! isset($wp_actions) )
$wp_actions = array();
# 如果$wp_actions变量未设置过,则将其定义为数组;
if ( ! isset($wp_actions[$tag]) )
$wp_actions[$tag] = 1;
else
++$wp_actions[$tag];
# 如果$wp_actions[$tag]未设置则将其赋值为1,否则将其值加1;
if ( isset($wp_filter['all']) ) {
$wp_current_filter[] = $tag;
$all_args = func_get_args();
_wp_call_all_hook($all_args);
}
# 跟apply_filters()中的all钩子处理方式完全一样!_wp_call_all_hook()源码分析见上篇文章过滤钩子源码解析;
if ( !isset($wp_filter[$tag]) ) {
if ( isset($wp_filter['all']) )
array_pop($wp_current_filter);
return;
}
# 当前钩子不存在,则直接返回,不再执行以后代码;
if ( !isset($wp_filter['all']) )
$wp_current_filter[] = $tag;
# 将当前钩子设置为$tag;
$args = array();
if ( is_array($arg) && 1 == count($arg) && isset($arg[0]) && is_object($arg[0]) )
$args[] =& $arg[0];
else
$args[] = $arg;
# do_action()若有传入参数,且为一个数组,该数组仅此一个元素,该元素有值则将$args值设置为引用$arg[0],否则直接赋值;
for ( $a = 2; $a < func_num_args(); $a++ )
$args[] = func_get_arg($a);
# 通过for循环,若do_action()有不只一个传入参数,将这些值赋给数组$args;
if ( !isset( $merged_filters[ $tag ] ) ) {
ksort($wp_filter[$tag]);
$merged_filters[ $tag ] = true;
}
# 跟apply_filter()函数排序代码完全一样!详解见上文;
reset( $wp_filter[ $tag ] );
do {
foreach ( (array) current($wp_filter[$tag]) as $the_ )
if ( !is_null($the_['function']) )
call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
} while ( next($wp_filter[$tag]) !== false );
array_pop($wp_current_filter);
}
# 除了少了一行return $value其他跟apply_filters()完全一样!
看过动作钩子的源码,是不是惊呼,原来这丫就是过滤钩子换了个名儿而已!
黄聪:WordPress动作钩子函数add_action()、do_action()源码解析的更多相关文章
- QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数
QT源码解析(一) QT创建窗口程序.消息循环和WinMain函数 分类: QT2009-10-28 13:33 17695人阅读 评论(13) 收藏 举报 qtapplicationwindowse ...
- Generator函数执行器-co函数库源码解析
一.co函数是什么 co 函数库是著名程序员 TJ Holowaychuk 于2013年6月发布的一个小工具,用于 Generator 函数的自动执行.短小精悍只有短短200余行,就可以免去手动编写G ...
- Vue源码解析:AST语法树转render函数
开始 今天要说的代码全在codegen文件夹中,在说实现原理前,还是先看个简单的例子! <div class="container"> <span>{{ms ...
- wordpress源码解析-目录结构-文件调用关系(1)
学习开源代码,是一种很快的提升自己的学习方法.Wordpress作为一个开源的博客系统,非常优秀,应用广泛,使用起来简单方便,具有丰富的主题和插件,可以按照自己的需求来任意的进行修改.所以就从word ...
- JavaScipt 源码解析 回调函数
函数是第一类对象,这是javascript中的一个重要的概念,意味着函数可以像对象一样按照第一类管理被使用,所以在javascript中的函数: 能"存储"在变量中,能作为函数的实 ...
- jQuery 源码解析(八) 异步队列模块 Callbacks 回调函数详解
异步队列用于实现异步任务和回调函数的解耦,为ajax模块.队列模块.ready事件提供基础功能,包含三个部分:Query.Callbacks(flags).jQuery.Deferred(funct) ...
- 【SMB源码解析系列】——001.JumpEngine函数
在SMB的源码中大概有不到20处看起来很奇怪的指令,它的格式是通过jsr指令调用一个名为JumpEngine的函数,其后并不是跟随某些后续的逻辑指令,而是通过.dw定义了一系列16位地址. 我们可以看 ...
- 黄聪:wordpress源码解析-数据库表结构(转)
如果是一个普通的用户,不需要了解wordpress数据库的结构.但是,如果你正在写一个插件,你应该会对wordpress如何处理它的数据和关系感兴趣.如果你已经尝试使用已经存在的wordpress a ...
- 黄聪:wordpress源码解析-目录结构-文件调用关系(转)
Wordpress是一个单入口的文件,所有的前端处理都必须经过index.php,这是通过修改web服务器的rewrite规则来实现的.这种做法的好处是显而易见的,这样URL更好看,不必为每一个url ...
随机推荐
- 来一场说走就走的骑行---23KM的上班探路行动圆满结束
上午带着宝贝在游乐场疯了2小时,回家吃过中午饭,收拾利落,刚上刚拾掇利落的单车,出发,目的地:公司.预测距离22.5KM目的 1 锻炼身体,变每天上下班的娱乐时间为锻炼时间. 2 省钱(其 ...
- 1-3-2 Windows应用程序常用消息
主要内容:介绍Windows编程中常用的消息 1.WM_LBUTTONDOWN产生单击鼠标左键的消息 lParam: 低字节包含当前光标的X坐标值 X = LOWORD(lParam); 高字节包含当 ...
- URAL 1227 Rally Championship(树的直径)(无向图判环)
1227. Rally Championship Time limit: 1.0 secondMemory limit: 64 MB A high-level international rally ...
- 【HAOI2006】【BZOJ1051】【p1233】最受欢迎的牛
BZOJ难得的水题(其实是HA太弱了) 原题: 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这 种关系是具有传递性的,如果A认为B受欢迎,B ...
- 科普:浅谈 Hellinger Distance
浅谈 Hellinger Distance 2016.05.24 最近在看 Hellinger Distance(海林格距离), 平时看多了欧式距离,马氏距离等等,貌似介绍这个的材料不是很多,例如:维 ...
- linux 大并发下 内核优化
To support over 500k users, you *need* - A 64 bits hardware/kernel (AMD64, Opterons) - At least 8GB ...
- vsftp虚拟用户配置
找了很久,终于找到像样一点的文章,很详细,参数方面懂英文基本能看懂,一个教程是否有用,关键在于细节.错了一点点就不能配下去了. ------------------------------------ ...
- docker镜像、容器
第一部分:Docker镜像的基本知识 1.1 什么是Docker镜像 从整体的角度来讲,一个完整的Docker镜像可以支撑一个Docker容器的运行,在 Docker容器运行过程中主要提供文件系统视角 ...
- 纯CSS绘制三角形(各种角度)
我们的网页因为 CSS 而呈现千变万化的风格.这一看似简单的样式语言在使用中非常灵活,只要你发挥创意就能实现很多比人想象不到的效果.特别是随着 CSS3 的广泛使用,更多新奇的 CSS 作品涌现出来. ...
- unity, Animation crossfade需要两动画在时间上确实有交叠
unity现在播动画都用Animator了,但公司的老项用的还是Animation,今天遇到一个bug,是两个动画的衔接处不连贯. 最后发现是由于A动画已经播完之后B动画才开始播,而且还用了cross ...