昊天SEO

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)

作用:该函数用于给指定的动作钩子$tag添加指定的挂载函数$function_to_add,同时它可以确定挂载函数执行优先级及其可接收参数个数;

参数说明

$tag 为钩子名;

$function_to_add 为挂载函数名;

可选参数 $priority 为该挂载函数执行的优先级,默认为10,该数字越小则越早执行,数字相同则按其添加到钩子上的顺序执行,越早添加越早执行;

可选参数 $accepted_args 确定挂载函数接收的参数个数,默认为1;

源码

  1. function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
  2. return add_filter($tag, $function_to_add, $priority, $accepted_args);
  3. }

怎么样,看到了吧!被坑了有木有!add_action() 函数的代码竟然是调用一次 add_filter()!这尼玛完全是一个人的大名和小名的问题有木有!

2. do_action($tag, $arg = ”)

作用:该函数调用挂载在过滤钩子$tag上的所有函数以完全特定的任务;

参数说明:

$tag 为钩子名;

$arg 为动作钩子上挂载函数的传入参数,默认为空;

源码

  1. function do_action($tag, $arg = ) {
  2. global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
  3. if ( ! isset($wp_actions) )
  4. $wp_actions = array();
  5. # 如果$wp_actions变量未设置过,则将其定义为数组;
  6. if ( ! isset($wp_actions[$tag]) )
  7. $wp_actions[$tag] = 1;
  8. else
  9. ++$wp_actions[$tag];
  10. # 如果$wp_actions[$tag]未设置则将其赋值为1,否则将其值加1;
  11. if ( isset($wp_filter[‘all’]) ) {
  12. $wp_current_filter[] = $tag;
  13. $all_args = func_get_args();
  14. _wp_call_all_hook($all_args);
  15. }
  16. # 跟apply_filters()中的all钩子处理方式完全一样!_wp_call_all_hook()源码分析见上篇文章过滤钩子源码解析;
  17. if ( !isset($wp_filter[$tag]) ) {
  18. if ( isset($wp_filter[‘all’]) )
  19. array_pop($wp_current_filter);
  20. return;
  21. }
  22. # 当前钩子不存在,则直接返回,不再执行以后代码;
  23. if ( !isset($wp_filter[‘all’]) )
  24. $wp_current_filter[] = $tag;
  25. # 将当前钩子设置为$tag;
  26. $args = array();
  27. if ( is_array($arg) && 1 == count($arg) && isset($arg[0]) && is_object($arg[0]) )
  28. $args[] =& $arg[0];
  29. else
  30. $args[] = $arg;
  31. # do_action()若有传入参数,且为一个数组,该数组仅此一个元素,该元素有值则将$args值设置为引用$arg[0],否则直接赋值;
  32. for ( $a = 2; $a < func_num_args(); $a++ )
  33. $args[] = func_get_arg($a);
  34. # 通过for循环,若do_action()有不只一个传入参数,将这些值赋给数组$args;
  35. if ( !isset( $merged_filters[ $tag ] ) ) {
  36. ksort($wp_filter[$tag]);
  37. $merged_filters[ $tag ] = true;
  38. }
  39. # 跟apply_filter()函数排序代码完全一样!详解见上文;
  40. reset( $wp_filter[ $tag ] );
  41. do {
  42. foreach ( (array) current($wp_filter[$tag]) as $the_ )
  43. if ( !is_null($the_[‘function’]) )
  44. call_user_func_array($the_[‘function’], array_slice($args, 0, (int) $the_[‘accepted_args’]));
  45. } while ( next($wp_filter[$tag]) !== false );
  46. array_pop($wp_current_filter);
  47. }
  48. # 除了少了一行return $value其他跟apply_filters()完全一样!

看过动作钩子的源码,是不是惊呼,原来这丫就是过滤钩子换了个名儿而已!

未经允许不得转载:新乡seo|网站优化,网站建设—昊天博客 » WordPress 动作钩子函数 add_action()、do_action() 源码解析

网站的维护离不开大家的支持鼓励,捐赠让我更有动力走的更远&& 也可以关注我的微信公众号,发布更多的干货
本文网址:https://www.168seo.cn/jianzhan/wordpress/advance-wordpress-tutorial/1742.html

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址