What's the difference between hooks, filters and actions?

时间:2017-05-05 作者:cjbj

看起来钩子、过滤器和动作这三个术语可以互换使用。他们之间有什么区别?他们是做什么的?如何使用它们?

1 个回复
最合适的回答,由SO网友:cjbj 整理而成

Hooks 是的集合名称filtersactions. 两者都是为了改变函数的正常行为。从编程角度来说,没有什么大的区别,正如您从以下事实中所看到的in the WP source code 添加操作与添加筛选器相同。

区别在于用法。您可以使用操作来完全更改函数的行为或向现有函数添加某些内容。您可以使用过滤器更改函数或变量的结果。读一点more on the theory here.

Example

假设这是您的主题模板文件index.php:

$me = \'I love Star Wars\';
$you = \'I love Star Trek\';
$me = apply_filters (\'do_force\', $me);
$you = apply_filters (\'do_force\', $you);
do_action (\'echo_me_you\', $me, $you);
然后在functions.php 对于主题或插件的主php文件,可以定义过滤器和操作。例如:

add_filter (\'do_force\',\'wpse_do_force\');
function wpse_do_force ($string) {
  str_replace (\'Trek\',\'Wars\', $string); // change all occurences of \'Trek \' to \'Wars\'
  return $string;
  }
过滤器不影响$me, 但它确实改变了$you, 因为它在字符串中搜索“Trek”并将其更改为“Wars”。所以,在应用过滤器之后,我们都喜欢《星球大战》。

现在,代码转到操作。这可能非常简单:

add_action (\'echo_me_you\', \'wpse_echo_neutral\');
function wpse_echo_neutral ($me, $you) {
  echo $me;
  echo $you;
  }
但是你可以随心所欲地采取行动。例如,您可以通过将所有发生的“战争”更改回“Trek”,使过滤器无效:

add_action (\'echo_me_you\', \'wpse_echo_trek\');
function wpse_echo_trek ($me, $you) {
  str_replace (\'Wars\',\'Trek\', $me);
  str_replace (\'Wars\',\'Trek\', $you);
  echo $me;
  echo $you;
  }

How does this function?

当WordPress开始组装页面时,它会读取functions.php 第一它在那里收集您添加的所有操作和过滤器。它将这些放在队列中。然后,当它发现do_actionapply_filters 它获取相应的队列,并按照找到它们的顺序逐个执行操作/过滤器。

因此,在上面的示例中,定义了一个在过滤器上触发的函数do_force 定义了两个在操作上触发的函数echo_me_you. 首先,它将过滤器应用于$me, 然后应用过滤器$you, 然后执行函数wpse_echo_neutral 最后wpse_echo_trek.

Priorities

加载(子)主题后,插件(和父主题)也会加载。它们还添加了操作和过滤器。所以filter you have written for the_title 可能看起来不起作用,因为该过滤器被插件中的另一个过滤器覆盖。这就是优先权派上用场的地方。

优先级允许您确定筛选器/操作在队列中的位置。因此,如果您对此进行定义:

add_filter (\'the_title\', \'wpse_the_title\', 999, 2);
优先级999应确保此筛选器作为队列中的最后一个筛选器执行(数字2是传递给筛选器/操作的参数量)。

It doesn\'t work!

是的,这种情况经常发生,或者看起来是这样。从上面的示例中可以看到,如果您有一个操作否决了过滤器,那么您可以对过滤器执行任何操作,而不会产生任何效果。您的子/父和插件的设置可能非常复杂,您必须仔细调试。

第一步是包括以下内容echo \'GOT HERE\' 作为你职能的第一行。这将告诉您是否调用了过滤器/操作。如果不是这样的话,你就太晚了。看看你的functions.php:

add_action (\'wp_footer\',\'wpse_footer\');
function wpse_footer() {
  add_action (\'wp_head\', \'wpse_head\');
  }
function wpse_head() {
  echo \'GOT HERE\';
  }
这行不通,因为do_action (wp_head) 已由WP在遇到do_action (wp_footer). 因此,如果您向wp_head 此时排队,则没有效果。始终查看hook order 向本机WordPress挂钩添加操作时。一个常见的错误是试图将小部件中的脚本/样式文件排队。正如你从钩子顺序中所看到的,dynamic_sidebar, 小部件连接到WordPress页面的位置,在wp_enqueue_scripts.

可能根本无法执行筛选/操作还有其他原因。例如,因为WP在某些情况下跳过过滤器。在这里,您别无选择,只能深入研究源代码(或在WPSE上询问)。

第二步,一旦确定调用了过滤器,就要将其更改为非常高的优先级,以确保它不会被否决。此外,禁用所有插件以排除干扰。

第三步,如果您的函数被调用并且排除了干扰,但它仍然不起作用,那么这可能与您自己的编码技能有关。检查拼写错误、回显中间结果等,找出错误的地方。

Wrapping up

hooks系统是一个功能强大但有时令人困惑的系统,可以修改WordPress本身或插件/主题的行为。因为每个人都在使用流行的钩子,所以结果可能出乎意料。然而,大多数问题都可以通过仔细查看挂钩顺序和优先级来解决。

相关推荐

apply_filters to $GLOBALS

我正在使用Pootle页面构建插件构建一个单页网站。使用get\\u page,我在1页上显示每个单独的页面。为了针对Pootle页面生成器内容,我使用以下代码:$content = $GLOBALS[\'Pootle_Page_Builder_Render_Layout\']->panels_render( $page_data->ID ); 当我尝试实现一个像旋转木马这样的插件时,我需要使用一个短代码,但短代码不起作用。为了使短代码有效,我需要使用apply_filters(\'