过滤器和钩子如何在PHP中真正起作用


21

过滤器和挂钩实际上如何在WordPress中工作?

我在问一些高级的东西。如何在PHP中实现?例如,它如何收集来自不同插件的所有钩子并将它们“附加”到核心钩子等。


2
据我所知,php中没有“钩子”或“过滤器”,有功能。WordPress具有一些特殊功能,在执行之前,它们会使用其他功能的回调。
Ofir Baruch


3
@OfirBaruch,我很确定OP指的是它们在WordPress中的实现,而不是在暗示它有一些本机PHP实现。
汤姆·奥格

Answers:


33

总览

基本上,召唤过滤器和挂钩的“ 插件API ”由以下功能组成:

  1. apply_filters()- 执行
  2. do_action- 执行
  3. apply_filters_ref_array()- 执行
  4. do_action_ref_array()- 执行
  5. add_filter()- 添加到堆栈
  6. add_action()- 添加到堆栈

基本内幕

总体而言,涉及几个全局变量(在WordPress世界中还有其他情况):

global $wp_filter, $wp_actions, $wp_current_filter, $merged_filters;

第一个$wp_filter是全局变量Array,将所有过滤器名称保留为子数组。然后,这些子数组中的每个子数组都包含更多的子数组,这些子数组是在优先级数组下召唤的回调。

简要深入

因此,当执行函数被调用时,WordPress会在全局数组中搜索具有该名称的键。然后,附加的回调将在优先级之后获得优先级。唯一发生在前面的是附加到all过滤器的回调。

当您使用add_action或添加回调时add_filter,WordPress首先会计算一个“唯一” ID,以不覆盖已附加的回调。

$idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority);

然后将您的回调添加到global $wp_filter堆栈中:

$wp_filter[ $tag ][ $priority ][ $idx ] = array(
    'function'      => $function_to_add,
    'accepted_args' => $accepted_args
);

如您所见,主子数组是$tag(或动作/过滤器名称),然后在特定优先级下召集所有内容,然后将“唯一”回调/ ID字符串用作键。

稍后,当调用过滤器时-发生在$tag/ action- / filter-name时,将搜索数组并调用回调。在使用时call_user_func_array,附加多少参数并不重要。WordPress会自行解决。

foreach ( (array) current( $wp_filter[ $tag ] ) as $the_ )
{
    call_user_func_array(
        $the_['function'], 
        array_slice(
            $args, 
            0, 
            (int) $the_['accepted_args']
        )
    );
}

3
不要忘记,因为它经历了回调,它下令在同一个钩)多个回调使用他们的“优先级”,这是设置(可选)与ADD_ACTION()和apply_filters(和默认值的执行,以10
汤姆Auger 2013年

1
@TomAuger请随时在答案中添加任何其他注释和修改。
kaiser

5

包含在WordPress核心文件和某些父主题文件中。它们使您可以将内容挂接到文件中特定位置。

一个示例是WordPress中的wp_head挂钩。您可以在子主题中使用此钩子在该位置添加内容”

例:

add_action('wp_head', 'add_content_to_head');
function add_content_to_head() {
echo 'Your Content';
}

一些高级主题还包括动作挂钩,您可以在子主题中使用该动作挂钩执行相同的操作。这是一个可视化地图,其中包括所有动作挂钩及其在Genesis主题框架中输出内容的位置。

例:

add_action('genesis_header', 'add_content_to_header');
function add_content_to_header() {
echo 'Your Content';
}

如果在Genesis主题框架中打开header.php文件,则此钩子的外观如下:

do_action( 'genesis_header' );

这是可以以多种方式使用的WordPress挂钩列表

筛选器使您能够修改现有功能的输出,并且包含在WordPress核心文件和某些父主题框架(如Genesis)中。

这是可以与Genesis Design Framework一起使用的过滤器列表

这是WordPress中包含过滤器的列表

这是一个示例,说明如何在诸如Genesis之类的主题框架中使用过滤器:

add_filter( 'comment_author_says_text', 'custom_comment_author_says_text' );
function custom_comment_author_says_text() {
return 'author says';
}

上面的代码可用于子主题中,以修改作者在您的评论中说的文字。它适用于任何主题。

这是另一个将摘录的长度自定义为50个单词的示例:

add_filter( 'excerpt_length', 'change_excerpt_length' );
function change_excerpt_length($length) {
return 50; 
}

您将在wp-includes / post-template.php文件中找到the_excerpt()函数

看起来是这样的:

  function the_excerpt() {
        echo apply_filters('the_excerpt', get_the_excerpt());
}

您还可以在插件中使用挂钩和过滤器来做完全相同的事情,并且在更新父主题或WordPress时代码不会丢失。

基本上,钩子和筛选器使您可以自定义和修改WordPress及其父主题,而无需编辑核心WordPress文件或父主题文件。

当父主题框架包含挂钩和过滤器时,自定义子主题非常容易,因为您无需编辑父主题模板文件。这样,您也可以安全地更改主题。


2
这是对钩子和过滤器的全面概述,但是恐怕完全会错过OP的问题,即关于钩子如何工作以及WordPress如何创建,存储和处理钩子的内部信息。好答案;您可能应该链接到WP网站上的教程。
汤姆·奥格

好的,我将其删除。我的坏处是我应该更好地阅读该问题,但是认为如果初学者知道基本知识,那么已经给出的答案将使他们更容易理解。
布拉德·道尔顿

2
布拉德,我未删除它,因为我认为在此也有该信息可能很有用。如果您不同意,请在此处提及/联系我,然后我将其删除。
kaiser 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.